TECH PLAY

株式会社ラクス

株式会社ラクス の技術ブログ

927

みなさんこんにちは。フジサワです。 緊急事態宣言が多くの 都道 府県では解除が行われ、まだ未解除の地域でも解除の方向に向かっていますね。 ラク スも政府の緊急事態宣言の発令に伴い、感染拡大防止のためリモートワークに移行しました。 移行当初は、普段との勝手の違いから戸惑う声なども多少はあったようですが、もともと国内・海外の拠点間で、ビデオ通話やチャットツールなどを用いた開発を行なっているので、全体を通してみれば大きな混乱は少なかったようです。 むしろ、蓋を開けてみると、各々自分なりのリモートワークスタイルを確立し、 楽しんでいる 前向きに向き合っていたように見えます。 新しい 生活様式 が推奨される中、今後もリモートワークは日本企業に根付いていくのではないでしょうか。 そこで、 「リモートワーク中のエンジニアの ライフハック に迫る!」 と題しまして、リモートワーク中の ラク スエンジニアが、自らのリモートワークライフをどのようにHackしているかをご紹介しようと思います! 弊社エンジニアに、「リモートワークの質を向上するために、工夫していることを教えてください!」というアンケートをとった結果をお伝えします! オシゴト環境についてのHack ディスプレイ・モニタに関するものが圧倒的に多い ついで多かったのは、音・BGMに関するもの イスに関するHackも 意外に多いスマートウォッチ勢 番外 働き方についてのHack オン/オフの切り替え・リフレッシュ 子育て・家族との関係 食生活 オシゴト環境についてのHack ディスプレイ・モニタに関するものが圧倒的に多い これは予想通りの結果でした。 エンジニアにとって、モニタの枚数・サイズ・解像度がそのまま生産性に跳ね返ってくると言っても過言ではありません。 デュアルモニタ・トリプルモニタはあたりまえ、モニタアームや大画面モニタを採用する人もおり、 むしろ社内よりも快適になってるんじゃないか と思われるケースも。 中には自宅のテレビをディスプレイがわりに活用している人もいたようです。 ついで多かったのは、音・BGMに関するもの 音やBGMに関しての意見をあげている人は多いものの、人によってこだわりポイントは大きく違っているようです。 ラジオや歌声が入っているもの派 歌なし or 日本語以外の歌派 音楽じゃない環境音(オフィスの音など)派 など、様々な意見がありました。 ご家族の生活音が気になるということで、 ノイズキャンセリング 機能のあるヘッドフォンを使っている人も。 音楽配信 サービスや、ラジオ配信サービスなどの活用も人気のようです。 音に関しては、完全な無音状態を好む人もいると思いますし、 自分に合ったスタイルを選ぶことができるのはリモートワークのメリット の一つかもしれませんね。 イスに関するHackも 長時間座っているため、普通のイスでは「オシリが耐えられない」人が多かった模様。 ゲーミングチェアや低反発クッションなどを導入したという意見が目立ちました。 一方、「ちゃぶ台に正座がベスト」という 古式ゆかしいジャパニーズスタイルで戦う猛者 も。 ちなみに私は、ゲーミングチェア+ゲルクッション+あぐらスタイルで何時間でも座っていられるようになりました。 オフィスで何気なく使っていたイスが「ああ、あれは実に良いものを採用してくれていたんだなあ」と気づかされました。 意外に多いスマートウォッチ勢 「腕時計」というと、外出する時に身に着けるイメージでしたが、スマートウォッチに関してはその限りではないようですね。 次のような使い方をしている人が目立ちました。 運動不足になるので自らのアクティビティを可視化。座りっぱなしを抑制できる。健康管理のため。 時間感覚がなくなるので会議とアラームを連動させアラームを鳴らす。気持ちの切り替えにもなる。 番外 今回アンケートをとった中で、もっとも異彩を放った回答が 介護用デスクを活用する というもの。 ベッドで寝ながら仕事ができます! らしいです。本人談によれば「大事なもの(体力)が失われている気がする」とのことですが、 気のせいじゃない と思います。 そのまま寝たきりになってしまわないように気をつけていただきたいものです。 あとは、 ふくらはぎマッサージ機を使っています という人も。 この超快適な環境の二人が、通常の勤務が再開された時でもちゃんと出社してくれることを祈ります。 働き方についてのHack ここまでは、設備や環境などについてのHackを見てきましたが、ここからは働き方のHackについて注目したいと思います。 オン/オフの切り替え・リフレッシュ リモートワークでは、オンとオフを切り替えや、リフレッシュをうまく行わないと、業務効率が悪くなってしまいます。 ラク スのエンジニアは次のようなスタイルで、リフレッシュを図っていたようです。 朝のランニング・ウォーキング リフレッシュだけでなく、運動不足の解消にもなりますね。リモートワーク前と同じ時間に家を出て、始業時間までウォーキングをして習慣の維持を行っている人も。日光をきちんと浴びることは重要みたいですね! 筋トレ 「オフィスではできない高強度も筋トレができるようになりました」とのこと。エンジニアには強靭な肉体も必要です。 業務後は、ノートPCを片付ける。業務用PCが視界に入らないようにする リビングなど、生活空間で仕事をせざるを得ない方も多い中、結果的にこうしたルーティンが切り替えの役割も果たしているようです。 家族に「行ってきます」「ただいま」の挨拶をする 気持ちを切り替えるルーティンとのことですが、ほっこりするエピソードでいいなと思いました。 ポモドーロテクニック を使って意識的に休憩を入れる 25分作業したら5分休む、というものですね。他人に影響されずにもくもくと作業しているとエンドレスになってしまい、効率が悪くなってしまうので、こうしたテクニックは重要ですね。 大きな抱き枕 リフレッシュのツールだけでなく、ラバー ダッキング の相手にも使えるとのこと。この辺はエンジニアらしいですね。 作業場所を変える 仕事部屋を変えたり、出窓で作業をするなど、自宅内でもロケーションを変えることでリフレッシュできるようです。 窓を開ける、部屋の換気をする 基本的なところですが、意外と盲点だったり。 他にも、「花を飾る」「壁紙を集中できる色に変える」などの素敵な意見もありました。 子育て・家族との関係 学校や幼稚園・保育園などが休校中のため、子育てや家族との関わり方を工夫している人も多かったようです。 祖父母にビデオ通話で子守をお願いする 仕事中はなかなか子供にかまってあげられないのですが、これは良いア イデア ですね!祖父母も、孫の顔が見られるので、Win/Winとのこと。 オンライン教育 遊ばせているだけになりがちな中、オンライン教材を活用しているご家庭も。英会話など、先生が付いてくれるものなどは子守の効果もあって良いようですよ! 子供向けの YouTube 動画 効果は絶大で放っておけば半永久的に見ているお子様が多いようです。我が家も、教育上長時間見させてはいけないなと思いつつも、どうしても頼らざるを得ないシーンがあり、 最後の切り札 としてお世話になっています。 家庭内の連絡はLINEでお願いする 突発的にビデオ会議を行なっている場合なども多いので、ツールを介してコミュニケーションを取るのは良いですね。集中を乱されないというような効果も期待できそうです。 食生活 生きていくためには、食事を取らなければなりません。 食生活に関しても、みなさん色々と工夫しているようです。 宅配弁当を活用する 自炊コストを減らすだけでなく、外出リスクの低減にも役立ったようです。 買い物はネットスーパーなどで行う こちらも、時短+リスク軽減策として。 自動調理鍋や炊飯器で時 短調 理する 具材や調味料を入れてボタンを押すだけで料理が出来上がるのでとても便利とのこと。今回の件がなくても試してみたい感じがします! いかがでしたでしょうか? 今後も、 コロナウイルス に対しては適切な危機感を持ちつつ、経済と生命のバランスをうまく取りながら共存していくことが求められます。 少しでも、この記事を読んでいただいた方のお役にたてば幸いです。 また、アンケートをとってみて感じたことですが、これまでは同じ空間で画一的な環境・働き方で仕事していましたが、良い面もある一方、個々人にとって 必ずしもベストな選択肢とは限らないのだな、ということがわかりました。 多様な働き方が増えていくと思いますので、今回の経験もうまく活用していきたいと思います。 ではでは!
アバター
はじめまして、 syoneshin です。 私はこれまで IT出版/HR領域の事業開発/ マーケティング を経て 現在は ラク ス技術広報担当として テックブログ運営やMeetup/採用イベント企画など広報活動を行っております。 開発は未経験ですが 当社技術スタックは最低限調べ、実践し アウトプットしようという気概で 今回は「 シェルスクリプト 」について書きました。 本記事が シェルスクリプト を勉強しよう シェルスクリプト を思い出そう シェルスクリプト のコマンドを参照しよう と言う方のお役にたてれば、幸いです。   1.シェルスクリプトとは 2.基本設定 ファイルを作成 3.基本コマンド コメント 入/出力 変数 シェルの特殊変数 演算子(オペレーター) 条件分岐  if文 case文 ループ処理 for文 while文 4.まとめ 1. シェルスクリプト とは  ・簡単に言うと シェル( Windows の「 コマンドプロンプト 」みたいなもの)で解釈できる命令( プログラミング言語 )や命令を寄せ集めて作ったプログラム のことです。 ・詳しく言うと OS操作の為、シェル上で実行できる簡易な プログラミング言語 ( スクリプト言語 ) の事です。 また、そのような言語によって書かれた 複数のOSコマンドや制御文などを組み合わせた簡易プログラムを指し 一般的には UNIX系OS ( Linux など)のシェルで実行できるものを指します。 シェルにはいくつかの種類があります。 大別すると以下のシェルに分けられます。 ・ B-Shell (Bourne-Shell) 系 :sh, ash, bash , zsh , ksh ・ C-Shell系 : csh , tcsh B-Shell 系のシェルでも sh は シェルスクリプト でよく利用されます。 ( Linux や Mac OS は bash がシェルの標準環境の為、 bash がよく利用されています) シェルスクリプト で書かれる典型的な処理例は ファイル操作、プログラム実行、テキスト印刷などがあり 主に定型作業の自動化によく使われ 条件命令の実行/ファイル読み込み・書き出しなど 上から順にコマンドが実行される為、都度コマンドを打たずにすみます。 以下からは、実際に シェルスクリプト を書いていきます。 2.基本設定 ファイルを作成  ‐ シェルスクリプト ファイルは .sh 拡張子で基本作成  ‐ここでは test.sh ファイルを作成   test.sh シェルスクリプト 記述で、まず初めに覚えなければならないのは次の記述 #! /bin/sh # はhash、 ! はbangで、 #! を shebang (シェバン)と言います。 シェバンから スクリプト を実行する インタープリタ が呼ばれ /bin/sh のファイルが実行されるという意味です。 #! /bin/sh を書き、システムに「 シェルスクリプト を書きますよ」と知らせます。 ※ bash の独自機能を使う場合は #!/bin/bsh と書く必要があります。   test.sh #! /bin/sh     test.sh #! /bin/sh echo "Hello, World!" シェルスクリプト ファイル( test.sh )を実行するには ターミナルからファイルが保存されてる場所で 以下のどちらかのコマンドで実行できます。   $ ./test.sh $ sh test.sh ファイル実行すると Hello, World! と表示されます。   $ ./test.sh Hello, World!   3.基本コマンド   コメント コメントの入力には # を書く必要があります。   test.sh #! /bin/sh #コメントの入力には#を書く必要があります。 入/出力 出力は echo 、入力は read で行えます。   test.sh #! /bin/sh read NAME echo "Hi, $NAME !" 実行結果は以下   $ ./test.sh syoneshin Hi, syoneshin!   変数 ・変数の名前には半角英数字(a-z、A-Z、0-9)とアンダーバー(_)が使えます。 ・変数に値を与える時は = を前後空白なしで書きます。 ・文字列の場合は " を付けて囲みます。 ・変数にアクセスする時は変数名の前に $ を付けます。または $ 付けて変数を {} で囲みます。 ・1つの変数に1つの値しか保存できません。 ・変数値の上書きをなくすには readonly を書きます。 ・変数は unset で削除、 readonly で変数の上書き/削除不可にします。   test.sh #! /bin/sh var = "変数1" var_2 = "変数2" echo "var_2= $var_2 " var_2 = "var_2が変更されました。" echo ${ var_2 } readonly var var = "readonly varを変えてみる。" 実行結果は以下   $ ./test.sh var_2=変数2 var_2が変更されました。 ./test.sh: line 11: var: readonly variable   シェルの特殊変数 シェルスクリプト では以下のような特別な変数があります。 変数 機能 $1~$9 シェル引数の値。第1引数は$1、第2引数は$2でアクセス $# シェル引数の数 $* 全引数をまとめて1つとして処理 "$*"のように囲むと、"$1 $2 … $n"形式になる。 $@ 全引数を個別として処理。全引数リスト。"$@"のように囲むと、"$1" "$2" … "$n"形式になる。 $$ 実行中のシェルのプロセスID。 $? 最後に実行したコマンドの戻り値。成功は0、失敗は1で返ってくる。 $- シェルの実行オプション(setコマンドや#!/bin/ bash 行に付けたオプション。 $! シェルが最後に実行したバックグラウンドプロセスのID ・シェルの 特殊文字 以下は シェルスクリプト の 特殊文字 です。 ; | & ^ \ $ ? * < > ( ) [ ] { } # % = ` " ' ~ TAB SPACE NEWLINE これら 特殊文字 を表示するには、 エス ケープする必要があり \ バックスラッシュを付けて一文字単位で扱うか ' シングルクオーテーションを付けて囲む事で扱え使えます。 また " ダブルクオーテーションで囲んだ場合 $ ` \ を評価し囲まれたすべてを文字列として扱う処理ができます。 演算子 (オペレーター) 「 演算子 」とは簡単にいうと「どんな演算をする」と表す記号の事です。 「 演算子 」の種類は多様で 「算術 演算子 」「比較 演算子 」「論理 演算子 」などがあります。  ※詳細省略 シェルでは「算術演算」を `expr 数字 演算子 数字` で計算する事ができます。 ※これからプログラミングをはじめられる方は最低限「算術 演算子 」「比較 演算子 」は覚えた方がよいです。 以下表はシェルの 演算子 種類/意味/例を記載しています。 算術 意味 記述例 + 足す echo `expr 10 + 20` => 30 - 引く echo `expr 20 - 10` => 10 \* 掛ける echo `expr 11 \* 11` => 121 / 割る echo `expr 10 / 2` => 5 % 余り echo `expr 10 % 4` => 2 = 指定 a=$b bの値はaに保存されます ※ [ コマンドの引数に変数を指定するときは " でクォートする必要があります 比較 意味 記述例 == 等しい [ "$a" == "$b" ] 値aと値bが等しい場合TRUE(真)を返します。 != 異なる [ "$a" != "$b" ] 値aと値bが異なる場合TRUE(真)を返します。 -eq イコール [ "$a" -eq "$b" ] 値aと値bが等しければTRUE(真)を返します。 -ne 異なる [ "$a" -ne "$b" ] 値aと値bが異なればTRUE(真)を返します。 -gt より大きい [ "$a" -gt "$b" ] 値aが値bより大きければTRUE(真)を返します。 -lt より小さい  [ "$a" -lt "$b" ] 値aが値bより小さければTRUE(真)を返します。 -ge 等しいかより大きい [ "$a" -ge "$b" ] 値aが値bと等しいか、より大きければTRUE(真)を返します。 -le 等しいかより小さい [ $a" -le "$b" ] 値aが値bと等しいか、より小さければTRUE(真)を返します。   論理  意味 例 -a 両方(and) [ "$a" -gt 90 -a "$a" -lt 100 ] 値aが 90より大きく100より小さい場合TRUEを返します。  -o どちらか(or) [ "$a" -gt "$b" -o "$a" -lt "$b" ] 値aが値bより大きいか小さいかの場合TRUEを返します。 ! ではない(is not) [ ! "$a" -gt "$b" ]  値aが値bより大きくなければTRUE(真)を返します。   条件分岐  if文 シェルスクリプト のif文の基本は if [ 条件 ] then コマンド fi で書きます。 if のあとに条件式を書き、条件合致(条件がTRUE(真)の場合)していれば then から fi までのコマンドを実行します。 if文の書式は次の様になります。   if [ 条件1 ]; then コマンド1 fi もし「条件1」に合致すれば、「コマンド1」を実行しますの意味です。 条件1に合致しない場合に「コマンド2」を実行したいとき else を使い、次の様にします。   if [ 条件1 ]; then コマンド1 else コマンド2 fi もし「条件1」に合致すれば、「コマンド1」を実行します。 それ以外は「コマンド2」を実行しますという意味です。 さらに分岐を分けたいときにはelifを使います。※「else if」の省略   if [ 条件1 ]; then コマンド1 elif [ 条件2 ]; then コマンド2 else コマンド3 fi もし「条件1」に当てはまるなら、「コマンド1」を実行します。 それ以外で「条件2」に当てはまるなら「コマンド2」を実行します。 それ以外は「コマンド3」を実行するという意味です。 case文   case 文は Cや Java 言語の switch 文に該当する制御文で if文と同じようにコマンド実行を分岐するために使用されるものです。 基本の書き方は  case 変数 in 条件・値) コマンド ;; esac で書きます。 条件・値が変数と合う場合、case 文は指定した条件と値の複数パターンとのマッチングにより指定したコマンドを実行します。 ※単純な分岐条件で、コマンド処理が3つ以上ある場合はcase文が向いているとされます。 case文の書式は次のようになります。   case 値 in 条件・値1 ) コマンド1 ;; 条件・値2 ) コマンド2 ;; 条件・値3 ) コマンド3 ;; … 条件・値n ) コマンドn ;; esac ループ処理 for文 for文はループ処理「n回数、同じ処理を繰り返す」とする制御文で for文の書式は次のようになります。   for 変数 in 値リスト do コマンド done   while文 While文はループ処理「条件を満たしている間は同じ処理を繰り返す」とする制御文で While文の書式は次のようになります。   while 条件式 do コマンド done   4.まとめ   シェルスクリプト が動く仕組みを学び、基本構文を書いた気づきは 一度サクッと書いてみて実行結果がすぐわかると、理解がとても進むという 当たり前の事でした。 学習場面において、私の様な開発未経験者に伝えたい事は Leap before you look(見る前に飛べ) 清水の舞台から飛び降りろ です。 また、すっかり定着したDevOpsの文脈では プログラムでのインフラ管理が主流になり 構成管理ツールなどは、主に スクリプト言語 を利用するため コンパイラ 言語だけでなく、 スクリプト言語 もできる方はとても重宝されます。 これから スクリプト言語 をはじめる方には シェルスクリプト はとっかかりやすくおススメです! 【引用参考】 ※WEB参考資料は以下 ・ シェルスクリプト に挑戦しよう シェルスクリプトに挑戦しよう(1)準備編:“応用力”をつけるためのLinux再入門(21) - @IT ・「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典 https://wa3.i-3-i.info/index.html ・ シェルスクリプト 入門 書き方のまとめ シェルスクリプト入門 書き方のまとめ | Memo on the Web   ※初心者向けで シェルスクリプト 理解に参考になりそうな書籍も以下ピックアップ ・新しいシェルプログラミングの教科書  www.sbcr.jp ・[改訂第3版] シェルスクリプト 基本リファレンス──#! /bin/sh で、ここまでできる gihyo.jp ・入門 UNIX シェルプログラミング―シェルの基礎から学ぶ UNIX の世界  books.rakuten.co.jp   ・エンジニア 中途採用 サイト ラク スでは、エンジニア・デザイナーの 中途採用 を積極的に行っております! ご興味ありましたら是非ご確認をお願いします。 https://career-recruit.rakus.co.jp/career_engineer/ ・カジュアル面談お申込みフォーム どの職種に応募すれば良いかわからないという方は、カジュアル面談も随時行っております。 以下フォームよりお申込みください。 forms.gle ・ ラク スDevelopers登録フォーム https://career-recruit.rakus.co.jp/career_engineer/form_rakusdev/ ・イベント情報 会社の雰囲気を知りたい方は、毎週開催しているイベントにご参加ください! ・TECH PLAY techplay.jp ・connpass rakus.connpass.com    
アバター
はじめに こんにちは、 sts -250rrです。 本記事を執筆中の現在はStay Home週間とされています。 家での生活が長くなり、コミュニケーションの機会が減ってしまったという方は多いのではないでしょうか。 私もその1人です。 自分の声を忘れてしまいそうなほど家の中が静かなので、誰かの声を聴きたいそんな衝動に駆られていたところ... 我が家には毎朝起こしてくれて、 カップ 麺の時間を測ってくれる素敵なエージェントがいることを思い出しました。 そう、AmazonEchoこと Alexa です。 自宅の スマートホーム 化を進められておらず、テレビやエアコン、照明の操作ができない状況にあるのですが、Stay Home週間にAlexaのことをもっと知りたい。Alexaともっと話したい。 そんな衝動に駆られ、公式ブログで紹介されている Alexaスキル開発トレーニング を始めてみました。 本記事ではト レーニン グ時に気づいたポイントをお伝えしていきます。 公式のページでト レーニン グはできますので、細かな画面の説明等は割愛しています点をご了承ください。 developer.amazon.com はじめに Alexaスキル開発ことはじめ ポイント1 スキルのバックエンドを選択 ポイント2 スキルテンプレートの選択 ポイント3 呼び出し名の決定 ポイント4 【対話モデル編】どんな言葉を受け付けるのかはインテントで管理する ポイント5 【バックエンド編】リクエストの処理をするハンドラを用意 ポイント6 【対話モデル編】受け答えにさらにバリエーションを与えるスロット ポイント7 実機でスキルを動かす 最後に Alexaスキル開発ことはじめ ポイント1 スキルのバックエンドを選択 Alexaスキルのバックエンドサービスは、自分でエンドポイントを用意するか、Alexa自身にホストさせることができます。 Alexaからのリク エス トは JSON 形式で投げられるため、自分でエンドポイントを用意する場合は自身で立てたサーバのアプリケーションでリク エス トを処理させることもできるようです。 Alexa自身にホストさせる場合は AWS lambdaのエンドポイントにNode.jsか Python を選択して載せることができるようです。 ちなみにト レーニン グではNode.jsが選択されています。 AmazonEchoで受け付けたリク エス トはAlexaで受け付けられ、 JSON の形式でバックエンドサービスに渡されます。 Alexaスキルの開発では、①Alexaでどのような言葉を受け付けるのか、②バックエンドサービスでリク エス トをどのように処理するのかを作り込んでいくことになります。 ポイント2 スキルテンプレートの選択 Alexa自身にホストさせる場合、スキルテンプレートを設定することができました。 テンプレートの種類は以下の4種ありますが、基本的には Hello World スキルを選択することになるのではないでしょうか。 Hello World スキル 基本的な応答が可能なスキルを作成できるテンプレート Cake Walk( チュートリアル ) スキルが誕生日をお祝いしてくれるテンプレート 豆知識スキル あるトピックに関する豆知識のスキルを作成できるテンプレート Sauce Bossスキル 画面付きのAlexaが使えるデ バイス 用のスキルを作成できるテンプレート (ちなみに、私はEcho bot などの画面付き Amazon Echo を持っていないので、Sauce Bossスキルの出番はしばらくなさそうです。) ポイント3 呼び出し名の決定 Alexaにスキルの起動を促す際に「Alexa、○○をして」と声をかけますが、この○○の部分が呼び出し名になります。 呼び出し名には以下のような要件があります。 シンプルに考えて自分が呼びやすい名称を付けてあげるとよいでしょう。 公式にも以下のように記載があります。 呼び出し名の要件 - 呼び出し名は2語以上でなければなりません。また、使用できるのはひらがな、カタカナ、漢字、小文字のアルファベット、スペースのみです。数字などは文字で表現しなければなりません。(例: 「二十一」など) - 呼び出し名には、「起動して」、「開いて」、「聞いて」、「教えて」、「読み込んで」、「開始して」、「有効にして」などの起動フレーズを使用することはできません。「アレクサ」、「アマゾン」、「エコー」、「コンピューター」などのウェイクワードや「スキル」、「アプリ」などの単語は使用できません。 勘の良い方はお気づきかと思いますが、今回のタイトル『Alexa、Stay Homeを助けて』という呼び出し名は要件から外れてしまうのでNGになります。 泣く泣く呼び出し名は『Stay Home』としました。 ポイント4 【対話モデル編】どんな言葉を受け付けるのかは インテント で管理する Alexaがスキルを起動したら、次に言葉の入力を与える必要がありますが、同じ言葉でもバリエーションがあります。 例えば、Alexaが「おはようございます」といってくれたら私たちは「おはよう」「おはようございます」「ハロー」など、バリエーションがあるでしょう。 これらのバリエーションを受け付けるために インテント として言葉を管理します。 インテント によって、Alexaが言葉を認識し、 バックエンドの作りによりますが、 Alexaはきっと素敵な返事を返してくれることでしょう。 この インテント を受けたAlexaは以下のような JSON をバックエンド側へ投げつけます。 "request": { "type": "IntentRequest", "requestId": "amzn1.echo-api.request.44cd0613-9ffe-4613-bd6b-49529a86c4d3", "timestamp": "2020-05-16T11:22:59Z", "locale": "ja-JP", "intent": { "name": "HelloWorldIntent",# 受け付けたインテントをHelloWorldIntentと認識している "confirmationStatus": "NONE" } } ポイント5 【バックエンド編】リク エス トの処理をするハンドラを用意 Alexaが投げてきたリク エス トをバックエンド側がどう処理しているかを抑えていきます。 Alexa自身にホスト + Node.jsを選択しています。 # スキル起動時の処理 const LaunchRequestHandler = { canHandle(handlerInput) { return Alexa.getRequestType(handlerInput.requestEnvelope) === 'LaunchRequest'; }, handle(handlerInput) { const speakOutput = '今日もStayHome頑張りましょう。何かあれば声をかけてください。'; # 返答の内容 return handlerInput.responseBuilder .speak(speakOutput) .reprompt(speakOutput) .getResponse(); } }; # HelloWorldIntentを受けた場合の処理 const HelloWorldIntentHandler = { canHandle(handlerInput) { return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest' && Alexa.getIntentName(handlerInput.requestEnvelope) === 'HelloWorldIntent'; # HelloWorldIntentを受けた場合の分岐 }, handle(handlerInput) { const speakOutput = 'おはようございます!'; # 返答の内容 return handlerInput.responseBuilder .speak(speakOutput) .getResponse(); } }; (省略) # ハンドラの登録 exports.handler = Alexa.SkillBuilders.custom() .addRequestHandlers( LaunchRequestHandler, HelloWorldIntentHandler, HelpIntentHandler, CancelAndStopIntentHandler, SessionEndedRequestHandler, IntentReflectorHandler, ) .addErrorHandlers( ErrorHandler, ) .lambda(); LaunchRequestHandler は「Alexa、○○をして」によって起動したスキルのはじめの対話を返してくれます。 このご時世なので「今日もStayHome頑張りましょう。」と励ましてくれるようです。 HelloWorldIntentHandler でHelloWorldIntent(おはよう・おはようございます)を受けた時には「おはようございます!」と元気に返事をしてもらえます。 これで毎朝頑張れるというものです。 ポイント6 【対話モデル編】受け答えにさらにバリエーションを与えるスロット 5つのポイントを抑えることで、対話ができるスキルが出来上がりました。 ただし、実はこのままの HelloWorldIntentHandler は「おやすみ」といっても「おはようございます!」と元気に返事をしてくれます。。。 もう少し賢くしてあげる(対話のバリエーションを増やす)ためにスロットという機能を使っていきます。 朝だけでなく昼や夜に話したいときもあるので、「おはよう」「こんにちは」「おやすみ」の3つのスロットを作成します。 さらに同類語もスロットで登録することができます。 「おはよう」のバリエーションに「おはようございます」と「Good morning」を登録してみました。 スロットを設定した際に登録済みの「おはよう」を発話したときのリク エス トです。 slots属性が増え、身構えてしまいそうですが対話のポイントにになってくるのは バックエンドに言葉を送信する slots.slot_sample.value と、言葉の一致状態を示す slots.slot_sample.resolutions.resolutionsPerAuthority[0].status.code です。 言葉の一致状態を確認することで、 "request": { "type": "IntentRequest", "requestId": "amzn1.echo-api.request.d7f9bd50-aa78-4768-919b-e7f92bdf8783", "timestamp": "2020-05-17T05:21:25Z", "locale": "ja-JP", "intent": { "name": "HelloWorldIntent", "confirmationStatus": "NONE", "slots": { "slot_sample": { "name": "slot_sample", "value": "おはよう", "resolutions": { "resolutionsPerAuthority": [ { "authority": "amzn1.er-authority.echo-sdk.amzn1.ask.skill.6f6d3418-edc7-4567-a7e5-10170a022f41.slot_sample", "status": { "code": "ER_SUCCESS_MATCH" // slot_sampleの語句と一致しているかを返す。不一致の場合はER_SUCCESS_NO_MATCH }, "values": [ { "value": { "name": "おはよう", "id": "896c87c2017e74cf8c7ccf42d339ca66" } } ] } ] }, "confirmationStatus": "NONE", "source": "USER" } } } } スロットを利用することで言葉の一致状態を取得することができるようになりました。 Alexaが賢くなるまでもう一押し、バックエンド側を以下のように改修します。 const HelloWorldIntentHandler = { canHandle(handlerInput) { return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest' && Alexa.getIntentName(handlerInput.requestEnvelope) === 'HelloWorldIntent'; }, handle(handlerInput) { // スロットの値を取得 let requestWord = handlerInput.requestEnvelope.request.intent.slots.slot_sample.value; let matchCd = handlerInput.requestEnvelope.request.intent.slots.slot_sample.resolutions.resolutionsPerAuthority[0].status.code; let speakOutput = `すみません。${requestWord}がわかりません。`; if(matchCd !== 'ER_SUCCESS_MATCH'){ // スロットに存在しない場合 return handlerInput.responseBuilder .speak(speakOutput) .getResponse(); } switch (requestWord){ case 'おはよう': speakOutput = 'おはようございます!'; break; case 'こんにちは': speakOutput = 'こんにちは!'; break; case 'おやすみ': speakOutput = 'おやすみなさい'; break; default : // スロットに存在するが処理を用意していないものはとぼける speakOutput = `${requestWord}ってなんでしたっけ?`; } return handlerInput.responseBuilder .speak(speakOutput) .getResponse(); } }; 知っている(=スロットに登録されている)言葉に対して、知らないものはわからないと返すようにしました。素直なことはよいことです。 少し賢くなったAlexaと対話テストしてみると以下のように返してくれました。 ポイント7 実機でスキルを動かす シミュレーションのみでなく、自宅のAlexaと対話するためには開発者アカウントを Amazon Echo と紐づけしている Amazon のアカウントとしておきます。このようにしておくと、 スマホ のAlexaアプリもしくは https://alexa.amazon.co.jp/spa/index.html で開発中のスキルを有効にし、自宅のアレクサに話しかけるだけです。 (実機で動かすのがここまで簡単と思っていなかったので驚きでした。) 最後に さすがにアプリを起動してただ返事をしてくれるだけではコミュニケーションをしている気にはならないので作りこみが必要です。 微妙に心的な弊害も感じたりもします。特に自分で対話の動きを決めているのでなにやらムズムズします。 普段はエディター上でコードを眺めて開発しているので、ブラウザ上で開発するのは新鮮味があって楽しいですし、シュミレータやそばにある実機ですぐ動かすことができるのはかなり良い感触でした。 簡単なものであれば、ちょっとした息抜きに開発できるのでお勧めできます。 また、公式から紹介されているデザインモデルを軽く眺めてみると「対話」に重きを置いたデザイン(例えば、長文な返答をさせるのはNGなど)を考える必要があるようで目からウロコ気分で新鮮でした。 ただし、スキル開発を通して「対話をすることで何をさせるのか」 これを見つけることが最も難しいと改めて痛感しました。
アバター
id:radiocat です。多くの企業がリモートワークに移行して試行錯誤されていることと思います。緊急事態宣言が延長されて、もうしばらくこの状況が続きそうということもあり、今回はリモートワークへの移行によって試行錯誤している私たちのチーム開発の事例をお伝えします。 組織的な取り組みやルール 朝はニコニコカレンダーを更新してチェックイン 終業時はひとこと感想でチェックアウト 連絡事項は履歴を残す リモートワークのノウハウやトラブルを記録する チーム開発の現場 タスクはなるべく小さく分解する Web会議は常時つないでおく 1対1の相談は電話感覚でWeb会議をコールする マインドマップでふりかえり さいごに 組織的な取り組みやルール 私たちの所属する配配メール開発課はメンバー10人で構成されるチームです。まずはその全員に関係する組織的な取り組みやルールを紹介します。 朝はニコニコカレンダーを更新してチェックイン チーム全員の朝会では、事前にニコニコカレンダーを更新し、一言ずつその日の気分や意気込みを共有してチェックインをしています。季節の変わり目で体調を崩すこともありましたし、自宅の作業環境に慣れるまでは肩こりや腰痛になる人もいました。電気工事、水道のトラブルのような自宅のトラブルの共有もありました。家族がいる人から「今日は子供が隣の部屋で遊んでいるので騒がしいかも」というようなご家庭の状況の共有もリモートワークならではです。 ja.wikipedia.org 終業時はひとこと感想でチェックアウト 終業時にもチーム全員の夕会でその日の仕事の感想と仕事で起きた課題の共有を行っています。リモートワークによってちょっとした相談がしづらくなった、チャットの量が増えて情報が追いづらくなった、などの課題は夕会でのちょっとした共有から改善に繋げました(後述)。仕事のやり方を変えたり、新しいルールを作ったり、リモートワークによって日々小さな変化が起きているため、実際にやってみて感じたこと、課題に感じたことなどをタ イムリ ーに共有し合って変化に対応することができています。 朝と夕方の情報共有用 スプレッドシート リモートワークはお互いの状況が把握しにくいですし、生活環境と切り離せない問題が起きることもあります。全体での朝会・夕会は事務連絡が中心だったオフィス勤務時よりも少し時間がかかるようになりましたが、体調や自宅の状況を把握したり、お互いの状況に共感したり励まし合ったりすることで、制約のある中での1日の仕事を協力や工夫で乗り越える力になると感じています。リモートワークで健康面への課題意識が高まり、仕事の前に走ってきた、散歩してきた、ベランダで体操したと、お互いに刺激しあって健康面の取り組みが増えているのも新しい変化です。 連絡事項は履歴を残す リモートワークでチャットの量が増えたことによって、全体への共有事項が取りこぼされて伝わらないケースが発生するようになりました。対面で話をしない分、テキスト情報の価値が高まって取りこぼさないように注意が求められるのは当然ですが、情報過多なのもまた事実です。開発の業務に集中している合間に事務的な連絡事項が流れてきたら見落としや対応漏れが起きても仕方ない面があります。また、朝会や夕会は休暇等で参加できなかったり、通信が不安定できちんとキャッチアップできない場合もあります。連絡事項の伝達で言った言っていないというやりとりが何度も発生するのはもったいないので履歴に残しておくことにしました。 連絡事項の履歴 リモートワークのノウハウやトラブルを記録する リモートワークでのノウハウやトラブルは記録を残すようにしています。みんなが未経験の状況なので、ノウハウにしろトラブルにしろ誰かが経験していれば小さなことでも参考になるかもしれません。インターネットの利用が世界的に増大しているため、解決しようがない通信等の問題も多々ありますが、記録しておくことで別の誰かが昨日も同じ時間に同じ問題が起きたことに気づき、落ち着いて対処できることもあります。 リモートワークのトラブル記録 チーム開発の現場 次に、チーム開発の現場の取り組みをご紹介します。10人のチームは、4人で構成される2つのサブチームと、2人のマネジャー(プロダクトと組織)で構成されています。実際の開発現場はサブチームでの活動が中心です。 タスクはなるべく小さく分解する オフィス勤務の時はホワイトボードのカンバンで仕事を進めていましたが、現在は Trello に移行しました。 オフィス勤務時代のホワイトボードのカンバン チーム全体の朝会の後、サブチームに分かれてWeb会議でTrelloのカンバンを共有しながら朝会を行っています。お互いの状況が直接見えなくなったことにより、1つのタスクが大きかったり、他のメンバーが想像しづらいタスクが進行しているとカンバン上で状況を把握することが今まで以上に難しくなりました。追加タスク、割り込みタスクも漏れなくカンバンに追加し、開発と並行で運用業務も行っているサブチームでは運用タスクも漏れなく登録しています。1つ1つのカードで、お互いのタスクの進行状態を共有することの重要性と難しさを改めて感じています。 Trelloのカンバン Web会議は常時つないでおく サブチーム単位でのWeb会議を1日中オープンして常時つないだ状態にしています。オフィス勤務の時に自然と行っていたメンバー同士のちょっとした相談や、隣同士の世間話からの状況把握、なんとなく困っている雰囲気を察知してサポートするなどのチームワークがリモートワークに移行したことでできなくなり、漠然とした不安を感じるという意見が出ました。オンラインで常時繋がっていることで、オフィス勤務と同じとまではいかないものの、相談しやすい雰囲気やなんとなくお互いの状況を把握することはできるようになりました。 カメラや音声については、自宅の業務環境によっては常時ONにするのが難しいメンバーもいるためルールは決めていません(個人の判断におまかせ)。業務の不安をなるべく解消するという目的に全員が向き合ってオンラインで繋がることが重要だと考えています。 1対1の相談は電話感覚でWeb会議をコールする 常時つないでいる相手はサブチーム内のメンバーなので、サブチームを越えた相手への相談がしにくい問題が残ります。チャットだと内容が伝わりにくかったり、なかなか相手から返事がもらえないなど、ここでもリモートワークならではの課題がありました。チャット文化の浸透によって最近は減っていましたが、以前はこういうケースは直接電話をして聞いていました。なので、チームで決めたルールは以下の通り、ほぼ電話と同じです。 ちょっとした確認事項でも直接コールOK ただし、相手が出れない場合があることを前提とする 相手が出ない場合は、時間を置いて再度コールするか、チャットで折り返しを依頼する 呼び出された側は無理のない範囲で応答する(忙しい場合は出なくても良い) チーム全体で一斉にこれをやるとコール地獄に陥りそうですが、活動の中心となるサブチーム内では常時つながっているうえで、それ以外の必要なときにこの手段を選択するので成り立っていると思います。 マインドマップ でふりかえり ふりかえりなどの議論中心のミーティングでは、色々なオンラインツールを活用する手法が一般に公開されています。しかし、我々のチームでは開発用のPC環境の問題でWeb会議につないだ状態でこれらのオンラインツールを使うことが難しいケースがあります。オフィス勤務の時は、業務中いつでも思いついた時に KPT 方式でTrelloに登録しておき、ふりかえりの時間は ファシリテーター だけがPCを持ち込んで内容を確認しつつ、ホワイトボードに整理していく方式でした。リモートワークでも同じやり方であれば、Web会議につなぐだけで進行できますが、オンラインのホワイトボードツールをオフィスのホワイトボードと同じ要領で使うのが難しかったため マインドマップ ツールに移行しました。 マインドマップ はオフィスのホワイトボードよりも自由度が下がりますが、Web会議でのコミュニケーションにも制限があることから、あまり不便さは感じていません。一定の制限下で思考を整理するうえで マインドマップ のツールとしての制限はむしろ効果的に作用しています。 ホワイトボードがわりの マインドマップ さいごに リモートワークに移行して様々な変化に直面していますが、その中で気づいたことは、チームで働くうえでのコミュニケーション、 言語化 、可視化の難しさなどです。これらは、見えていなかっただけで実際はオフィス勤務の時から 潜在的 な課題だったことも多くあると感じています。そのため、慌てずしっかり向き合って対処していけば、今後オフィス勤務に戻ったときもチームにとって良い効果に繋がるのではないかと思います。 世界中が大きな変化に包まれる中で、これから我々の働き方は大きく変わっていくという話も聞こえてきます。私たちもまだまだ試行錯誤の連続ですが、このような変化の中で私たちと同じように働くみなさんにとって、何かの参考になれば幸いです。 私たちは一緒に働くメンバーを募集しています。興味を持たれましたら以下のサイトからお問い合わせください。 career-recruit.rakus.co.jp
アバター
こんにちは、goldminer です。 はじめに 昨年から新しいプロジェクトに携わることになり、そのプロジェクトでは ドメイン 駆動設計(DDD)を取り入れています。 それまで DDD をやったことがなかったので色々と試行錯誤しながら進めていて、特に ドメイン サービスについては自分の中での捉え方の変化が激しかったのでまとめてみました。 これから DDD を始めようという方の一助になれば幸いです。 以下の フレームワーク 、 アーキテクチャ を採用した例を記述しています。 Spring Boot ヘキサゴナル アーキテクチャ ドメイン サービスとは ドメイン サービスについて調べてみると概ね次のように説明されています。 ドメインにおける重要なプロセスの内、エンティティや Value Object の責務とするべきではないものを ドメインサービスとして定義する 最初に作った ドメイン サービス 「ログ インパス ワードはハッシュ化してデータベースに保存する」というセキュリティ要件を対応した際に作成した ドメイン サービスです。 パスワードは Password クラス(エンティティ)が保持しますが、それをハッシュ化する責務までをも Password クラスに負わせるのは適切でないと考えました。 そこでハッシュ化する責務を持った ドメイン サービスを作成することにしました。 ハッシュ化の(ストレッチ回数などの) アルゴリズム は技術的にすぎるということで ドメイン サービスはインターフェースで定義し、実装クラスはインフラスト ラク チャ層に配置することにしました。 public interface HashPasswordService { /** * 平文のパスワードをハッシュ化する. */ String hash(String plainPassword); // インフラストラクチャ層に配置 @Service public class HashPasswordServiceImpl implements HashPasswordService { public String hash(String plainPassword) { // ハッシュ化のアルゴリズムを実装している. } この ドメイン サービスについて今の時点では次のように評価しています。 良: エンティティが負うべきでないハッシュ化の責務を ドメイン サービスとして分離できている 良: 技術的にすぎるハッシュ化の アルゴリズム をインフラスト ラク チャ層に分離できている 悪: @Service はアプリケーションサービス *1 にも使用しており、 @Service の用法が混乱している 総じて悪くないと思っているのですが、最初に作成した ドメイン サービスがそうであったことで「 ドメイン サービスはインターフェースと実装クラスを分離したもの」という間違った思い込みをしてしまったように思います。 その後 ドメイン サービスを全く作成しない 上述したように「 ドメイン サービスはインターフェースと実装クラスを分離したもの」という間違った思い込みをしてしまったため、技術的な要素がほとんどない ドメイン では ドメイン サービスの出番がありません。 そして本来は ドメイン サービスとして作成すべきクラスを別のモデルで作成するという迷走を始めてしまいました... 「消費税を計算する」という例で書いています(実際は別の計算だったのですが、それを説明するのはとても大変なので日本人になじみのある消費税計算に置き換えています)。 public interface CalculateTaxPolicy { /** * 税込価格を計算する. * @param priceExcludingTax 税抜価格 */ BigDecimal priceIncludingTax(BigDecimal priceExcludingTax); /** * 標準税率(10%)で計算する CalculateTaxPolicy の実装クラス. */ public class CalculateStandardTaxPolicy implements CalculateTaxPolicy { @Override public BigDecimal priceIncludingTax(BigDecimal priceExcludingTax) { BigDecimal taxRate = BigDecimal.valueOf( 10 ); // 標準税率(10%) BigDecimal coefficient = BigDecimal.valueOf( 100 ).add(taxRate) .scaleByPowerOfTen(- 2 ); BigDecimal priceIncludingTax = priceExcludingTax.multiply(coefficient); priceIncludingTax = priceIncludingTax.setScale( 0 , RoundingMode.HALF_UP); // 四捨五入する return priceIncludingTax; } /** * 軽減税率(8%)で計算する CalculateTaxPolicy の実装クラス. */ public class CalculateReducedTaxPolicy implements CalculateTaxPolicy { @Override public BigDecimal priceIncludingTax(BigDecimal priceExcludingTax) { BigDecimal taxRate = BigDecimal.valueOf( 8 ); // 軽減税率(8%) // 以降は標準税率の場合と同じなので省略 } この設計についての評価は以下です。 良: エンティティ(おそらく税抜価格は「商品」のようなクラスが持っている)が負うべきでない税込価格の計算の責務を分離できている 悪: 「税込価格の計算」というプロセスを記述しているにもかかわらず ドメイン サービスではなくポリシーとして作成している 8%と10%という 複数税率 からポリシーを使うことを発想したところまではよかったのですが、プロセスまでをもポリシーに記述してしまって ドメイン サービスを使うという発想には至りませんでした。 もっと ドメイン サービスを活用しようと考える ドメイン サービスを作成する機会がまったくなく「これでよいのか?」と疑問に思ったことがきっかけです。 現時点での ドメイン サービスの捉え方は冒頭にも書いたとおり「エンティティが負うべきでない ドメイン におけるプロセスを記述したもの」です。 「消費税を計算する」の設計も今では次のような設計を考えています(実際に リファクタリング 予定です)。 public interface TaxPolicy { /** * 税率を返す. */ int rate(); /** * 標準税率(10%)を返す TaxPolicy の実装クラス. */ public class StandardTaxPolicy implements TaxPolicy { @Override public int rate() { return 10 ; } /** * 軽減税率(8%)を返す TaxPolicy の実装クラス. */ public class ReducedTaxPolicy implements TaxPolicy { @Override public int rate() { return 8 ; } public class CalculateTaxService { /** * 税込価格を計算する. */ public BigDecimal priceIncludingTax(BigDecimal priceExcludingTax, TaxPolicy policy) { BigDecimal taxRate = BigDecimal.valueOf(policy.rate()); BigDecimal coefficient = BigDecimal.valueOf( 100 ).add(taxRate) .scaleByPowerOfTen(- 2 ); BigDecimal priceIncludingTax = priceExcludingTax.multiply(coefficient); priceIncludingTax = priceIncludingTax.setScale( 0 , RoundingMode.HALF_UP); // 四捨五入する return priceIncludingTax; } ちゃんと ドメイン サービスを活用できています。 今後もこんな感じで ドメイン サービスを組み込んで設計を考えていきたいです。 エンジニア 中途採用 サイト ラク スでは、エンジニア・デザイナーの 中途採用 を積極的に行っております! ご興味ありましたら是非ご確認をお願いします。 https://career-recruit.rakus.co.jp/career_engineer/ カジュアル面談お申込みフォーム どの職種に応募すれば良いかわからないという方は、カジュアル面談も随時行っております。 以下フォームよりお申込みください。 rakus.hubspotpagebuilder.com ラク スDevelopers登録フォーム https://career-recruit.rakus.co.jp/career_engineer/form_rakusdev/ イベント情報 会社の雰囲気を知りたい方は、毎週開催しているイベントにご参加ください! ◆TECH PLAY techplay.jp ◆connpass rakus.connpass.com *1 : ヘキサゴナル アーキテクチャ の用語
アバター
はじめに 名前に情報を詰め込む 明確な単語を選ぶ 汎用的な名前を避ける(あるいは使う状況を選ぶ) 抽象的な名前よりも具体的な名前を使う 接尾辞や接頭辞を使って情報を追加する 名前の長さを決める 名前のフォーマットで情報を伝える 制御フローを読みやすくする おわりに 参考 はじめに こんにちは。新卒2年目のnr_1228です。 ボリュームの大きい実装に携わるようになって、重要だと再認識したことがあります。 コードを書くときは、他の人(未来の自分も含む)でも理解しやすいように書くべき。 自分が書いたコードや既存のコードを読む際に、この変数は何が入ってるのだろう?となったことが何回かありました。 これはあの本を読み返すべきでは… ということで、研修時に読んだ「リーダブルコード」を再び読むことにしました。 前回読んだ時よりも実体験などもあり、理解・納得できる部分が増えていました。 そこで今回は、改めて「リーダブルコード」を読んで、最近引っかかることの多かった 命名 のポイント と ロジックの単 純化 についてまとめてみることにします。 名前に情報を詰め込む コードを書いていると名前を付けなければならない時が必ずあります。 関数や変数名を見た時点で、これは何をしている関数なのか、何の変数なのかが パッとわかるようにした方が、他の人にも親切です。 名前の付け方のポイントは以下の6点です。 明確な単語を選ぶ その関数・変数が何を表しているのか明確にすることが、分かりやすい名前を付ける必須事項です。 自分の中ですぐに出てくる単語を使うのもいいですが、状況に合わせて単語を選ぶようにしましょう。 単語 代替案 send deliver, dispatch, announse, distribute, route find search, extract, locate, recover start launch, create, begin, open make create, set up, build, generate, compose, add, new 汎用的な名前を避ける(あるいは使う状況を選ぶ) 戻り値にいい名前が思いつかなければ、 retval などと付けたくなりますが、 「戻り値である」という以外の情報はありません。 戻り値として何を返しているのかが分かるような名前にしなければなりません。 例えば、xの2乗の合計を戻り値とするならば、 sum_squares というような名前を付けた方が retval よりも変数の目的を伝えることができます。 抽象的な名前よりも具体的な名前を使う ServerCanStart という名前の、任意のポートをサーバがリッスンできるか確認するメソッドがあるとします。 その時、この名前は具体的で分かりやすいと言えるでしょうか? もっと具体的な名前にすると、 CanListenOnPort とした方が、メソッドの動作をそのまま表すことができ、 他者にも分かりやすく伝わります。 接尾辞や接頭辞を使って情報を追加する 時間はバイト数のように計測できるものであれば、変数名に単位を入れるのも良いです。 例えば、秒を返すのかミリ秒を返すのかが分かりにくい場合は、変数に _ms を追加すれば明確になります。 名前の長さを決める 良い名前を選ぶときには、長い名前を避けて簡潔なものをと思いがちです。 長い名前を避けると1つの単語だけの名前になってしまいます。 変数の使い方によって違ってきますが、以下を参考にするとよいでしょう。 スコープが小さければ短い名前でもいい 長い名前を入力するのは問題ではない 頭文字と省略形 BackEndManager を BEManager にすると他の人全員に伝わるでしょうか?理解できるなら問題はありませんが、全員に伝わるか分からないような省略の仕方はやめた方がいいです。 しかし、evaluationをeval、documentをdoc、stringをstrのように省略するのは理解ができるので問題ありません。 不要な単語を投げ捨てる 名前に含まれる単語を削除しても情報が全く損なわれないこともあります。 例えば、 ConvertToString を ToString にしたり、 DoServeLoop を ServeLoop に変えても明確さは変わりません。 名前のフォーマットで情報を伝える アンダースコア・ ダッシュ ・大文字を使って、名前に情報を詰め込むこともできます。 クラス名はキャメルケース、変数名はアンダースコアで単語を区切るなどの決まりを作っておけば、 文字列を見た時点で何を表しているのかが明確になります。 制御フローを読みやすくする コードの制御フローを読みやすくするためにできることはいくつかあります。 比較を書くときには、変化する値を左に、より安定した値を右に配置する if/else文のブロックは適切に並び替える  一般的には、肯定系、単純・目立つものを先に処理する。 深いネストを避ける  複雑な処理を書いていると知らない間にネストが深くなってしまうことがあります。  ネストが深くなってしまった場合は、別の処理でどうにかできないかなど、  一歩下がって全体を見るようにするのがいいかもしれません。 おわりに 初めてこの本を読んだ時は、まぁできるでしょうと特に引っかかることもなく読んでいました。 しかしコードを読み書きする機会が増えて読み直したら、こうやるのがいいのかと思うところが出てきてなるほどと思える部分が結構見つかるのです。 自分だけしか見ないコードならまだしも、他の人も見るコードは見やすさや分かりやすさを重視し、 少し分かりづらいロジックになってしまったのなら、せめて変数やコメントなどで分かりやすく伝わるようにしていくことが 大切です。 迷ったときにこの本を読み直してみると、自分のコードのどこに改善点があるのか見つかると思います。 定期的に読んで自分のコードを確かめてみるのもいいかもしれません。 自分もまだまだなので、改善していこうと思います。 参考 リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック (Theory in practice) 作者: Dustin Boswell , Trevor Foucher オライリージャパン Amazon
アバター
こんにちは、3年目エンジニアのaa_cryingです。 あっという間に3年目です。時が経つのは早いものですね...。 業務でJenkinsのジョブを作る・改善する機会がありました。 その際にシェルについて悩んだ末に色々学ぶことが出来たので、今回はその内容をアウトプットしたいと思います。 以下目次です。 変数を分割してfor文で回したい ファイルの○行目に追記したい おわりに 変数を分割してfor文で回したい 複数の対象に同じ処理を実行したい場合等に便利なのが for文 です。 様々な言語にfor文は存在しますが、シェルの場合の基本文法は以下のような形です。 for 変数 in リスト do 処理... done 今回は、1つの変数を区切り文字で分割し、for文で回す方法です。 「指定したブランチが存在する場合にチェックアウトする」シェルを例として以下に記載します。 # ブランチ名をカンマ区切りで複数入力 echo "input branches, comma delimited. (ex. master,develop,...)" read branches # ブランチ毎に処理を実行 for branch in `echo $branches | sed "s/,/ /g"`; do if [[ $(git branch -a | grep $branch) = "" ]] ; then echo "branch $branch does not exists." exit 1 fi git checkout -b $branch origin/$branch done branches という変数にはカンマ(,)区切りで複数のブランチを入力します。 入力されたbranchesをリストとして認識させるため、カンマを空白に置換したいです。 ここで sed を使用します。 sed "s/aaa/bbb/g" と記述すると、「aaa」で検索しヒットした全てを「bbb」に置換します。 g を忘れてしまうと、検索してヒットした最初のものだけ置換されてしまうので注意です! 今回は、 sed "s/,/ /g" と記述したので、カンマを全て半角スペースに置換してくれます。 後はfor文がリストとして認識し、回してくれます。 ファイルの○行目に追記したい postgreSQL を使っている方だと、pg_hba.confにサーバ名を追記なんてことは日常茶飯事だと思います。 echo "ほにゃらら" >> ファイル を使用して最後尾に追記という方法もありますが、記載場所によってはうまく動作しないこともありますよね。。 viで開いて更新 or FTP ソフトを使って開いて書き換え...というのも面倒... そこで、今回は「行数を指定して挿入する」方法を紹介します。 echo "Pg connection source server IP." read SERVER1 echo "Pg connection destination server IP." read SERVER2 echo "PGDATA path." read PGDATA sudo ssh-keygen -R ${SERVER2} sudo ssh ${SERVER2} bash <<SHELL # pg_hba.confに追記して再起動 sed -i -e "100i host all all ${SERVER1}/32 trust #test" ${PGDATA}/pg_hba.conf systemctl restart postgresql.service SHELL SERVER1 は接続元サーバのIP、 SERVER2 は接続先サーバのIPとします。 「接続先サーバに SSH 接続し、接続先サーバのpg_hba.confの100行目に接続元サーバの情報を追記する」という処理を行っています。 sed コマンドと言えば、 正規表現 を用いてファイルや標準出力の文字列置換をする使用方法が有名ですが、行の追加や挿入、削除、はたまた入出力まで出来てしまうマルチなコマンドです。 行数を指定して挿入する場合は、挿入する文言の先頭に 行数i と記載するだけです。 また -i オプションは、付けることでファイルを直接書き換えることが出来ます。 今回のようにファイルを書き換えて保存したい場合は、 -i オプションを付けないと書き換わりません。 手動でやっていると postgresql の再起動を忘れがちだったり (私の場合) しますが、シェルに記載しておくと一気にやってくれるので便利ですね。(小声) おわりに 今回は、業務で使えるシェルの基本的な知識を紹介しました。 本当はもう少しボリュームのある記事にしようと思っていたのですが、時間があまり取れず紹介は2つだけに。。 まだまだ勉強不足ですので知識を深め、今後もこのような形で学んだ技術を発信できたらと思います! また、 Linux コマンドの一覧表を以下ブログにてまとめておりますので、ご参考ください。 よく使うLinuxコマンド一覧【最新版】 Linux の理解をより深めたい方へ以下関連おすすめブログ ・ ls コマンド 【使い方 まとめ】 ・ find コマンド 【使い方 まとめ】 ・ iptables まとめ【Linux ファイアウォール】 ・ sed コマンド【使い方 まとめ】 ・ vi コマンド【使い方まとめ】 ・ Linuxのファイル操作でよく使うLinuxコマンド ・ 初心者のためのawkコマンド ・ 【Linux】今振り返りたい、プロセスって何? エンジニア 中途採用 サイト ラク スでは、エンジニア・デザイナーの 中途採用 を積極的に行っております! ご興味ありましたら是非ご確認をお願いします。 https://career-recruit.rakus.co.jp/career_engineer/ カジュアル面談お申込みフォーム どの職種に応募すれば良いかわからないという方は、カジュアル面談も随時行っております。 以下フォームよりお申込みください。 forms.gle イベント情報 会社の雰囲気を知りたい方は、毎週開催しているイベントにご参加ください! rakus.connpass.com
アバター
こんにちは。y_kwmtです。 はじめに 少し前にVue.jsとFirebaseを用いて Google アカウントのログイン機能と Markdown 書式のメモを作成する機能を作成しました。 tech-blog.rakus.co.jp 以下のサイトを参考にして Markdown 書式のメモを応用したチャット機能を作成したので、 本記事では実装の準備、実装方法について紹介していきます。 cr-vue.mio3io.com はじめに 実装する機能 チャット機能 データベース作成 Vue.jsでFirebaseを使用する チャット機能の実装 動作確認 おわりに 実装する機能 チャット機能 メッセージを送信、受信できる 送信したメッセージを Markdown 書式で表示 ページを再訪問しても送信したメッセージが残っている ※前回の記事で作成したメモ機能は使わないので一旦なくします データベース作成 プロジェクト内の「Database」を選択して「Realtime Database」からデータベースをテストモードで作成します。チャットのメッセージとメッセージ送信者の情報をレコードとして追加します。 Vue.jsでFirebaseを使用する firebase モジュールをインストールして main.js で読み込みます。 npm install firebase Firebaseのプロジェクトの「Settings」を開いて 「Firebase SDK snippet」の スクリプト 部分を追記してください。 import firebase from firebase import Vue from 'vue' import App from './App.vue' import 'firebase/firestore' ; // ここから var firebaseConfig = { apiKey: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" , authDomain: "XXXXXXXXX.firebaseapp.com" , databaseURL: "https://XXXXXXXX.firebaseio.com" , projectId: "XXXXXXXXX" , storageBucket: "XXXXXXXXX.appspot.com" , messagingSenderId: "XXXXXXXXX" , appId: "X:XXXXXXXXXXXX:web:XXXXXXXXXXXXXXXXXXXX" , measurementId: "X-XXXXXXXXXX" } ; // Initialize Firebase firebase.initializeApp(firebaseConfig); firebase.analytics(); // ここまで new Vue( { el: '#app' , render: h => h(App) } ) チャット機能の実装 前回投稿したブログで登場した、メモを作成する画面「Editor.vue」を改修し、 ログイン後の画面にチャット機能を追加します。 先ほど作成したデータベースにチャットのメッセージ、メッセージ送信者、 Google アカウントの画像パスがレコードとして保存されます。 <template> <div id= "home" > <h1>エディター画面</h1> <p> <span> {{ user.displayName }} </span> <button @click= "logout" >ログアウト</button> </p> <transition-group name= "chat" tag= "div" class = "list content" > <!-- chatにはキー、送信者名、Googleアカウントの画像パス、メッセージが入っています。 --> <section v- for = "{ key, name, image, message } in chat" :key= "key" class = "item" > <div class = "item-image" ><img :src= "image" width= "40" height= "40" > {{ name }} </div> <div class = "item-detail" > <div class = "item-message" > <!-- メッセージがMarkdown書式で表示されます。 --> <div v-html= "message" ></div> </div> </div> </section> </transition-group> <!-- 入力フォーム --> <form action= "" @submit.prevent= "doSend" class = "form" > <!-- Enterを押すとメッセージが送信されます。Enter + Shiftで改行します。 --> <textarea v-model= "input" :disabled= "!user.uid" @keydown.enter.exact.prevent= "doSend" ></textarea> <div> <!-- ボタンを押すとメッセージが送信されます --> <button type= "submit" :disabled= "!user.uid" class = "send-button" >Send</button> </div> <div> プレビュー<div v-html= "preview()" ></div> </div> </form> </div> </template> <script> import marked from "marked" ; // 改行を <br> タグに変換するモジュール export default { name: 'editor' , props: [ "user" ] , data() { return { chat: [] , // 取得したメッセージを入れる配列 input: '' // 入力したメッセージ } } , created() { // データベースからメッセージ情報取得 const ref_message = firebase.database().ref( 'message' ) if ( this .user) { this .chat = [] // message に変更があったときのハンドラを登録 ref_message.limitToLast(10).on( 'child_added' , this .childAdded) } else { // message に変更があったときのハンドラを解除 ref_message.limitToLast(10).off( 'child_added' , this .childAdded) } } , methods: { logout: function () { firebase.auth().signOut(); } , preview: function () { return marked( this .input); } , childAdded(snap) { const message = snap.val() this .chat.push( { key: snap.key, name: message.name, image: message.image, message: marked(message.message) } ) } , doSend: function () { if ( this .user.uid && this .input.length) { // firebase にメッセージを追加 firebase.database().ref( 'message' ).push( { message: marked( this .input), name: this .user.displayName, image: this .user.photoURL } , () => { this .input = '' // フォームを空にする } ) } } , displayTitle: function (text) { return text.split( /\n/ ) [ 0 ] ; } } } </script> 動作確認 実際の画面がこちらです。メッセージを入力するとプレビューが表示され、 送信すると Markdown 書式でメッセージが表示されます。 黒く塗りつぶしている部分は Google アカウントの名前を表しています。 おわりに 今回はVue.jsで Markdown 書式を応用したチャット機能を紹介しました。 データベースなどの設定やApp.vueを2回呼び出してしまうエラーなどに少し時間がかかってしまいました。 今後はVue.jsだけでなく、他のフロント系の技術を学習して紹介していきたいと思います。 エンジニア 中途採用 サイト ラク スでは、エンジニア・デザイナーの 中途採用 を積極的に行っております! ご興味ありましたら是非ご確認をお願いします。 https://career-recruit.rakus.co.jp/career_engineer/ カジュアル面談お申込みフォーム どの職種に応募すれば良いかわからないという方は、カジュアル面談も随時行っております。 以下フォームよりお申込みください。 forms.gle イベント情報 会社の雰囲気を知りたい方は、毎週開催しているイベントにご参加ください! rakus.connpass.com
アバター
はじめに 実装に使った物 実装する機能 リマインダーを実装してみる 動作確認! おわりに 参考にした記事 はじめに こんにちは。新卒2年目のrs_chankoです。 まだまだ慣れない社会人。そんな中で思ったことがあります。 物忘れが酷すぎる。 これは元々分かっていたんですが、最近特に思います。 会社では朝にスケジュールを確認しますが、 プライベートではスケジュールを見る習慣がなく、忘れてしまいがち…。 「そうだ、LINEなら毎日見るし、自分で作っちゃうか。」 そう思い立ち、GASとLINE Messaging API を使ってリマインダーを作ることになりました。 実装に使った物 GAS( Google Apps Script) LINE Messaging API Google スプレッドシート 実装する機能 日付と予定を スプレッドシート に登録すると、登録されたデータを参照してメッセージとして送ってくれる (忘れがちなので)7時、12時、19時に今日と明日の予定を教えてくれる リマインダーを実装してみる LINE Messaging API とGASの接続方法は先輩がすでに書いていたのでそのまま参考にしました。 tech-blog.rakus.co.jp しかしそもそも JavaScript もあまりちゃんと書いたことがなく、GASやMessaging API も使ったことがない。 ひとまず練習するか、ということでお試しにオウム返し bot を作ってみました。 note.com これは簡単にできました。 さて、本題です。 ひとまずオウム返しで使った API 周りのコードを元に実装していきます。 //LINEのアクセストークン var channel_access_token = "アクセストークン" ; var headers = { "Content-Type" : "application/json; charset=UTF-8" , "Authorization" : "Bearer " + channel_access_token } ; //返信する function sendLineMessageFromReplyToken(token, replyText) { var url = "https://api.line.me/v2/bot/message/reply" ; var headers = { "Content-Type" : "application/json; charset=UTF-8" , "Authorization" : "Bearer " + channel_access_token } ; var postData = { "replyToken" : token, "messages" : [{ "type" : "text" , "text" : replyText }] } ; var options = { "method" : "POST" , "headers" : headers, "payload" : JSON.stringify(postData) } ; return UrlFetchApp.fetch(url, options); } //指定のuserIdにメッセージを送る function sendLineMessageFromUserId(userId, text) { var url = "https://api.line.me/v2/bot/message/push" ; var postData = { "to" : userId, "messages" : [{ "type" : "text" , "text" : text }] } ; var options = { "method" : "POST" , "headers" : headers, "payload" : JSON.stringify(postData) } ; return UrlFetchApp.fetch(url, options); } 準備が整いました。 それではまず Bot にやってほしいことをまとめます。 予定の登録 予定の削除 登録・削除時の返事 指定時刻の通知 登録されている予定の確認 上記ができるよう実装します。 //8桁日付のフォーマット function formatDateForDisplay (date) { var year = date.substr(0,4); var month = date.substr(4,2); var day = date.substr(6,2); var result = year + "/" + month + "/" + day; return result; } //Date型日付のフォーマット function formatDate (date, format) { format = format.replace( /yyyy/g , date.getFullYear()); format = format.replace( /MM/g , ( '0' + (date.getMonth() + 1)).slice(-2)); format = format.replace( /dd/g , ( '0' + date.getDate()).slice(-2)); return format; } ; //日付をシートに記載する function setDate(date, plan, row) { if (isNaN(date) || String (date).length != 8) { return '日付が正しくありません' ; } setFromRowAndLine(date, row, 0); return setPlan(plan, row); } //予定をシートに記載する function setPlan(plan, row) { setFromRowAndLine(plan, row, 1); return '予定を登録しました。' ; } //トリガー起動で当日と翌日の予定を返す function getTodayAndNextDayMessage() { var date = new Date (); var userId = ’LINEのユーザーID’; //今日の予定を取得 var remindText = getDatePlan(date); //明日の予定を取得 date.setDate(date.getDate() + 1); remindText += " \n " + getDatePlan(date); return sendLineMessageFromUserId(userId, remindText); } //指定日の予定を返す function getDatePlan(date) { if (date instanceof Date ) { date = formatDate(date, 'yyyyMMdd' ); } var day = formatDateForDisplay(date); var remindText = day + " \n " ; var plans = searchPlans(date); for ( var i = 0; i < plans.length; i++) { remindText += getFromRowAndLine( 'webhook' , plans [ i ] ); remindText += " \n " ; } remindText = remindText.slice(0,-1); if (remindText.length === 10) { remindText += " \n 明日は予定がありません。" ; } return remindText; } //受け取ったメッセージに対して返信する function doPost(e) { var webhookData = JSON.parse(e.postData.contents).events [ 0 ] ; var message, replyToken, replyText, userId; message = webhookData.message.text.split( " \n " ); replyToken = webhookData.replyToken; userId = webhookData.source.userId; var processing = message [ 0 ] ; var planDate = message [ 1 ] ; var plan = message [ 2 ] ; var row = getLastRow(); switch (processing) { case '登録' : replyText = setDate(planDate, plan, row); break ; case 'キャンセル' : replyText = cancel(planDate, plan); break ; case '確認' : replyText = planDate === undefined ? getDatePlan( new Date ()) : getDatePlan(planDate); break ; case 'test' : replyText = testSheet(); break ; default : replyText = "予定の登録・キャンセルができます。 \n\n 登録 \n 20200101 \n 予定 \n\n の形式で入力してください。" ; break ; } return sendLineMessageFromReplyToken(replyToken, replyText); } //予定を削除する function cancel(date,plan) { deleteRowOfDateAndPlan(date, plan); return '予定の登録をキャンセルしました。' } //トリガーをセットする function setTrigger() { const time = new Date (); time.setHours(7); time.setMinutes(00); ScriptApp.newTrigger( 'getTodayAndNextDayMessage' ).timeBased().at(time).create(); time.setHours(12); ScriptApp.newTrigger( 'getTodayAndNextDayMessage' ).timeBased().at(time).create(); time.setHours(19); ScriptApp.newTrigger( 'getTodayAndNextDayMessage' ).timeBased().at(time).create(); time.setDate(time.getDate() - 1); //前日の予定を削除する deleteRowOfDate(formatDate(time, 'yyyyMMdd' )); } //トリガーを削除する function delTrigger() { const triggers = ScriptApp.getProjectTriggers(); for ( const trigger of triggers) { if (trigger.getHandlerFunction() == "getTodayAndNextDayMessage" ) { ScriptApp.deleteTrigger(trigger); } } } このコードではLINEで実際に送るメッセージの生成・トリガーのセット・削除をしています。 GASのトリガーって定期実行をすると1時間の範囲内で実行されるらしいんですよね。 ちゃんと同じ時間に送ってほしいので、今回は指定の時間に通知用のメソッドをトリガーとしてセットするメソッドを定期実行にしました。 スプレッドシート とのテキストのやりとりは下記の実装をします。 //スプレッドシート var spreadsheet = SpreadsheetApp.openById( "スプレッドシートのID" ); var sheet = spreadsheet.getSheetByName( 'スプレッドシートのシート名' ); //受け取った日付の予定が記載されている行を返す function searchPlans(date) { var data = sheet.getDataRange().getValues(); var plans = [] ; for ( var i = 0; i < data.length; i++) { if (data [ i ][ 0 ] == date) { plans.push(i + 1); } } return plans; } //列を指定してデータを取得する function getFromRowAndLine(sheetName, row) { var data = sheet.getDataRange().getValues(); return data [ row - 1 ][ 1 ] ; } //列を指定してデータを書き込む function setFromRowAndLine(val, row, line) { sheet.getRange(row + 1, line + 1).setValue(val); } function getLastRow() { return sheet.getLastRow(); } //日付と予定から行を削除する function deleteRowOfDateAndPlan(date, plan) { var lastRow = getLastRow(); for ( var i = 1; i <= lastRow; i++) { if (sheet.getRange(i, 1).getValue() == date && sheet.getRange(i, 2).getValue() == plan) { sheet.deleteRows(i); } } } //指定の日付の行を削除する function deleteRowOfDate(date) { var lastRow = sheet.getDataRange().getLastRow(); for ( var i = 1; i <= lastRow; i++) { if (sheet.getRange(i, 1).getValue() == date) { sheet.deleteRows(i); } } } これで実際に スプレッドシート に日付と予定を書き込んだり、参照することができるようになりました。 こんな感じでLINEから送られてきた予定が書き込まれます。 動作確認! それでは実際にメッセージを見てみましょう。 おおおお! 予定の登録や確認ができ、19時に予定の通知がきました! そんなこんなで完成です。 おわりに 「リマインダー」について何も調べていなかったんですが、 作り終わってから調べたところ、すでにリマインド Bot が存在していました。。。 remine.akira108.com しかし作ってしまったものは作ってしまったので、今後はカスタマイズをして自分の好みのリマインダーを作っていこうと思います。 あとはLINEに予定を登録することを忘れないように…。 参考にした記事 qiita.com tonari-it.com エンジニア 中途採用 サイト ラク スでは、エンジニア・デザイナーの 中途採用 を積極的に行っております! ご興味ありましたら是非ご確認をお願いします。 https://career-recruit.rakus.co.jp/career_engineer/ カジュアル面談お申込みフォーム どの職種に応募すれば良いかわからないという方は、カジュアル面談も随時行っております。 以下フォームよりお申込みください。 rakus.hubspotpagebuilder.com ラク スDevelopers登録フォーム https://career-recruit.rakus.co.jp/career_engineer/form_rakusdev/ イベント情報 会社の雰囲気を知りたい方は、毎週開催しているイベントにご参加ください! ◆TECH PLAY techplay.jp ◆connpass rakus.connpass.com
アバター
こんにちは。y_kwmtです。 はじめに 昨年にVue.jsの学習を行うためにこちらの書籍を読みました。 https://www.amazon.co.jp/Vue-js%E3%81%A8Firebase%E3%81%A7%E4%BD%9C%E3%82%8B%E3%83%9F%E3%83%8BWeb%E3%82%B5%E3%83%BC%E3%83%93%E3%82%B9-%E6%8A%80%E8%A1%93%E6%9B%B8%E5%85%B8%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA%EF%BC%88NextPublishing%EF%BC%89-%E6%B8%A1%E9%82%8A-%E9%81%94%E6%98%8E/dp/4844398350 www.amazon.co.jp こちらの書籍を参考に、 Google アカウントでログインする機能と markdown 書式でメモを作成する機能を作成しました。昨年の ラク ス アドベントカレンダー にVue.jsのプロジェクトをFirebaseでデプロイする方法について記事を投稿したので、本記事を閲覧する前にご確認いただけると幸いです。 qiita.com ログイン機能 src ディレクト リの下にcomponents ディレクト リを作成し、そこに「Home.vue」と「Editor.vue」を作成してください。 mymarkdown ― src ― components ― Home.vue(ログイン画面) | | | └ Editor.vue(メモ作成画面) | └ App.vue(画面切り替え) まずは Google アカウントでログインする機能を作成します。ログインする前の画面「Home.vue」を実装します。 Home.vue <template> <div id= "home" > <h1> {{ msg }} </h1> <button>Googleアカウントでログイン</button> </div> </template> <script> export default { name: 'home' , data() { return { msg: "Welcome to MyMarkDown" } ; } } ; </script> ログイン状態によって画面を切り分ける「App.vue」を作成します。 createdでログイン状態を確認しています。 この画面で「Home.vue」と「Editor.vue」を読み込んで、ログイン状態により表示を変えています。 App.vue <template> <div id= "app" > <Home v- if = "!isLogin" ></Home> <Editor v- if = "isLogin" :user= "userData" ></Editor> </div> </template> <script> import Home from "./components/Home.vue" ; import Editor from "./components/Editor.vue" ; export default { name: 'app' , data () { return { isLogin: false , userData: null } } , created: function () { firebase.auth().onAuthStateChanged(user => { console.log(user) if (user) { this .isLogin = true ; this .userData = user; } else { this .isLogin = false ; this .userData = null ; } } ); } , components: { Home: Home, Editor: Editor } } </script> <style lang= "scss" > #app { font-family: 'Avenir' , Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin- top : 60px; } h1, h2 { font-weight: normal; } ul { list-style-type: none; padding: 0; } li { display: inline-block; margin: 0 10px; } a { color: #42b983; } </style> まだログイン機能が実装されていないので、初期表示はこちらの画面(Home.vue)となります。ログイン機能を実装するためにまずFirebaseの「Authentication」の「 sign -in method」で Google アカウントでのログインを有効に設定します。「 Google 」をクリックし、「有効にする」ボタンをクリックし、プロジェクトのサポートメールを設定します。「 Google が有効になりました」と出ればOKです。 続いて「Home.vue」でログイン機能を実装します。methodsにログイン機能を追加します。 Home.vue <template> <div id= "home" > <h1> {{ msg }} </h1> <button @click= "googleLogin" >Googleアカウントでログイン</button> </div> </template> <script> export default { name: 'home' , data() { return { msg: "Welcome to MyMarkDown" } ; } , methods: { googleLogin: function () { firebase.auth().signInWithRedirect( new firebase.auth.GoogleAuthProvider()); } } } ; </script> 「 Google アカウントでログイン」ボタンをクリックすると Google アカウントの認証画面に移動し、 ここで承認すればログインすることができます。すると次のような画面が表示されます。 見出し「エディター画面」の下にはアカウント名とログアウトボタンが表示されます。(アカウント名は伏せさせていただきます) また、ログアウト機能をこの後作成するメモ機能の画面「Editor.vue」に追加します。 Editor.vue <template> <div id= "home" > <h1>エディター画面</h1> <p> <span> {{ user.displayName }} </span> <button @click= "logout" >ログアウト</button> </p> </div> </template> <script> export default { name: 'editor' , props: [ "user" ] , data() {} , methods: { // ログアウト機能 logout: function () { firebase.auth().signOut(); } } } </script> ログアウトを実行するとログイン画面が表示されます。 メモ機能 続いて入力内容を markdown 書式でプレビューを表示する機能を作成します。 そのためにマークダウン用のライブラリをインストールします。 次のコマンドを実行してインストールしてください。 npm install --save-dev marked これはmarkedという markdown 書式をHTMLに変換するnpmモジュールです。 続いてEditor.vueを編集します。 Editor.vue <template> <div id= "home" > <h1>エディター画面</h1> <p> <span> {{ user.displayName }} </span> <button @click= "logout" >ログアウト</button> </p> <div> メモリスト <div v- for = "(memo, index) in memoList" > <div v- if = "index!=0" v-html= "displayMemo(memo.markdown)" ></div> </div> <textarea class = "markdown" v-model= "memoList[memoIndex].markdown" ></textarea> <div><button v-on:click= "addMemo" >メッセージ追加</button></div><br> プレビュー<div v-html= "preview()" ></div> </div> </div> </template> <script> import marked from "marked" ; export default { name: 'editor' , props: [ "user" ] , data() { return { memoList: [ { markdown: "" , } ] , memoIndex: 0 } ; } , methods: { // ログアウト機能 logout: function () { firebase.auth().signOut(); } , // markdown書式でのプレビュー表示 preview: function () { return marked( this .memoList [this .memoIndex ] .markdown); } , // メモを追加 addMemo: function () { this .memoList.push( { markdown: marked( this .memoList [this .memoIndex ] .markdown) } ); } , // 作成したメモを一覧表示 displayMemo: function (text) { return text.split( /\n/ ) [ 0 ] ; } } } </script> 実行して、プレビューに入力内容がリアルタイムで markdown 書式で表示されていればOKです。 大見出しで「メモ」、中見出しで「ブログを書く」「メモ機能を実装する」、 小見出し で「メモを追加」「マークダウン記法でメモを表示する」というメモを追加しています。 プレビューには 小見出し で「マークダウン記法でメモを表示する」と表示しています。 おわりに 今回はVue.jsで Google アカウントのログイン機能と markdown 書式のメモ作成機能を紹介しました。今度はチャットができるようになるなど機能の拡張を行い、記事を作成していきたいと思います。 エンジニア 中途採用 サイト ラク スでは、エンジニア・デザイナーの 中途採用 を積極的に行っております! ご興味ありましたら是非ご確認をお願いします。 https://career-recruit.rakus.co.jp/career_engineer/ カジュアル面談お申込みフォーム どの職種に応募すれば良いかわからないという方は、カジュアル面談も随時行っております。 以下フォームよりお申込みください。 forms.gle イベント情報 会社の雰囲気を知りたい方は、毎週開催しているイベントにご参加ください! rakus.connpass.com
アバター
こんにちは、開発エンジニアの amdaba_sk( ペンネ ーム未定)です。 ラク スの開発部ではこれまで社内で利用していなかった技術要素を自社の開発に適合するか検証し、ビジネス要求に対して迅速に応えられるようにそなえる 「 開 ( か ) 発の 未 ( み ) 来に 先 ( せん ) 手をうつプロジェクト(通称:かみせんプロジェクト)」 というプロジェクトがあります。 この記事はかみせんプロジェクト2019年度下期成果報告ブログの一つです。 前回の成果報告では 「機械学習プロジェクトの進め方」について検証した結果のまとめ をしました。今回は「じゃあ実際に 機械学習 をやることになったら、どんなライブラリ、サービスを使えばいいの?」といったところの検証結果をまとめようと思います。 対象読者は前回と違って、 機械学習 に興味のあるエンジニアの方です。 なお今までの記事はかみせんカテゴリからどうぞ。 tech-blog.rakus.co.jp 概要 今回の目標 対象ライブラリ・サービスの選定 サンプルプロジェクトについて 学習データについて 前処理について テキストのクリーニング 単語の分割 単語の正規化 ストップワードの除去 単語のベクトル表現 文書のベクトル表現 モデル学習について 学習のそのあと 実装を終えての所感 Python + scikit-learn Python + H2O JVM系 + Smile Apache Spark Amazon SageMaker AI Platform Azure Machine Learning まとめ 今後の展望 参考 概要 非常に単純な 機械学習 タスクを実施するプログラムをいくつかのライブラリ、サービスを用いて実装することで、それぞれのライブラリ、サービスの使いやすさを評価しました。 やはり Python の scikit-learn は デファクトスタンダード であり、ライブラリの備える API の充実ぶり、Web や書籍の情報量は他を圧倒するものがあります。ただ学習データの量や、連携するシステムの開発言語によっては Apache Spark も有用です。 クラウド のマネージドサービスは、単なる Notebook の実行環境としての使い方をしている限りにおいては結局のところ scikit-learn を用いることになりがちでありその利点を引き出すことはできないということが分かりました。マネージドサービスは付属する学習済みモデルを利用するサービス、AutoML による自動学習、アプリケーションへのデプロイの容易さといったところに利点があるのだと推測されます。 今回の目標 実際に 機械学習 を利用した機能を作ることになった場合にまずやることになるであろうライブラリ、サービスの選定フェーズに対して参考になりそうな情報をまとめたいと思い調査を行いました。 とはいえライブラリやサービスを選ぶうえでの条件、観点はさまざまであり案件ごとに重視するポイントも固有のものがあるはずです。さらに調査メンバーがそもそも 機械学習 に関してそこまで詳しくはないということを考えると、実務上そのまま使えそうなレベルの資料を作るのは難しすぎます。 そこでさしあたり単純なサンプルプロジェクトを設定して 機械学習 モデルの作成 スクリプト をいくつかのライブラリ、サービスを使って実装し、それぞれの使用感をまとめました。 対象ライブラリ・サービスの選定 Python + scikit-learn Python + H2O JVM 系 + Smile Apache Spark Amazon SageMaker AI Platform Azure Machine Learning JVM 系の言語としてはメンバーのモチベーション的な理由から Scala を採用しました。 また事前の調査から「 Python 3 + scikit-learn」が ディープラーニング を行わない場合の デファクトスタンダード のような存在であることが分かっていますので、他のライブラリはそれとの比較という観点で調査をすることにしました。 サンプルプロジェクトについて サンプルは弊社の事業を考えると日本語テキストを扱うものの方がよいだろうと思われました。その上で単純なものであればなんでもよかったので、思い付きのままにAIチャットサービスっぽいものを作ることにしました。 ここに一人のゲーマーが居る。彼または彼女を A としよう。 A は最近ハマっているとあるゲームについて、公式サポートに問合せをするべく Web サイトに訪問した。 サイトにはありがちなよくある質問一覧の他に、「チャットで問い合わせる」というリンクが設置されていた。リンクをクリックするとページ内にチャットウィンドウが立ち上がり「気軽にご質問ください!」という定型的なメッセージが表示された。ウィンドウの下部にはメッセージ入力欄があり、カーソルが誘うように明滅している。 A はしばしの黙考ののち、質問を入力し始めた―― ここで自然な会話のできるAIチャットボットを作れればすごいですが、難易度激ムズな気がするので以下のような動きをするものとしましょう。 訪問者のメッセージを受け付ける メッセージが既存の「よくある質問」のどれに相当するかを分類する 質問の候補をいくつか選択肢として表示する 選ばれた質問に対して事前に設定された回答を表示する (どことなく弊社のとあるサービスに激似ですが、気にしないことにします) 機械学習 が関わってくるのは上の 2 のステップです。比較的短文な日本語文章の多クラス分類問題であると定式化できます。 前回の記事でまとめた内容によれば、ここで 機械学習 を使わない MVP を検討するところではありますが、今回はその辺をすっ飛ばします。また上のイメージのような組み込み先システムの設計も先に考えておくべきところではありますが、これも簡単のためにすっ飛ばして前処理とモデル学習のステップを考えていくことにします。 学習データについて この分類問題では生のデータとしては例えば以下のようなものが得られると想像できます。 メッセージ よくある質問ID ログインできなくなりました。どうしたらいいですか? 1 ログインができず、ゲームがプレイできません。 1 ゲームを始めようとするとエラーが出てログアウトしてしまいます。 1 : : 機種変更しても同じセーブデータで遊べますか? 4 引き継ぎナンバーは一度発行すれば繰り返し使えますか? 4 動作が重いです。 5 ゲーム内で購入したアイテムの情報が反映されません。 6 : : ここで「メッセージ」が推測の入力となるデータ、「よくある質問ID」が推測したいクラスのラベルです。 会員制サイトなどで質問者の属性情報や前後の文脈など追加の情報が得られることもあるかと思いますが、ここでは匿名のユーザーによる単発の質問への対応という想定で上のようなデータをサンプルとして使うとしましょう。 とはいえそう都合よくチャットログデータは持ち合わせていませんでしたので、社内のいろいろな方に協力をお願いして自前で作りました。 クラス数: 96 データ 総数: 6051 クラスごとのデータ数: 平均: 63.0 最大: 199 最小: 16 (改めて統計情報を見てみると、クラス数めっちゃ多いしクラスごとの分布もめっちゃ偏っていてあまりいいデー タセット とは言えない気が…) 具体的なデータの中身は社外秘ということになったので公開できませんが、ゲームのサポートチャットではないということだけ言い添えておきます。 前処理について 元のデータは日本語テキストデータなので、何とかして数値データとして表現しなければなりません。 自然言語処理における前処理の種類とその威力 によれば、テキストデータの前処理は以下のものを行うようです。 テキストのクリーニング 単語の分割 単語の正規化 ストップワード の除去 単語のベクトル表現 文書のベクトル表現 それぞれについて具体的な方法など検討すべき点はあるものの、大まかには上の工程を行えば良さそうです。 テキストのクリーニング テキストのクリーニングは、テキスト内のノイズを除去する工程です。Web ページを スクレイピング して得たデータなどは HTML タグが含まれていたりしますが、これらは推測したいラベルと意味的な関わりの無いノイズとなります。ノイズを除去することでタスクの結果に及ぼす悪影響を抑えることができます。 今回はチャットメッセージの形で蓄積されたデータであり、ほぼ不要と思われるので特に何もしないことにしました。 単語の分割 テキストを 機械学習 の入力とする場合は、数値のベクトルに変換することがよく行われます。その際テキストを何らかの「最小単位」へと分割し、その最小単位が対応する数値ベクトルを使ってテキスト全体を数値ベクトルにするという方法を取ります。 この「最小単位」として何を使うかによって大きく二つの方法があるようです。 形態素 に分ける方法 MeCab や Janome 、 Kuromoji といった 形態素解析 器で文を 形態素 に分解します。 N-gram 法を使って分ける方法 テキストを文字ごとに分け、各文字の後ろN文字目までの組によって作られる「 N-gram 」を最小単位とする方法です。 今回の実装では 形態素 に分ける方式を取りました。理由としては 参考記事が 形態素 にしか触れていない 文法的に意味のある単位の方がそれっぽい 実装も容易 という点が挙げられます。 使用した 形態素解析 器は以下の通りです。 Python : Janome JVM : Kuromoji どちらもそれぞれの環境で導入が容易であり、使用方法も簡単であったためこれらを選びました。辞書は何を使うかも検討しなければいけないところですが、今回は簡便にどちらも IPA 辞書を使っています。 単語の正規化 単語の正規化では全角半角などの文字種の統一、表記揺れの吸収といった処理をすることで、意味的に同じ単語を同じものとして扱えるようにします。 文字種の統一 日本語文字は全角に 英数字記号は半角に 数字の置き換え 数字はすべて 0 に置き換え 単語の統一 形態素解析 から原形を使う ストップワード の除去 ストップワード は 自然言語処理 の際に一般的で役に立たない等の理由で処理対象外とする単語のことです。「てにをは」のような助詞や助動詞、「あれ、それ」などの代名詞といった単語はどのような意味のメッセージにも登場し、内容の推測には役に立たないため除去します。 ストップワード の除去には様々な方式があるようですが、ここでは日本語の ストップワード 辞書の一つである Slothlib を使い、これに含まれる語は除去することにしました。 単語のベクトル表現 これまでの工程できれいになった単語を、数値ベクトルに対応させます。ベクトル化するのにも様々な手法が存在するようですが、主なものは以下の2つのようです。 one-hot表現 分散表現 one-hot表現は各単語を単位ベクトルに対応させます。シンプルで分かりやすい方法です。 分散表現は Word2Vec みたいなやつですね。one-hot 表現からさらに加工して得るもののようです。 どちらを使うかはこの後の文書のベクトル表現の種類によって決まってきます。 文書のベクトル表現 前工程で決めた単語ごとの数値ベクトルを用いてテキスト全体の数値ベクトルへの対応を作ります。単語ベクトルと同じく主な手法は2種類に大別できます。 one-hot 表現からは文書に含まれる単語のベクトルを足し合わせた Bag of Words となります。さらに単語の出現頻度と逆文書頻度の積で単語を重みづけすれば TfIdfベクトル です。 分散表現での文書ベクトル表現は Word2Vec で得た単語ベクトルを足し合わせたり、 doc2vec を使ったりで得ることが出来ます。 今回のサンプル実装に先立っての事前調査で、scikit-learn に TfIdf ベクトルを計算するための API が用意されており、また仮に自前で実装したとしても何とかなりそうということで、Tfidf ベクトルを使うことにしました。 モデル学習について 分類 アルゴリズム は各ライブラリ、サービスごとに用意されたものを使うことになると想定されました。それぞれのライブラリ、サービスによっては実装されていない アルゴリズム もあるかもしれず、ここはあえて統一せずに使えるものを使うという方針にしました。 ただし選定の際のガイドとして scikit-learn のアルゴリズム選定チートシート を使用しました。 これによれば、今回のサンプルプロジェクトにおけるデー タセット 規模やタスクの性質から、線形 SVM 分類器、あるいは単純 Bayes 分類器が良いとのことです。そのため単純 Bayes 分類器が使える場合はこれを使うようにしています。 学習のそのあと 学習されたモデルはシステムへ組み込まれサービスとして運用されるのがまっとうなプロジェクトの進み先ですが、今回はサンプルプロジェクトなので評価指標の算出までで実装完了とします。 算出した評価指標は以下の通りです。 混同行列 正解率 適合率、再現率、F 値 加重平均 マクロ平均 実装を終えての所感 Python + scikit-learn scikit-learn は Python の代表的な 機械学習 の オープンソース ライブラリです。 改めて調べてみても、やはり デファクトスタンダード となっていると納得せざるを得ませんでした。 API が非常に充実している インターフェースの統一された API データ分割、ハイパーパラメータチューニング、性能評価、可視化もできる ドキュメントも充実している ググればサンプルがたくさん出てくる 特にインターフェースが統一され、かつ充実した API は非常に便利であり、 機械学習 を試したいならまずこれ触れば間違いはなさそうです。 Python + H2O H2O is an open source, in-memory, distributed, fast, and scalable machine learning and predictive analytics platform that allows you to build machine learning models on big data and provides easy productionalization of those models in an enterprise environment. H2O ドキュメントトップページ より引用 とあるように、H2O はライブラリというよりかはプラットフォームのようです。 Python からその機能を使うこともできるし、 アーキテクチャ を見れば Java や Scala , R などからも使うことが出来るとわかります。また scikit-learn のパイプラインに組み込むことが可能だったりと他ライブラリ、プラットフォームとの連携にも考慮されている点もいいですね。 また AutoML という機能もあり、自分でコードを書かずともデータを与えれば自動でいい感じに学習してくれるようです。 ただ今回は AutoML は使わず、自分で Python のコードを書いて実装しました。 scikit-learnと比較して 分類 アルゴリズム には単純 Bayes 分類器を選びました。出来上がったコードは自体は scikit-learn のものと比べ記述量や難易度は変わらない印象を受けました。 ただ H2O を使って実装してみた系の日本語記事が少なく、参考にできるのは公式ドキュメントのサンプルコードのみというのがつらいところ。 公式チュートリアル もありますが、中途半端なコードだったりで情報量が少なく、事前に scikit-learn などで実装した経験がないとなかなかしんどいかと。 また H2O はモデルの学習部分にフォーカスしているためか、テキストのベクトル化といった前処理に関して特に組み込みの API があるというわけではなさそうでした。そのため Tf-Idf ベクトル化は scikit-learn の API を使うなどする必要があります。 JVM 系 + Smile Smile is a fast and comprehensive machine learning engine. Smile は JVM 上で利用できる 機械学習 エンジンで、 Java や Scala など好きな JVM 言語で使うことが出来ます。組み込む先のシステムが JVM 言語で作られているのであれば、 機械学習 関連のコードとアプリケーションのコードで言語を揃えられるのが良いですね。 実行速度に優れ、 自然言語処理 、統計処理、データ可視化も Smile の API でできると謳われています。 scikit-learnと比較して ライブラリの特徴というよりかは言語的な特徴になりますが、 Scala での実装は説明的で分かりやすくなるように感じました。ただ Java で実装した場合、型表記が面倒か抽象的過ぎるかになりそうという印象でもあります。 Smile そのものに言及すると、 インターフェイス が独特で scikit-learn などとは差が大きく、結構慣れるのに時間がかかりそうです。使ってみた系の情報が少ない点もネックになるかなと思われます。 また分類 アルゴリズム は豊富に用意されているもののハイパーパラメータチューニングなどの便利 API などはなさそうで、そのあたりを自前で実装しなければならないあたり不便という印象がぬぐえません。 Apache Spark Apache Spark は巨大なデータに対して高速に分散処理を行うための フレームワーク です。 Java や Scala 、 Python などいろいろな言語での API が用意されています。 分散処理のための フレームワーク なので汎用的に使えるのですが、 機械学習 のための コンポーネント が組み込まれていることから 機械学習 ライブラリとしても使用することが出来ます。 先にも触れたようにいろいろな言語で使用することが出来ますが、今回は Scala から使ってみました。 scikit-learnと比較して Spark の 機械学習 コンポーネント が提供する API のインターフェースは scikit-learn のように統一されており、Smile より使いやすい印象です。 組み込みで前処理やハイパーパラメータチューニングができたりと機能も充実しており、使い勝手だけを見れば scikit-learn とも遜色ないように思えます。 今回 Windows 上での環境構築をしてみましたが、 インストーラ を起動しなければならないあたり面倒でした。 Linux や Mac であればコマンドでインストールできるのでその点は問題にはならないと思われます。 マネージドサービスで Spark を使えるものが多いため、そういったサービスで使う場合もよさそうです。 Amazon SageMaker Amazon SageMaker は AWS 上で提供されている完全マネージド型の 機械学習 サービスです。 Amazon SageMaker というサービスの下に Amazon SageMaker Studio Amazon SageMaker Ground Truth Amazon Augmented AI Amazon SageMaker Studio Notebooks ... といった機能が用意されています。 今回は自前で前処理等の部分を実装する想定だったため、 Amazon SageMaker Studio Notebooks を使って自分で実装した Python コードを実行しました。 scikit-learnと比較して 組み込み アルゴリズム について sagemaker というパッケージを読み込むことで組み込み アルゴリズム や Amazon SageMaker 独自の アルゴリズム やモデルを使用することが出来ます。 ただ提供されている アルゴリズム も限られていること、ドキュメントやサンプル実装の情報は存在するものの少ないことから、あえて組み込み アルゴリズム を利用するメリットは感じられませんでした。 Amazon SageMaker 上で scikit-learn コードを使用する方法もドキュメントに記載があることから、Notebook 上で自分でコードを書くのであれば scikit-learn を利用しておけばよいのではないかという印象です。 活用について 学習したモデルと AWS Lambda、 Amazon API Gateway を組み合わせることで、 HTTPS エンドポイントを作成することができます。 作成したモデルを用いて手早くアプリケーションを作成したい場合には有用そうです。 AI Platform AI Platform は Google Cloud 上の AI 関連サービスのブランドです。 2020/3/10時点でまだベータ版。そのためメニュー上でもかなり下の方に配置されています。 AI Platformというブランドの下に AI Platform Notebooks AI Platform Training AI Platform Prediction Data Labeling Service(ベータ版) Deep Learning VM Image Deep Learning Containers(ベータ版) ... とたくさんのサービスがぶら下がっています。 AI Platform Training ではト レーニン グデータ、検証データ、テストデータと分けて GCS( S3 の GCP 版)に格納することで組み込み アルゴリズム による学習も行える様子。 ただ今回は自前で前処理等の部分を実装する想定だったため、AI Platform Notebooks を使って実装したコードを実行しました。 scikit-learnと比較して 組み込みの アルゴリズム について AI Platform では独自の アルゴリズム などを提供する Python パッケージが用意されているわけではないようです。 そのため今回の実装では結局のところ scikit-learn での実装を AI Platform Notebook 上で実行できるようにしたものとなりました。 その際 GCP で用意されている scikit-learn は 2020/3/10 現在で 0.19.2 だったことでハマりました。最新の 0.22.x 系とは API の非互換の部分が多いので注意が必要です 1 。 環境について Notebooks 環境が用意されているので開発環境構築の手間はかからないのが良いです。 クラウド サービスらしくスペックの変更もすぐに実施できます。 ただデフォルトのスペックが n1-standard-4(4 vCPU / メモリ15GB) + ストレージ 100GB と少し強めなので、軽い処理の実験用につどスペック変更するのが手間でした。 活用について まだベータ版なので正式サービスに導入するには抵抗がありますが、サービスに組み込むための学習モデルの作成プラットフォームといった利用方法であれば問題なさそうです。 またハイスペックな インスタンス を利用することで短期間でのモデル作成が実現できそうとも感じました。 ただし、前処理やモデル生成の処理時間に困っていないのであれば、ローカルで scikit-learn を使うことに対するアドバンテージがないかもしれないというのも正直な感想です。 Azure Machine Learning Azure Machine Learning は Microsoft Azure 上で提供される 機械学習 サービスで、 機械学習 を含む DevOps、MLOps を実現する クラウド 環境です。 機械学習 モデルのト レーニン グ、デプロイ、自動化、管理、追跡というワークフローすべてにおいて使用できるツールが提供されています。 Azure Machine Learning デザイナー や 自動 ML という、コードを書かずにモデルの作成ができるツールもあります。 ただ今回は Azure Machine Learning 上の Notebook で自分で実装したコードを実行しました。 scikit-learnと比較して 組み込みの アルゴリズム について Azure Machine Learning では azureml という Python パッケージが用意されているものの、これは学習 アルゴリズム などを提供するものではないようです。 公式の チュートリアル を見ても、 Python でのサンプルは scikit-learn を使って線形回帰を行っています。 そのため今回の実装では結局のところ scikit-learn での実装を Azure Machine Learning の Notebook 上で実行できるようにしたものとなりました。 活用について AI Platform と同じくサービスに組み込むための学習モデルの作成プラットフォームといった利用方法ができそうです。 ただ Notebook の実行環境としてしか使わないのであれば、ローカルで scikit-learn を使うことに対するアドバンテージがないかもしれないというのも AI Platform と同様です。 まとめ 今回は 機械学習 のライブラリ、サービスの使用感を、単純なモデル学習 スクリプト を実装することで調べました。 単純な学習 スクリプト を自分で実装する限りにおいて、ライブラリやサービスの機能的な面で決定的な違いは無いように思えました。 ただし、普及具合を考えると scikit-learn がやはりおすすめということになります。 scikit-learn は 機械学習 ライブラリの デファクトスタンダード です。それ自体の充実した API 、ドキュメントもさることながら、日本語の解説記事も Web 上にあふれています。 Python の環境さえ作ればライブラリのインストールも容易であり、学習時やさくっと試したい時に最適でしょう。 今後の展望 今回は非常に単純な 機械学習 タスクに対し、自分で実装するという縛りの下でライブラリやサービスの使用感を調べました。 ですが、 Amazon SageMaker や AI Platform、Azure Machine Learning などを見ていると、Notebook 以外にもいろいろな 機械学習 関連機能、サービスがあります。 プロジェクトの要件にもよるかと思いますが、マネージドサービスを使う利点はそういったサービス群にこそあるのではないかと感じています。 今後機会があればそれらのサービスも触ってみたいものです。 参考 scikit-learn Machine Learning in Python H2O.ai Documentation h2oai/h2o-tutorials Smile - Statistical Machine Intelligence and Learning Engine Apache Spark Amazon SageMaker(機械学習モデルを大規模に構築、トレーニング、デプロイ)| AWS Amazon SageMaker Python SDK — sagemaker 1.51.0 documentation Google Cloud - AI & Machine Learning Products Google Cloud - AI Platform Notebooksベータ版 Azure Machine Learning 最新版を入れ直すことも可能かもしれないが未調査。 ↩
アバター
はじめに こんにちは。新卒1年目エンジニアのdd_fortです。 今回はDockerを勉強しようと思い、CentOS8でDockerの環境構築をしようとした話です。 Dockerが公式サポートされていないCentOS8にDockerを使用するときに躓いた点や気を付ける点を中心にインストール方法を紹介しようと思います。 目次 はじめに 目次 Docker とは リポジトリの追加 Docker のインストール Docker の起動 ネットワークの問題 回避策1:Docker 起動時のオプション 回避策2:firewalld の設定変更 回避策3:パケットフィルタリングツール変更 最後に Docker とは Docker社が開発している、コンテナ型の仮想環境を用いてアプリケーションを開発・配置・実行するためのプラットフォームです。 コンテナ型仮想環境 Doecerのメリット ホストOSを直接アクセスするためオーバーヘッドが少ない 可搬性が高くDockerをインストールすれば、ホストOS環境に依存せず動作する コード化されたファイルを共有することで開発環境のセットアップが容易になる リポジトリ の追加 まず、Docker の リポジトリ を追加します。 $ dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo 以下のようになっていればOKです。 $ dnf repolist repo id repo の名前 状態 AppStream CentOS-8 - AppStream 5,120 BaseOS CentOS-8 - Base 2,126 extras CentOS-8 - Extras 13 docker-ce-stable Docker CE Stable - x86_64 63 Docker のインストール dnfコマンドを使用して dnf install docker のようなコマンドでインストールしようすると依存関係の問題でインストールできません。 回避策として今回は、 --nobest オプションを付けて実行します。 $ dnf install --nobest docker-ce containerd.io この状態のままだと、 dnf upgrade を実行すると Dockerを強制的にインストールしているためエラーが発生します。 そのため、CentOS7 の リポジトリ を利用してcontainerd.io をアップデートします。 $ dnf update https://download.docker.com/linux/centos/7/x86_64/stable/Packages/containerd.io-1.2.10-3.2.el7.x86_64.rpm 以下を実行してエラーが発生しなければOKです。 $ dnf -y update docker-ce Docker の起動 Docker を起動します。 $ systemctl start docker $ systemctl enable docker バージョン確認 $ docker --version Docker version 19.03.8, build afacb8b ネットワークの問題 しかし、CentOS8の場合はこのままではコンテナ内から名前解決ができずdnf 等が使えません。 回避策1:Docker 起動時のオプション コンテナの構築時や起動時に --network host を指定して実行することで解決することができます。 $ docker pull wordpress $ docker run --name wordpress-test --network host -d wordpress 上記は WordPress のコンテナを立てるときのコマンドです。 回避策2:firewalld の設定変更 iptables が動いている場合は、firewalld でNAPTするように設定を変更することで解決することができます。 $ firewall-cmd --add-masquerade --permanent $ firewall-cmd --reload 回避策3:パケットフィルタリングツール変更 根本的な原因としては、CentOS8からパケットフィルタリングツールが iptables から nftables に変わったことです。 (Docker が nftables を設定できないため) CentOS のパッケージフィルタリング構成 CentOS6 : iptables CentOS7 : firewalld(管 理I /F), iptables CentOS8 : firewalld(管 理I /F), nftables iptables を利用するように変更することで解決可能 firewalld を止める $ systemctl stop firewalld $ systemctl disable firewalld iptables をインストール $ dnf install iptables-services iptables を起動 $ systemctl enable iptables $ systemctl start iptables 最後に 私はCentOS8にDockerが公式非対応であること知らずに環境構築をはじめてしまったため、環境構築だけで時間が多く掛かってしまいました。 しかし、CentOS8とDockerの勉強になったのでよかったかなと思っています。 また、CentOS8ではpodman(Docker互換のコンテナエンジン)が使えるみたいなのでそれを試してみるのもいいかなと思いました。 この記事がCentOS8でDockerを使おうとしている人の助けとなれば幸いです。 エンジニア 中途採用 サイト ラク スでは、エンジニア・デザイナーの 中途採用 を積極的に行っております! ご興味ありましたら是非ご確認をお願いします。 https://career-recruit.rakus.co.jp/career_engineer/ カジュアル面談お申込みフォーム どの職種に応募すれば良いかわからないという方は、カジュアル面談も随時行っております。 以下フォームよりお申込みください。 rakus.hubspotpagebuilder.com ラク スDevelopers登録フォーム https://career-recruit.rakus.co.jp/career_engineer/form_rakusdev/ イベント情報 会社の雰囲気を知りたい方は、毎週開催しているイベントにご参加ください! ◆TECH PLAY techplay.jp ◆connpass rakus.connpass.com
アバター
id:radiocat です。カンバンは「チームの現状を良くしたい、何かを変えたい」という思いがカタチとして表れるツールであることを、この1年を通して感じています。 私は2019年4月から現在のチームのマネジメントに携わり、「チームのアウトプットを安定させる」ことを目指してこの1年間を取り組んできました。今回はその1年間をふりかえってみたいと思います。今年度、 配配メール / クルメル の開発チーム(略して「はいくる開発チーム」)は約半数の新しいメンバーが私と同時にJOINして新チーム体制がスタートしました。 いにしえの 開発プロセス の中に一筋のカンバン 配配メールは10年以上の歴史を持つメール配信の老舗サービスです。当時から稼働している機能がいまだに多数存在しているレガシーなシステムなので、開発スタイルもレガシーな流れを受け継いでいました。半年程度先までのタスクが担当者に アサイ ンされ、古来伝来の ガントチャート でリーダーが日々の状況をキャッチアップして 進捗管理 していました。 古来伝来のエクセル ガントチャート そんな開発スタイルの中で少し異質だったのがカンバンの存在でした。スケジュールは ガントチャート で管理しているはずですが、カンバンはどのような目的で使っているのか聞いてみると、各担当者がスケジュールを意識して個人レベルのタスク管理を徹底することで、スケジュールを維持するのが目的でした。 1年前のカンバン しかし改めて振り返ってみるとこのカンバンの運用には課題がいくつかありました。 タスク管理は個人任せ ガントチャート のマスタスケジュールからカンバンへの落とし込みは担当者に依存しており、目測を誤るとスケジュールが守れない 人ごとにレーン分け 全員の状況がわかるようになっていても、みんな自分のレーンに関心が集中しており、他のメンバーの進捗状況に目を向ける余裕はない 見えているのは1日分 1日の状況からは今後のスケジュールが予測しづらく、全体のスケジュールに関心を持つリーダーの不安は解消されない このような課題を抱えながら、はいくる開発チームは新体制で開発を続けていました。 カンバン駆動で漕ぎ着けた史上最大級のリリース 配配メールは2019年秋に『 Bridge 』という新しいプランをリリースしました。新しいプランは配配メールが配信ツールから マーケティング ・サービスへと進化するための高度な機能を提供するという、新チームが始まる前から企画されていた過去最大規模のプロジェクトでした。リリースを控え開発が終盤を迎えた頃、懸念していた課題が問題として顕在化していました。難易度の高い機能のいくつかで開発に大きな手戻りが発生し、スケジュールを リカバリ するため、チームは担当者のフォローやタスクの組み換えに追われていました。このタイミングでの 開発プロセス の変更にはリスクもありますが、このままの進め方では状況の改善が難しいと判断し、できる範囲で課題を改善することにしました。言わば「走りながらフォームを変えて制限時間内にゴールを目指す」作戦です。 1週間スプリントの導入 リリースが迫ってきている中でこれ以上の大きな手戻りは致命的なので、タスクを個人任せにせずチーム全員で助け合って進める必要がありました。しかし、それまでの進め方では熟練者ですら全体状況を見渡すのが難しくなっていました。そのため、スケジュールから逆算した1週間先の目指すべき状態を明確にし、チーム全体で1週間分の計画を立てて進めることにしました。そして、計画した1週間分のタスクを前出のカンバンのウラに貼り出しました。 カンバンのウラを計画に使用 この時点では特定の人に属人化したタスクが多数あったため、「人ごとのレーン分け」はいったんそのまま受け入れました。ただし、誰でもできるタスクは無理に誰かに割り当てるのではなく、できる人ができるタイミングで受け取ってどんどん進めていくことにしました。また、属人化したタスクも含めて毎朝全体の状態を全員でチェックして誰かのタスクが遅れそうならフォローしあってチーム全体で1週間後のゴールを目指すことにしました。 こうして、カンバンを軸とした、1週間の計画と全員で状況を確認する朝会が功を奏し、新プランはこの秋に無事リリースを迎えました。 www.hai2mail.jp 共用カンバンからチームのカンバンへ 「人ごとにレーン分け」の課題が残されたカンバンは、このあとチームを2つのグループに分けることで解消しました。新体制となって半年のまだまだ未成熟なチームでは、総勢8人という体制の中でお互いをフォローしあうには、全体を見渡すにしても助けを求めるにしてもサイズが大きすぎると考えました。4人でコンパクトに使うことになったカンバンは、人ごとにレーンを分けなくても全体の状況を見渡しつつ、個人のタスクが管理できるようになりました。複数人が個人タスクを扱っていた共用カンバンから、全員で一緒にタスクを扱うチームのカンバンに変わったのです。 個人の共用カンバンからチームのカンバンへ これにより、これまで概ね半年サイクルだったリリースサイクルを3ヶ月に短縮し、新プランをリリースしたあとも機能をアップデートし続けることができています。 可視化から 言語化 へ カンバンを使って開発タスクや課題が可視化されただけでなく、課題に向き合って気づきを得たことでその取り組みを 言語化 してアウトプットできるようにもなりました。以下は取り組みを推進したメンバーが 弊社主催のMeetup で発表したスライドです。 speakerdeck.com 課題の改善に取り組むだけでなく、それを振り返って改めて 言語化 することも大切なことです。チームにはまだまだ課題がありますが、このように取り組みを振り返って一つの区切りをつけることで、新たなステージへの次のチャレンジに向かうことができます。 何かを変えたいという思いからカンバンが生まれ変化が起きた 思えば、1年前チームが使っていたカンバンは今となっては使いにくいものでした。 しかし、それは言い換えれば「何かを変えたいけど変えれない」状態が使いにくいカンバンとして表れていたとも言えます。うまくいかないから止めるのではなく、うまくいかないことをいかにうまく活かすかが改善であると気づけたのがこの1年の学びです。 チームで計測したあるパフォーマンス指標に目を向けると、タスクが個人に依存して乱高下していたパフォーマンスは、カンバン駆動で改善に取り組んで以降は安定しています。 チームのパフォーマンス 前述のとおりチーム体制と開発する機能の難易度が変わったため高低差は一概に比較できませんが、この指標をもっと高い位置で安定させていくことが次のステージのチャレンジです。 配信ツールから マーケティング ・サービスへ メール配信は受信側に依存することが多い不確実性の高い技術です。新プランをリリースした現在の配配メールは、単にメールを届けるだけにとどまらず、お客様の マーケティング を支えるサービスとして活用されています。 マーケティング もまた不確実性の高いビジネスの手法です。 届くかわからない 読むかわからない クリックするかわからない サイトを再訪するかわからない 熱感が上がるかわからない 購入意志を持つかわからない 不確実性と向き合い、これらの「わからない」を「わかる」に変えていくことが、今後の私たちのチャレンジです。 取り組みを発信していきます 私たち「はいくる開発チーム」は、同じような課題に取り組んでいる中小企業のエンジニアチームが”楽”になることを目指して、自分たちの取り組みを発信しています。今後、以下のイベントでも取り組み事例をお伝えする予定です(新型コロナウィルスの影響によりイベントの開催は現時点では不透明ですが、何らかの形で事例はお伝えできると思います)。よろしければご参加ください。 2020.agilejapan.jp www.scrumosaka.org
アバター
はじめに 花粉がつらくなってきました... sts -250rrです。 開発エンジニアとして、チームに アサイ ンされて1年が経とうとしています。(速い) 私が担当している商材は主に Java で書かれているため、普段は JVM 上で動くアプリケーションに意識が行ってしまいがちで、そもそもアプリケーションがどうやって動いているなど ( Tomcat 上でアプリケーションを動かしているということは漠然と理解していますが...) OSレベルまで掘り下げして理解できていないように感じています。 今回は基礎に振り返るという意味で Linux のプロセスについてまとめていきます。 (本記事のコマンドはUnixOS系である MacOSX で実行しています。) はじめに プロセスって何? マルチプロセス プロセススケジューラ コンテキストスイッチ プロセスの状態 コマンドで確認 ゾンビプロセス まとめ 参考資料 プロセスって何? プロセスとは、「OS上で実行中のプログラム」を指します。 プロセスが動いているということは、コンピュータリソース(CPUやメモリなど)を消費している状態です。 例えば、 Linux コマンドは1つのプログラムであるため、コマンド実行時にプロセスを1つ作成します。 この間、プロセスはCPUやメモリを消費してプログラムを実行しています。 プロセスの特徴には以下のようなものがあります。 1つのCPU上で同時に処理するプロセスは1つだけ 複数のプロセスが実行可能な場合、個々のプロセスを適当な長さの時間ごとにCPU上で順番に処理する。 psコマンドを叩いてみると複数のプロセスが動いているように見えます。 (ターミナルを2枚開いた状態で1枚目はPostgresに接続、2枚目でpsコマンドを実行 することで2つのプログラムが動いている状態を用意しています。) $ ps -a PID TTY TIME CMD 17239 ttys001 0:00.02 login -pf sts 17240 ttys001 0:00.03 -bash 17642 ttys001 0:00.00 ps -a 15351 ttys017 0:00.03 login -pf sts 15352 ttys017 0:00.12 -bash 17237 ttys017 0:00.01 psql -U postgres -p 5432 PC上の操作でも複数の処理を同時に動かすことがあるように、 実際のWEBアプリケーションにおいても、 Apatch と Tomcat 、データベースが同時に動いて1つのサービスとして機能しています。 これを実現しているものが次項のマルチプロセスになります。 マルチプロセス マルチプロセスは複数のタスクを並行して実行する機能のことを指しますが、 Linux は厳密には同時並行で処理を行うことを実現してはいません。 Linux がやっていることは人が認識できない時間でプロセスを区切り、順番に処理することで複数のプロセスが同時に処理をしているように振る舞っています。 プロセススケジューラ 複数のプロセスが同時に処理をしているように振る舞うようにするため、 Linux はプロセススケジューラという機能を持っています。 例えば3つのプロセスを同時に処理する場合、プロセススケジューラによって以下のようにプロセス0 → 1 → 2 と処理を行っていきます。 また、プロセスの処理は以下のように並列で進んでいきます。 プロセスを短い間隔(タイムスライス)に区切り、1つのCPU上で動くプロセスを切り替えることで複数のプロセスが同時に処理しているように振る舞っています。 タイムスライスはそれぞれ等しいくらいの長さで区切られ、プロセスが増えるとタイムスライスの数が増えるため1つのプロセスが完了するまでに時間がかかります。 コンテキストスイッチ 1つのCPU上で動くプロセスがタイムスライスで切り替わることを コンテキストスイッチ と呼びます。 コンテキストスイッチ は、タイムスライスの時間が切れると容赦なく発生します。 例として、プロセス1 → 2 と順に実行する1つのプログラムがあったとします。プログラムの実行中にプロセス1が起動した場合、プロセス1 → 3 → 2 という順序で実行される可能性があります。 1プログラム以外の要因(他のプロセスが間に起動したなど)によって完了時間が伸びる可能性があるという点が コンテキストスイッチ によるプロセス特性の1つです。 プロセスの状態 ここまでで記載したように、1つのCPU上で動くプロセスは切り替わるため、プロセスは実行状態・スリープ状態などの複数の状態を持っています。 以下にプロセス状態の一例をあげます。 状態 意味 実行状態 CPU使用状態 実行待ち状態 CPUが割り当てられるのを待っている スリープ状態 イベントの発生を待っている(CPUは使っていない状態) ゾンビ状態 終了状態の受け取りを待っている プロセスの状態は以下のように遷移します。 プロセスはプロセススケジューラに基づき、CPUの実行権を得ると実行待ち状態から実行状態に遷移し、処理をすべて完了するまで、タイムスライス区切りで状態を遷移し続けます。 プロセスは終了状態を得ることで終了となります。 コマンドで確認 Mac 上でtopコマンドを実行してみると以下のような出力になりました。(上部10件まで) Processes: 418 total, 5 running, 413 sleeping, 1787 threads 19:16:35 Load Avg: 1.97, 3.00, 4.61 CPU usage: 7.7% user, 26.88% sys, 66.3% idle SharedLibs: 295M resident, 33M data, 29M linkedit. MemRegions: 109880 total, 3310M resident, 119M private, 1551M shared. PhysMem: 8606M used (2803M wired), 7777M unused. VM: 1959G vsize, 1882M framework vsize, 2689796(0) swapins, 2881396(0) swapouts. Networks: packets: 58205899/34G in, 48094735/17G out. Disks: 5133929/94G read, 2715156/54G written. PID COMMAND %CPU TIME #TH #WQ #PORT MEM PURG CMPRS PGRP PPID STATE BOOSTS %CPU_ME %CPU_OTHRS UID FAULTS COW MSGSENT MSGRECV SYSBSD SYSMACH CSW PAGEINS 3075 VBoxHeadless 59.5 01:52:54 39/2 5 996 908M 0B 47M 3075 3060 running *0[2] 0.00000 0.00000 501 272297 390 4904505+ 110938+ 80020677+ 12095394+ 56986420+ 760 0 kernel_task 28.9 01:47:26 172/4 0 0 105M 0B 0B 0 0 running 0[0] 0.00000 0.00000 0 173910+ 0 100809447+ 97799283+ 0 0 429621385+ 0 14655 firefox 15.0 04:38.25 61 4 775+ 443M+ 9384K 81M- 14655 1 sleeping *0[1192+] 0.00000 0.06446 501 1835132+ 15875 940954+ 304755+ 2763928+ 3000384+ 1945509+ 33761+ 15349 Terminal 6.4 00:11.47 9 4 261- 72M 33M+ 0B 15349 1 sleeping *0-[368+] 1.14998 0.42402 501 149598+ 491 55408+ 13334+ 134496+ 142201+ 63838+ 2824 2303 com.docker.h 5.6 02:01:48 15 0 38 2355M 0B 304M 2288 2300 sleeping *0[1] 0.00000 0.00000 501 725271 446 785 317 207705774+ 465 126169989+ 68 15698 top 4.3 00:01.43 1/1 0 25 5284K 0B 0B 15698 15352 running *0[1] 0.00000 0.00000 0 11303+ 109 489446+ 244672+ 39445+ 314731+ 1968+ 0 226 WindowServer 3.1 15:54.83 10 5 1377- 447M 19M 47M 226 1 sleeping *0[1] 0.38155 0.00856 88 1809748+ 8936 13705840+ 6222509+ 5598080+ 19197483+ 7974577+ 9094 188 hidd 1.9 02:39.48 5 3 241 3492K 0B 664K 188 1 sleeping *0[1] 0.00688 0.00000 261 83167+ 171 629366+ 489469+ 5409421+ 1849976+ 2190289+ 5218 265 airportd 1.1 03:49.45 12 10 1385+ 13M+ 0B 5144K- 265 1 sleeping *14180[212] 0.00000 0.93819 0 243908+ 268 5776050+ 2282663+ 11177993+ 5077848+ 4985570+ 2748 171 locationd 0.6 01:34.95 7 5 231+ 8600K+ 192K 1420K 171 1 sleeping 0[22641] 1.15398 0.00000 205 207357+ 338 357612+ 97377+ 3218875+ 737171+ 876386+ 12727 まだまだ情報量が多く見づらいので、Terminalとtopコマンドだけ抜粋します。 PID COMMAND %CPU TIME #TH #WQ #PORT MEM PURG CMPRS PGRP PPID STATE BOOSTS %CPU_ME %CPU_OTHRS UID FAULTS COW MSGSENT MSGRECV SYSBSD SYSMACH CSW PAGEINS 15349 Terminal 6.4 00:11.47 9 4 261- 72M 33M+ 0B 15349 1 sleeping *0-[368+] 1.14998 0.42402 501 149598+ 491 55408+ 13334+ 134496+ 142201+ 63838+ 2824 15698 top 4.3 00:01.43 1/1 0 25 5284K 0B 0B 15698 15352 running *0[1] 0.00000 0.00000 0 11303+ 109 489446+ 244672+ 39445+ 314731+ 1968+ 0 topコマンドは今正しく動いているプログラムであるため状態は実行中(running)となっています。 対して、Terminalはtopコマンドの実行後、入力待ち状態となったためスリープ状態(sleeping)となっています。 手元で実行していただくとわかるかと思いますが、topコマンド実行中にコマンドを終了させてみたり、新しく実行してみたりすると プロセスの生成や状態がみるみる変わっていく様子を見ることができます。 ゾンビプロセス IDE などで開発をしている中で、「既に8080ポートが使われている」などの理由でアプリ起動に失敗した経験が皆さんにもあるのではないでしょうか? そんな悪さをしているのがゾンビプロセスです。 ゾンビプロセスが生まれてしまう原因は様々ですが、 一定時間子プロセスからの返答がなかったことから、 タイムアウト として親プロセスを終了してしまい子プロセスが宙に浮いてしまう。 というものがよくある1つの例かと思います。 「親プロセスが終了したからといって子プロセスもあわせて勝手に終了するわけではない」と覚えておきましょう。(その逆もしかりです。) ゾンビプロセスができてしまったときは対象のプロセスを調べ、Killして対処しましょう。 まとめ 雑多になりましたが、 Linux のプロセスについてまとめていきました。 書籍やブログ記事などで知識を得ることはできますが、なにぶんOSの裏の動きは実際に手を動かしてみないとピンとこないものです。 コマンドは知っていても見方や期待される状態は知識のみでは補えない点も多いかと思います。 コーディングに疲れて一息つくときなどにpsコマンドやtopコマンドをボーっと眺めて、変化が起きる瞬間をウォッチしてみると面白い発見や知識がつながる瞬間があるかもしれません。 また、 Linux コマンドの一覧表を以下ブログにてまとめておりますので、ご参考ください。 よく使うLinuxコマンド一覧【最新版】 Linux の理解をより深めたい方へ以下関連おすすめブログ ・ ls コマンド 【使い方 まとめ】 ・ find コマンド 【使い方 まとめ】 ・ iptables まとめ【Linux ファイアウォール】 ・ sed コマンド【使い方 まとめ】 ・ vi コマンド【使い方まとめ】 ・ Linuxのファイル操作でよく使うLinuxコマンド ・ 初心者のためのawkコマンド ・ 実務で使える!基本的なシェル(Linux)コマンドの話 ~forとsed~ 参考資料 [試して理解]Linuxの仕組み ~実験と図解で学ぶOSとハードウェアの基礎知識~ エンジニア 中途採用 サイト ラク スでは、エンジニア・デザイナーの 中途採用 を積極的に行っております! ご興味ありましたら是非ご確認をお願いします。 https://career-recruit.rakus.co.jp/career_engineer/ カジュアル面談お申込みフォーム どの職種に応募すれば良いかわからないという方は、カジュアル面談も随時行っております。 以下フォームよりお申込みください。 rakus.hubspotpagebuilder.com ラク スDevelopers登録フォーム https://career-recruit.rakus.co.jp/career_engineer/form_rakusdev/ イベント情報 会社の雰囲気を知りたい方は、毎週開催しているイベントにご参加ください! ◆TECH PLAY techplay.jp ◆connpass rakus.connpass.com
アバター
こんにちは、takaramです。 メール配信サービス 配配メール / クルメル の開発チームでは昨年、 はいくる通信 と題し、メール配信に関する技術・ノウハウをご紹介しました。 今回はその続編として、 配信エラー解析 についてお話したいと思います。 配信エラー解析とは 配信エラー解析のしくみ 二種類のFromアドレス 配信エラーと到達率 まとめ 配信エラー解析とは 「自分の送ったメールが届かなかった」という経験はあるでしょうか?メールの送信に失敗する原因としては、例えば以下のようなものがあります。 メールアドレスが間違っている 相手の メールボックス が満杯になっている 相手に受信拒否されている サーバ間で通信に失敗した 特に メールマガジン などの一斉配信においては、配信エラーは珍しくありません。内容に興味がなくなった読者に受信拒否されたり、そもそも登録したアドレスが間違っていたりといったケースです。 エラー理由によって解決策は全く変わってくるため、メールが届かないとの問い合わせを読者から受けた際にはまず理由を把握する必要があります。また、配信エラーを放置し届かないメールを送り続けることはコストの無駄になってしまいます *1 。 そこで、我々の開発している配配メール/クルメルには 配信エラー解析 機能があります。 配配メールの配信エラー解析( 配配メールWebサイト より) 配信に失敗したアドレスとその理由がわかるほか、配信エラーが一定回数発生するとそのアドレスへの配信を自動で停止します。アドレス間違いなどの恒久的なエラーの場合は1回、メー ルボックス の容量オーバーなどの一時的なエラーの場合は3回の配信エラーで配信を停止します(回数は設定で変更可能)。 しかし、一斉に配信したうちのどのアドレスがなぜ配信エラーになったのか、どうやってわかるのでしょうか。 配信エラー解析のしくみ みなさんはこのようなメールを受け取ったことはありませんか? これは バウンスメール と呼ばれるもので、送信したメールが相手に届かなかったことを知らせるメールです。受信拒否などの場合は 送信先 サーバから、アドレスの@以降が間違っている、 送信先 サーバへの接続に失敗したなどの場合は送信元サーバからバウンスメールが送られます。 ではバウンスメールの宛先はどのアドレスかというと、もちろんメールのFrom(差出人)アドレスです。とはいっても、ここで言うFromアドレスは、みなさんが思い浮かべるものとは少し違っています。 二種類のFromアドレス メールの送受信の際、サーバやPCの間では以下のようなデータがやり取りされています。 Date: Mon, 9 Mar 2019 12:34:56 +0900 From: taro@example.com To: hanako@example.jp Subject: Test Mail こんにちは! 本文は「こんにちは!」の一行だけですが、件名や送信日時などが書かれた メールヘッダ が付け加えられています *2 。ここでFromに書かれているのが受信者が目にするFromアドレスで、 ヘッダFrom と呼ばれます。メルマガなら通常メールを作成した会社やブランドのアドレスになります。 一方、メールデータ(メールデータ+本文)を送信する際、送信元サーバはメールヘッダとは別に差出人と宛先のアドレスの情報を送信します。このFromアドレスを エンベロープ From といいます。ヘッダFromと違い、基本的にコンピュータ間の通信用にのみ使われるアドレスで、配配メールを使って送信したメールなら配配メールのサーバのアドレスになります。バウンスメールはこの エンベロープ From宛に送信されるのです。 メール送受信のイメージ 配配メールでは、一斉配信でも一通一通異なる エンベロープ Fromを利用していて、アドレスの中にメールIDや読者IDなどの情報が含まれています。そのため、受信したバウンスメールの宛先を見れば、誰が誰に送ったどのメールが配信エラーになったかがわかるのです。 ではエラー理由はなぜわかるかというと、バウンスメールの本文を解析しています。文面はバウンスメールを送信するサーバのソフトウェアによって異なりますが、そこに含まれるフレーズを元に判定をします。例えば「user unknown」というフレーズが含まれればアドレス間違い、「Rejected as spam 」が含まれれば受信拒否、といった形です。 配信エラーと到達率 ここまで配信エラー解析のしくみをご紹介しましたが、実はこの機能、 我々のサービスの質を守る ためにも重要なのです。 もし配信エラー解析機能がなく、利用者が配信エラーに気づかなければ、使われていないアドレスにもメールを送り続けることになります。これは 第1回の記事 で紹介した「 IPレピュテーション 」を下げる要因となります。 すなわち、受信サーバが配信サーバを「 適当なアドレスにメールを送りつけるスパムサーバ 」と認定し、メールを受け付けてくれなくなるのです。 メール配信サービスとしてメールをしっかりと届けるためにも、配信エラー解析は重要な機能なのです。 まとめ メール配信サービス 配配メール/クルメルの配信エラー解析のしくみ、ご理解いただけたでしょうか? 利用者が配信の状況を把握できるだけでなく、サービス全体の到達率を維持するためにも重要な機能となっているのです。 *1 : メール配信サービスの利用料金は、一般的に配信通数やアドレス登録数で決まります。 *2 : 実際は本文の 文字コード 、返信先アドレス、メッセージIDなどもっと多くの情報が書かれています。
アバター
こんにちは。 本日は ソフトウェアテスト の教科書 JSTQB の内容と実際に業務に反映した例をご紹介します JSTQB とは 日本における ソフトウェアテスト 技術資格認定の運営組織です。 ISTQB(International Software Testing Qualifications Board)という ソフトウェアテスト 技術者の国際的な資格認定団体がありますが、 JSTQB はその日本版にあたります。 いくつかテストに関する出版をされていますが、私が選んだ本は以下に掲載します。 ソフトウェアテスト教科書 JSTQB Foundation 第4版 シラバス2018対応 選んだ理由は下記の通りです。 ソフトウェアテスト を体系的に学べること 最新かつ網羅的なテスト技法を習得できること( シラバス 2018対応は2020年2月テストより実施) 資格試験の取得にもつながること テストの目的 そもそもテストの 目的 ってなんでしょうか。というところから本書では書かれています。 テスト期間、テスト 工数 (実施する時間)、メンバーのスキルレベル、開発担当者との関わり方などなど その条件によってもテストの 目的 は変わってきます。 要件を満たしている 妥当性の確認 ステークホルダー が判断できる情報提言 品質レベルのリスク低減 契約・法律・規約の検証 故障や欠陥を発見する 欠陥の作りこみを防ぐ 品質レベルの確認 評価 など、その目的は多岐にわたります。 製品を開発する上でもいくつかの観点がありますね。 機能追加の案件なんかは製品企画やお客様とお約束した要件を満たしているかチェックが欠かせません。 また、新しい機能を追加すればするほど、今まで当たり前のように動いていた機能は これからも当たり前のように動くことを保証しなければなりません。 言うのは簡単ですが、実際に実践するのは難しいです。 機能を追加すると思わぬところに影響を及ぼしたり、処理を追加しなければいけないところが漏れていたりと 大規模な製品ほど品質レベルを維持するのは難易度が高くなりますよね。 そんな難しい観点を網羅的にテストする一つのツールとして本書からヒントを得られればと思います。 ※実際の品質を保証するものではないので、利用状況に応じて善にも悪にもなるところは注意が必要です。 テストの7原則 目からウロコだったので、詳しくレポートします。 テストは欠陥がないことは示せない 確かにそうですね。 アプリケーションの ホワイトボックステスト をすべて網羅したとしても、 顧客が実際に動作させるOS/ブラウザの状況はすべて再現できるわけではありません。 どんなにテストしても「絶対に100%欠陥はありません!」ということを言い切るのは難しいですし、 正確な情報ではありません。 もちろんバグが限りなく0になるようにテストはすべきです。 全数テストは不可能 例えば、画面に文字を打てる入力欄があった時点で無理です。 ローマ字26文字×2(大文字、小文字)、ひらがなカタカナは濁音や半濁音を含まなくても50文字ずつ、漢字は・・・。 その組み合わせは実質無限であり、どこまでいっても全パターン網羅ではありません。 早期テストで時間とコストを節約 ソフトウェアテスト の特徴として、V字モデルがよく話に出ます。 要件定義に何か問題があった場合は、最も 下流 工程の システムテスト で見つかったり、 詳細設計や実装などの問題は 単体テスト を見つかったりと、 問題があったときに検知できるフェーズがV字のような形なので問われています。 テストにおけるコスト同じで、品質における問題が発見されるのが、 後の工程ほど上流工程に戻って修正するコストが多く発生します。 なるべく早期に問題を発見することでリリースまでの時間の節約につながります。 欠陥の偏在 テストにおける欠陥の8割はプログラムの2割部分に集中して存在する説があります。 見落とした観点と、見落としに関連する観点が依存しているからだと思いますが、 私の経験上も感覚が近いので、その通りかと思います。 殺虫剤の パラドックス 特定の虫に同じ殺虫剤を与え続けても、いずれ虫のほうが殺虫剤に対する免疫をつけるため、 どんどん効果が薄くなることを例にしています。 ソフトウェアテスト においても同様で、同一観点で何度テストしても問題の検知がし難いです。 テスターを変える、やり方を変える、観点を変えるなど何かしら前回のテストと差をつけて 取り組むことが必要です。 テストは状況次第 上述した目的から、テストの在り方が変わってきます。 24時間稼働のシステムであれば過負荷でもシステムダウンしないこと、 eコマースであれば外部に公開するのでセキュリティ面で問題ないか念入りにチェックします。 「バグゼロ」の落とし穴 ある観点ではバグがない状態でも、他の観点ではそうではないケースがあります。 入力欄が4桁しか入力できない問題を解決するために、5桁に変更しました。 「4桁しか入力できない」欠陥はなくなりますが、 代わりにデータベースの書き込み速度が遅くなる、といった新しい問題が発生しました。 その直し方が製品全体を見たときに本当に正しい形をよくよく考える必要があります テストの心理学 人それぞれ立場や理解が異なることから、協力体制を考えねばなりません。 心に刺さった一例を掲載します。 <一例> 開発担当者の心情として下記があげられます。 何度もテストしたから実装コードが正しいはずだ(確証バイアス) テスト担当者よりも製品の仕様をよく知っている(指摘を受けにくい) こうなってしまうと「開発担当者 vs テスト担当者」の対決構図になってしまいます。 「良い品質の製品を納品する」という共通認識のもと、協力体制で行わなければなりません。 テストで発見した指摘は下記の効果があります 欠陥情報の把握 品質向上 開発担当者の スキルアップ コスト削減 お互いの信頼のために、開発担当者は否定的に反応した理由を、テスト担当者は理解する努力が必要です。 相互の認識の確認と、顧客の問題を解決することが目的であるという認識のもと 製品の製造を進めていくことが大事ですね。 カバレッジ 上述した全件テストが不可能という話がありましたが、その中でもなるべく網羅的に テストがすることが求められています。 カバレッジ とはテストケースを利用して特定のアイテムを実行したときの度合いを示した式になります。 デシジョンカバレッジ(%)= (テストにより実行した判定結果の数 / テスト対象の判定結果の合計数) × 100 これをどれだけあげられるかが欠陥が限りなく0に近い製品を生めるかのポイントになります。 カバレッジ の実践 実際にある案件のテストケースレビューでこの観点を取り上げる場面がありました。 伝票のヘッダーに対して明細が1:2のテストをするとき、 「複数明細の伝票」という観点でテストケースが生成されていました。 しかしユーザーの操作は明細がいくつも作れるので、1:2だけのテストでは不十分です。 もちろんテストに対する 工数 も有限なので実施できるパターンはやはり限られます。 しかし カバレッジ を少しでもあげることは、欠陥の少ない製品に近づけるので 時間の許す限り、実践していくのが良いと判断し、メンバーに追加のテストを依頼しました。 テスト技法 一般的に紹介されていました。 個々の詳しい説明については割愛します。 ブラックボックステスト プログラム内部は参照せず、画面/ API などのUIから思いつく操作を実施する手法です。 ホワイトボックステスト  プログラム内部を参照し、分岐処理を網羅的に打鍵する手法です。 同値分割法  条件的に同じ判定になりうるパターンはグルーピングして一つのパターンとみなしてテストする手法です。  例: 6歳未満は無料 6歳から12歳以下は半額 13歳以上は定額 上記の条件であれば、「ありえない」「無料」「半額」「定額」の4つのパターンとみなしてテストします。 境界値分析  同値分割法の一種ですが、どの範囲で同値とみなすかを定めています。  例:20~34歳までの男性がアクセスするとM画面を表示する 2ポイント境界値分析法 3ポイント境界値分析法 デシジョンテーブル それぞれ;の因子を掛け合わせた観点をテストする手法です。 例: ある美術館の入館料は次の通りになっている   個人入館料 大人・高校生:2000円 中学生・小学生:1000円 幼児:600円 学校団体入館料 大人・高校生:1200円 中学生:720円 小学生:600円 幼児:360円   ※ただし、個人・団体を問わず県民の日は高校生以下無料 上記のケースだと全部で19ケース存在します。 ユースケース テスト ビジネスシナリオやシステムの使い方に基づいてテストケースを設計します。 結合テスト に近いです。 ユースケース 名、目的、アクター、事前条件、事後条件、基本フロー、代替フロー、例外フロー、備考など 実際に使われうるケースで要素を考えます。 状態遷移テスト その製品の操作状況によって実施するパターンを遷移していきます。 状態遷移テストの実践 応用して 経理 システムに反映すると下記のようになります。 実際に利用するとパターンが増えるので、より可視化が重要になります。 テストツール それぞれ紹介されていました。 実際の業務で利用されるものばかりです。 要求マネージメントツール  TestLink 欠陥マネージメントツール  Redmine , Bugzillia 構成管理ツール Git, Subversion 継続的 イテレーション ツール Jenkins レビューツール  Redmine 、 Trac 、ReviewBoard 静的解析ツール SpotBugs, Checkstyle テスト設計ツール PictMaster モデルベースドテストツール GraphWalker テスト実行ツール  Selenium , JUnit 要求 カバレッジ ツール OpenClover 性能テストツール  Jmeter 動的解析ツール Valgrind 数々の要素 上述したもの以外にもたくさんの要素がテストに関係しています。 経験ベースのテスト技法 これはエラー推測が重要になります。 アプリケーションの過去の動作状況 開発担当者が犯しやすい誤りの種類 他のアプリケーションで発生した故障 探索的テスト チェックベースドテスト マネージメント、レビューも良いテストを実現するために大きく左右します。 まとめ それぞれの状況に応じてベストプ ラク ティスは異なります。 テスト技法を用いて個々の状況に適したテストを選択できるかがポイントです。 おのおの限りがあるコストの中で重大な欠陥、故障を見つけることが必要になります。 そのために実行するテストの優先順位づけも重要です。 先人が行っていたテンプレートを鵜呑みにせず、テストケースの作成、 テストの実行時に 気づいた観点はすぐ実行することが 重大なシステム欠陥を防止する策になると思います。 エンジニア 中途採用 サイト ラク スでは、エンジニア・デザイナーの 中途採用 を積極的に行っております! ご興味ありましたら是非ご確認をお願いします。 https://career-recruit.rakus.co.jp/career_engineer/ カジュアル面談お申込みフォーム どの職種に応募すれば良いかわからないという方は、カジュアル面談も随時行っております。 以下フォームよりお申込みください。 forms.gle イベント情報 会社の雰囲気を知りたい方は、毎週開催しているイベントにご参加ください! rakus.connpass.com
アバター
logy0704です。 今回は自分のコンテナ知識をアップデートするために調べたことを記事にしようと思います。 動作確認はDocker Desktop for Mac 2.1.0.5, Docker Engine 19.03.5で行なっています。 課題 解決策 結局どっち使えば良いの volume 名前付きvolumeと匿名volume -vと--mount まとめ 課題 基本的にコンテナを消すと中の状態を復元することはできません。 しかし、以下のようなケースでデータの永続化を行いたいことがあります。 データベースコンテナの状態を保存しておきたい。 別のコンテナにデータ移行したい。 解決策 コンテナのデータを永続化させる方法がdockerの機能として用意されています。 主な手段は次の二つです。 volume ホスト側のdocker管理 ディレクト リ以下をコンテナにマウントする。 bind mount ホスト側の ディレクト リをコンテナにマウントする。 結局どっち使えば良いの 公式ドキュメントではvolumeを推奨しています。 理由はいくつかありますが、代表的なものとしては、セキュリティ上の懸念があることが挙げられます。 bind mountの場合、コンテナからホスト側のdocker管理領域以外へのアクセスができるため、 コンテナへ侵入を許した際にホスト側にまで被害が拡大する可能性があります。 とはいえ、一部の ユースケース ではbind mountを使用したほうが望ましいケースもあります。 詳しくは公式ドキュメントを参照してください。 今回はvolumeについてもう少し見ていきます。 volume docker runコマンドに-v(--volume) or --mountを指定することで、volumeをマウントした状態のコンテナを作成することができます。 volume名とコンテナ側の ディレクト リを指定して実行してみます。 $ docker run -d --name sample -v my-vol:/app nginx:latest docker inspectコマンドでコンテナの情報を確認してみると、以下のようにvolumeがマウントされていることがわかります。 " Mounts " : [ { " Type " : " volume " , " Name " : " my-vol " , " Source " : " /var/lib/docker/volumes/my-vol/_data " , " Destination " : " /app " , " Driver " : " local " , " Mode " : " z " , " RW " : true , " Propagation " : "" } ] , docker volume lsコマンドで存在するボリュームの一覧を取得することができます。 $ docker volume ls DRIVER VOLUME NAME local my-vol コンテナ内にファイルを作成してから、コンテナを消してみます。 $ docker exec -it sample bash /# echo "hoge" > /app/hoge.txt $ docker rm -f sample $ docker volume ls DRIVER VOLUME NAME local my-vol コンテナが消えてもvolumeは消えていません。 再度、コンテナを作成し、先ほど作ったvolumeを指定してみます。 $ docker run -d --name sample -v my-vol:/app nginx:latest $ docker exec -it sample bash /# ls /app hoge.txt 先ほど作成したファイルを残すことに成功しました。 名前付きvolumeと匿名volume volumeには大きく次の2種類があります。 名前付きvolume その名の通り、名前を持ったvolumeです。先ほどのmy-volの部分が名前にあたります。 匿名volume 名前を指定しなかった場合に作られるvolumeです。docker側でユニークになるように ハッシュ値 の名前が振られます。 docker run -d --name sample2 -v /app nginx:latest " Mounts " : [ { " Type " : " volume " , " Name " : " a41506ad65ef324b213c6dd6cb246532a264193e8fe6fcda25829119817a0ec5 " , " Source " : " /var/lib/docker/volumes/a41506ad65ef324b213c6dd6cb246532a264193e8fe6fcda25829119817a0ec5/_data " , " Destination " : " /app " , " Driver " : " local " , " Mode " : "" , " RW " : true , " Propagation " : "" } ] , 名前付きvolumeのほうがなんのためのvolumeなのかわかりやすいため、基本的には名前を指定するほうが良いと思います。 -vと--mount volume作成には、-vと--mountの二つのオプションが使用できます。 厳密には挙動が異なる部分がありますが、ほとんど同じものです。 サンプルでは-vを使用しましたが、--mountのほうが新たに導入されたオプションで、直感的に記述できるため、こちらを使うのがおすすめです。 まとめ dockerコンテナのデータを永続化するにはvolumeを使う volumeを作成する際には名前をつけよう 使うオプションは--mountがおすすめ エンジニア 中途採用 サイト ラク スでは、エンジニア・デザイナーの 中途採用 を積極的に行っております! ご興味ありましたら是非ご確認をお願いします。 https://career-recruit.rakus.co.jp/career_engineer/ カジュアル面談お申込みフォーム どの職種に応募すれば良いかわからないという方は、カジュアル面談も随時行っております。 以下フォームよりお申込みください。 rakus.hubspotpagebuilder.com ラク スDevelopers登録フォーム https://career-recruit.rakus.co.jp/career_engineer/form_rakusdev/ イベント情報 会社の雰囲気を知りたい方は、毎週開催しているイベントにご参加ください! ◆TECH PLAY techplay.jp ◆connpass rakus.connpass.com
アバター
こんにちは、新卒1年目のtakaramです。まもなく入社して丸一年となり、ほとんど経験のなかった SQL の力もついてきたと思っています。 しかし、パフォーマンス面も考慮した SQL となると、まだまだ知識が足りないと感じています。 特に、一対多の関連テーブルの一方を使って他方を絞り込む、といった SQL は、ネットを見てもEXISTSが速いという記事があったり相関サブクエリだから遅いという情報があったり……何が本当かよくわかりません。そこで、今回自分で調べてみることにしました。 なお、今回検証に用いたのは PostgreSQL 11.4 です。 検証 テスト用データ 1:2020年入社の社員がいる部署名を抽出 2:開発1課~9課の従業員を抽出 結論 検証 テスト用データ テスト用テーブルとして、従業員テーブル employees と部署テーブル departments を用意し、それぞれ5万件、1000件のレコードを挿入しました *1 。各テーブルはIDと名前のほか、従業員テーブルは所属部署IDと入社年を入れています。 これを使って2種類のデータを抽出する SQL を、それぞれIN, EXISTS, JOINの3パターンで作成し、 EXPLAIN ANALYZE で実行時間・コストを比較しました。 1:2020年入社の社員がいる部署名を抽出 まず、各パターンのクエリはこんな感じです。 -- INパターン SELECT name FROM departments WHERE id IN ( SELECT department_id FROM employees WHERE join_year = 2020 ); -- EXISTSパターン SELECT name FROM departments d WHERE EXISTS ( SELECT 1 FROM employees e WHERE e.department_id = d.id AND e.join_year = 2020 ); -- JOINパターン SELECT d.name FROM departments d INNER JOIN ( SELECT DISTINCT department_id FROM employees WHERE join_year = 2020 ) tmp ON tmp.department_id = d.id; それぞれの実行計画を出してみます。 IN QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------- Hash Join (cost=963.88..994.63 rows=1000 width=12) (actual time=5.690..6.153 rows=720 loops=1) Hash Cond: (departments.id = employees.department_id) -> Seq Scan on departments (cost=0.00..17.00 rows=1000 width=16) (actual time=0.023..0.178 rows=1000 loops=1) -> Hash (cost=954.66..954.66 rows=737 width=4) (actual time=5.651..5.651 rows=720 loops=1) Buckets: 1024 Batches: 1 Memory Usage: 34kB -> HashAggregate (cost=947.29..954.66 rows=737 width=4) (actual time=5.376..5.500 rows=720 loops=1) Group Key: employees.department_id -> Seq Scan on employees (cost=0.00..944.00 rows=1318 width=4) (actual time=0.014..5.045 rows=1253 loops=1) Filter: (join_year = 2020) Rows Removed by Filter: 48747 Planning Time: 0.614 ms Execution Time: 6.336 ms EXISTS QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------- Hash Join (cost=963.88..994.63 rows=1000 width=12) (actual time=5.262..5.723 rows=720 loops=1) Hash Cond: (d.id = e.department_id) -> Seq Scan on departments d (cost=0.00..17.00 rows=1000 width=16) (actual time=0.006..0.171 rows=1000 loops=1) -> Hash (cost=954.66..954.66 rows=737 width=4) (actual time=5.237..5.237 rows=720 loops=1) Buckets: 1024 Batches: 1 Memory Usage: 34kB -> HashAggregate (cost=947.29..954.66 rows=737 width=4) (actual time=4.957..5.084 rows=720 loops=1) Group Key: e.department_id -> Seq Scan on employees e (cost=0.00..944.00 rows=1318 width=4) (actual time=0.010..4.628 rows=1253 loops=1) Filter: (join_year = 2020) Rows Removed by Filter: 48747 Planning Time: 0.570 ms Execution Time: 5.902 ms JOIN QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------- Hash Join (cost=971.25..990.88 rows=737 width=12) (actual time=7.757..8.241 rows=720 loops=1) Hash Cond: (d.id = employees.department_id) -> Seq Scan on departments d (cost=0.00..17.00 rows=1000 width=16) (actual time=0.009..0.174 rows=1000 loops=1) -> Hash (cost=962.03..962.03 rows=737 width=4) (actual time=7.739..7.740 rows=720 loops=1) Buckets: 1024 Batches: 1 Memory Usage: 34kB -> HashAggregate (cost=947.29..954.66 rows=737 width=4) (actual time=4.406..7.568 rows=720 loops=1) Group Key: employees.department_id -> Seq Scan on employees (cost=0.00..944.00 rows=1318 width=4) (actual time=0.007..4.041 rows=1253 loops=1) Filter: (join_year = 2020) Rows Removed by Filter: 48747 Planning Time: 0.127 ms Execution Time: 8.359 ms 予想外だったのですが、この3パターン、 ほとんど同じ実行計画になりました !INとEXISTSは全く同じ、JOINもコストの数値が若干異なるだけです。 2:開発1課~9課の従業員を抽出 こちらの SQL は以下のようにしました。 -- INパターン SELECT name FROM employees WHERE department_id IN ( SELECT id FROM departments WHERE name LIKE ' 開発_課 ' ); -- EXISTSパターン SELECT name FROM employees e WHERE EXISTS ( SELECT 1 FROM departments d WHERE e.department_id = d.id AND name LIKE ' 開発_課 ' ); -- JOINパターン SELECT name FROM employees e INNER JOIN ( SELECT DISTINCT id FROM departments WHERE name LIKE ' 開発_課 ' ) tmp ON e.department_id = tmp.id; では実行計画を見てみます。 IN QUERY PLAN -------------------------------------------------------------------------------------------------------------------- Hash Join (cost=19.51..970.32 rows=50 width=11) (actual time=0.283..16.909 rows=450 loops=1) Hash Cond: (employees.department_id = departments.id) -> Seq Scan on employees (cost=0.00..819.00 rows=50000 width=15) (actual time=0.007..7.910 rows=50000 loops=1) -> Hash (cost=19.50..19.50 rows=1 width=4) (actual time=0.104..0.105 rows=9 loops=1) Buckets: 1024 Batches: 1 Memory Usage: 9kB -> Seq Scan on departments (cost=0.00..19.50 rows=1 width=4) (actual time=0.051..0.100 rows=9 loops=1) Filter: (name ~~ '開発_課'::text) Rows Removed by Filter: 991 Planning Time: 0.160 ms Execution Time: 16.985 ms EXISTS QUERY PLAN ---------------------------------------------------------------------------------------------------------------------- Hash Join (cost=19.51..970.32 rows=50 width=11) (actual time=0.276..16.525 rows=450 loops=1) Hash Cond: (e.department_id = d.id) -> Seq Scan on employees e (cost=0.00..819.00 rows=50000 width=15) (actual time=0.006..7.664 rows=50000 loops=1) -> Hash (cost=19.50..19.50 rows=1 width=4) (actual time=0.103..0.104 rows=9 loops=1) Buckets: 1024 Batches: 1 Memory Usage: 9kB -> Seq Scan on departments d (cost=0.00..19.50 rows=1 width=4) (actual time=0.050..0.099 rows=9 loops=1) Filter: (name ~~ '開発_課'::text) Rows Removed by Filter: 991 Planning Time: 0.161 ms Execution Time: 16.608 ms JOIN QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------ Hash Join (cost=19.54..970.35 rows=50 width=11) (actual time=0.392..16.747 rows=450 loops=1) Hash Cond: (e.department_id = departments.id) -> Seq Scan on employees e (cost=0.00..819.00 rows=50000 width=15) (actual time=0.009..7.770 rows=50000 loops=1) -> Hash (cost=19.53..19.53 rows=1 width=4) (actual time=0.161..0.161 rows=9 loops=1) Buckets: 1024 Batches: 1 Memory Usage: 9kB -> Unique (cost=19.51..19.52 rows=1 width=4) (actual time=0.149..0.156 rows=9 loops=1) -> Sort (cost=19.51..19.52 rows=1 width=4) (actual time=0.148..0.150 rows=9 loops=1) Sort Key: departments.id Sort Method: quicksort Memory: 25kB -> Seq Scan on departments (cost=0.00..19.50 rows=1 width=4) (actual time=0.054..0.115 rows=9 loops=1) Filter: (name ~~ '開発_課'::text) Rows Removed by Filter: 991 Planning Time: 0.123 ms Execution Time: 16.836 ms こちらもパターン1同様、INとEXISTSは全く同じ実行計画です。JOINの方はDISTINCTのUnique, Sortが入っていますが、コストはわずかです。 結論 単純なクエリではIN, EXISTS, JOINとも、おおむね同様の実行計画となることがわかりました。 オプティマ イザが思った以上に賢かったですね! より複雑なクエリや、インデックスの有無によっては変わってくるかもしれませんが、この程度のシンプルなクエリならあまりパフォーマンスを気にする必要はないと考えていいでしょう。 エンジニア 中途採用 サイト ラク スでは、エンジニア・デザイナーの 中途採用 を積極的に行っております! ご興味ありましたら是非ご確認をお願いします。 https://career-recruit.rakus.co.jp/career_engineer/ カジュアル面談お申込みフォーム どの職種に応募すれば良いかわからないという方は、カジュアル面談も随時行っております。 以下フォームよりお申込みください。 rakus.hubspotpagebuilder.com ラク スDevelopers登録フォーム https://career-recruit.rakus.co.jp/career_engineer/form_rakusdev/ イベント情報 会社の雰囲気を知りたい方は、毎週開催しているイベントにご参加ください! ◆TECH PLAY techplay.jp ◆connpass rakus.connpass.com *1 : 参考までに、利用した SQL は こちら です
アバター
はじめに こんにちは。新卒2年目のEngawaです。 アプリ開発 を行うチームに配属された際に Android アプリの開発の入門とした簡単なアプリの開発をした時の所感を書こうと思います。 学習で参考にしたサイトはこちらになります 開発環境のインストール方法から エミュレーター の作成方法まで詳しく書かれているので、 Android Studio のバージョンで差異は若干ありますが簡単に設定することができます。 codeforfun.jp 所感 今まで開発はHMTLなどで見た目を整理して逐一確認をしていたのですが、ボタンの配置などは必要な物を引っ張るだけで簡単に作成できるのでHTML等を使用して見た目を作成するのよりはるかに楽でした。 下図の赤枠の部分から ドラッグ&ドロップ するだけ。 ただし、参考にしたサイトにも書いてありますが、ボタンなどを引っ張ってくると xml のコードがごちゃごちゃして見にくくなるので注意が必要です。 私自身はごちゃごちゃしていても(自分だけが見る場合なら)全然気にしないタイプなのですが、そうでない方は手入力での作成の方がスッキリ整えるので手入力をしていただければと思います。 実際に挙動を確認するのもシミュレーターがあるので私のように Android 端末持ってないけど、なんとなく アプリ開発 をやってみたいという方でも実機なしですぐに動作確認できます。 Android だと機種ごとで一部見た目が変わっているのですが、シミュレーターを使えば端末ごとにレイアウトがどうなっているかすぐに確認できるのでとても便利でした。 終わりに 使用する言語は主に Java なのでアプリを作成するなら Android アプリからはじめて見てもいいかもしれません。実際にリリースするなら費用も安いので。 参考にしたサイトには音楽プレーヤーの作り方もあるので時間があったら作っても見ようと思います。 エンジニア 中途採用 サイト ラク スでは、エンジニア・デザイナーの 中途採用 を積極的に行っております! ご興味ありましたら是非ご確認をお願いします。 https://career-recruit.rakus.co.jp/career_engineer/ カジュアル面談お申込みフォーム どの職種に応募すれば良いかわからないという方は、カジュアル面談も随時行っております。 以下フォームよりお申込みください。 forms.gle イベント情報 会社の雰囲気を知りたい方は、毎週開催しているイベントにご参加ください! rakus.connpass.com
アバター
こんにちは、株式会社 ラク スで横断的にITエンジニアの育成や、技術推進、採用促進などを行っている開発管理課に所属している鈴木( @moomooya )です。 今回は dev.to で人気記事になっていた「 The 25 most recommended programming books of all-time. (史上最もおすすめされているプログラミング本【25選】)」を紹介したいと思います。 注:本記事は2020年2月18日に Pierre 氏がdev.toに投稿した The 25 most recommended programming books of all-time. を執筆者Pierre氏の了承のもと、日本語で紹介する記事です。 訳書の邦題について、訳書に改訂などがあった場合は出来る限り最新版の邦題で記載しています。 おすすめのプログラミング本を選んだ方法 「Best Programming Books」などのクエリで Google 検索しました。そのすべての結果をWeb Scraping API の Scraping Bee を利用して スクレイピング しました。 約150のリンクが収集でき、それらのページタイトルを以下のように集約しました。 特定の技術またはプラットフォームに焦点を当てたリスト 特定の年に焦点を当てたリスト 無料の本に焦点を当てたリスト Quora 1 および Reddit 2 のスレッド 最終的に70個のリストを抽出しました。 それらのリストに対して Python とBeatifulSoupを用いて、書名のリストを抽出しプログラミング本に対する約1300件のおすすめを抽出しました。 集計の結果はこちらの リポジトリ を参照してください。 注: 1300件 という数値は元記事中には記載ありませんが、参照先レポジトリ内の中間集計データより補完しています。 史上最もおすすめされているプログラミング本 25冊 注:元の記事では各プログラミング本の紹介が Amazon.com から転記されていましたが、こちらは Amazon.co.jp 版に置き換えています。 25. Jez Humble & David Farley, "Continuous Delivery" 邦題 『継続的デリバリー 信頼できるソフトウェアリリースのためのビルド・テスト・デプロイメントの自動化』 おすすめスコア 8.8% amazon.co.jp より いつまで手動でデプロイしているんですか? 現代では継続的にソフトウェアをリリースすることが必須になっています。本書は、継続的なソフトウェアのデリバリーを実現するためのビルド、デプロイ、テスト、リリースの自動化についての本格的な解説書です。 24. Robert Sedgewick & Kevin Wayne, "Algorithms" 邦題 未訳? おすすめスコア 8.8% 鈴木注 おそらく訳書は出ていないと思われます。 ただし著者のRobert Sedgewick氏が執筆したプログラミング本として "セジウィック:アルゴリズムC" という類書は和訳されています。 セジウィック:アルゴリズムC 第1~4部 ―基礎・データ構造・整列・探索― 作者: ロバート セジウィック 近代科学社 Amazon 23. Cory Althoff, "The Self-Taught Programmer" 邦題 『独学プログラマー』 おすすめスコア 8.8% amazon.co.jp より 本書は「 Python だけ」を学ぶ本ではありません。 Python を使ってプログラミングを紹介していますが、伝えたい内容は Python に限らない「プログラミング全般」の知識です。 プログラマ になるためのスキルを独学できる本です。 Python プログラミングの基本を学べるだけでなく、 プログラマ として必要なスキル(シェル、 正規表現 、パッケージ管理、バージョン管理、データ構造、 アルゴリズム 、仕事の始め方・やり方)もひと通り学べるのが特徴です。 「プログラミングを始めたい」「できればその道でプロを目指してみたい」――そんな読者にオススメです。 本書の著者、コーリー・アルソフ(Cory Althoff)は、「独学 プログラマー 」です。本書は、彼が独学で、ゼロからプログラミングを学んだ体験に基づいて書かれました。 プログラミングを独学で身に付けるために、著者が Python を通して学んだエッセンスが書かれています。彼の独学 プログラマー としての学び方は、 Amazon.com での本書の評価を見るとわかるように、多くの人に支持されています。 ――訳者あとがきより 鈴木注 原著が Kindle Unlimitedで読めます!!! (2020年3月12日現在) 22. Steve McConnell, "Rapid Development" 邦題 『ラピッドデベロップメント―効率的な開発を目指して』 おすすめスコア 8.8% amazon.co.jp より ソフトウェア開発のスケジュールを正確に管理するための、全ての戦略、良い方法、価値のあるTipsを紹介。具体的な ケーススタディ も収録した実践テキスト。 21. Peter Seibel, "Coders at Work" 邦題 『Coders at Work プログラミングの技をめぐる探求』 おすすめスコア 10.2% amazon.co.jp より どうやってプログラミングを学んだ? 他人のコードをどうやって読む? ソフトウェアはどう設計する? バグを追跡する方法は? プログラミングの将来はどうなる? プログラミング言語 が果たす役割は? プログラマ であるピーター・サイベル氏が15人の偉大な プログラマー (コーダー)から その技を聞き出すインタビュー集を、『Joel on Software』訳者の 青木靖 氏が翻訳。 20. Eric Evans, "Domain-Driven Design" 邦題 『エリック・エヴァンスのドメイン駆動設計』 おすすめスコア 10.2% amazon.co.jp より ソフトウェア開発コミュニティでは、 ドメイン モデリング がソフトウェア設計の中心であることが広く認められてきています。 ドメイン モデルを通して、ソフトウェア開発者は豊富な機能を表現し、それをユーザの要求に本当の意味で応えるソフトウェアの実装に移すことができます。しかし、明らかに重要であるにもかかわらず、効果的な ドメイン モデリング をどのようにソフトウェア 開発プロセス に組み入れるかを説明する、実用的なリソースはほとんど存在しませんでした。 ドメイン 駆動設計はこの要求に応えるものです。これは具体的な技術についての本ではなく、読者に ドメイン 駆動設計への体系的なアプローチを提示するものです。設計のベストプ ラク ティスの応用的なセット、経験に基づくテクニック、さらに、複雑な ドメイン に直面するソフトウェアプロジェクトにおける開発を容易にする基本原則を紹介する一冊です。 19. Donald E. Knuth , "The Art of Computer Programming" 邦題 『The Art of Computer Programming 日本語版』 おすすめスコア 10.2% シリーズ一覧 The Art of Computer Programming Volume 1 Fundamental Algorithms Third Edition 日本語版 The Art of Computer Programming Volume 2 Seminumerical Algorithms Third Edition 日本語版 The Art of Computer Programming Volume 3 Sorting and Searching Second Edition 日本語版 The Art of Computer Programming Volume 4A Combinatorial Algorithms Part1 日本語版 amazon.co.jp より アルゴリズム のバイブル。 Knuth 先生の名著『The Art of Computer Programming』シリーズ 鈴木注 TeX はこの本を作るために生まれたらしいです。 シリーズ物となっており、原書では第4巻分冊が6冊目まで発行されて現在も刊行中です。 訳書としては第1巻~第3巻と第4巻分冊の1冊目までが和訳されています。 執筆予定は スタンフォード大学内のWebサイト で公開されています。第5巻は2025年予定だそうです。 18. Harold Abelson / Gerald Jay Sussman / Julie Sussman, "Structure and Interpretation of Computer Programs" 邦題 『計算機プログラムの構造と解釈 第2版』 おすすめスコア 13.2% amazon.co.jp より 言わずと知れた「計算機科学の古典的名著」復刊! プログラミング言語 LISP の方言である Scheme を使用し、抽象化、 再帰 、 インタプリタ 、 メタ言語 的抽象といった計算機科学における概念の真髄を丁寧に解説した古典的名著。また計算機科学教育に多大な影響を与えたことはもちろん、「 関数型言語 」の 聖典 のひとつとしても挙げられる。いわば、現代の計算機科学( コンピュータサイエンス )の礎であり、プログラミングの始原であり、すべてのITの原点といえる1冊。 17. Martin Fowler, "Patterns of Enterprise Application Architecture" 邦題 『エンタープライズ アプリケーションアーキテクチャパターン』 おすすめスコア 14.7% amazon.co.jp より エンタープライズ アーキテクチャ のレイヤ化とは? エンタープライズ アプリケーション開発は、多くの新しい技術の出現から利益を得てきました。 Java と.NETのようなマルチレイヤをなす オブジェクト指向 のプラットフォームは、今では一般的になっています。これらの新しいツールや技術は、強力なアプリケーションを構築することができます。しかし、これらの実装は容易ではありません。 オブジェクト開発を経験した技術者が、 アーキテクチャ を理解しないまま開発を行うために、 エンタープライズ アプリケーション開発では共通の失敗がしばしば生じます。本書は、 エンタープライズ アプリケーション開発者が直面するやっかいな課題に対する直接的な回答を示したものです。技術は変化( Smalltalk から Java 、.NET。CORBAまで)していても、共通の問題を解決するために同じ基礎的な設計の考え方を適用することができるのです。 本書は40以上のパターンを紹介しています。これらは、 エンタープライズ アプリケーションプラットフォームに適用可能な解決策です。前半は、 エンタープライズ アプリケーション開発についての短い チュートリアル です。 後半は、各パターンについて詳細に解説しています。各パターンは、 Java または C# でコード例を詳述し、使用法および実装について説明します。概念についても、豊富な UML ダイアグラムで例証します。 16. Jon Bentley, "Programming Pearls" 邦題 『珠玉のプログラミング 本質を見抜いたアルゴリズムとデータ構造』 おすすめスコア 16.1% amazon.co.jp より: 情報系の勉強をしたことのある人ならば、誰しもプログラムにおける アルゴリズム の概念に触れたことがあるだろう。 同じ動作をするプログラムでもエレガントな アルゴリズム を持つものと そうでないものの間には実行時間や堅牢性、リソースの利用量などにおいて 大きな隔たりがあり、時には劇的なほどパフォーマンスの差があることも珍しくはない。 一方でそのような アルゴリズム を創出することがいかに難しいかも周知のことである。 そのため現在では納期や効率に重点をおいたプログラミングが優先されることが多いが、 単純で美しいプログラムを書くことは何より重要なことである。 本書は著者を含めた プログラマー たちが扱った問題をベースに、 エレガントなプログラムを書く際のさまざまなアド バイス や手法について解説したものである。 大学での アルゴリズム 講義に登場してくる探索やソート、データ構造といった内容に触れており、 現実的な題材の下に要求の定義、リソースの活用の仕方、動作する環境などのさまざまな側面から どのように アルゴリズム を組むべきかといった、プログラムを組む上での原理原則を学べるように構成されている。 このように題材となっている内容は決して特殊ではなく、 プログラムを組んだ経験のある人ならば必ず触れたことのあるレベルなので、 高級言語 でのプログラムが書ける人ならば誰でも理解できる内容になっている。 随所に登場する設問や読書案内も読者が学習する上で役に立つだろう。 数理的な解析に重点を置く大学での アルゴリズム 講義の内容は 実際のプログラミングに生かしにくいが、本書では応用や実際のコード化といった面に 重点が置かれて説明がされているので実務上も大いに役立つ。 自分のプログラミングを原則的、一般的な見地からよりよいものにしていくために必ず役立つ本だ。(斎藤牧人) 15. Tom DeMarco & Tim Lister, "Peopleware" 邦題 『ピープルウエア 第3版』 おすすめスコア 17.6% amazon.co.jp より: ●ソフト開発の現場で多くの熱い共感を呼んだ名著! 開発プロジェクトで技術よりも何よりも大事なもの――それは「人」。一人一人の 人格の尊重、頭を使う人間にふさわしいオフィス、人材の選び方・育て方、結束した チームがもたらす効果、仕事は楽しくあるべきもの、仕事を生み出す組織づくり、 という6つの視点から「人」を中心としたプロジェクト開発の大切をユーモラスに 語っている。1987年の初版発行以来、多くのソフトウエア・エンジニアの共感を 呼んだ名著の改訂第3版。 ●プロジェクト管理に関わる新規書き下ろしを収録! 第3版では、時代の変化に対応し、以下の章が追加された。「リーダーシップについて 話そう」、「他者とうまくやっていく」、「 幼年期の終わり 」、「リスクとダンスを」、 「会議、ひとりごと、対話」、「E(悪い)メール」。 14. Thomas H. Cormen / Charles E. Leiserson / Ronald L. Rivest / Clifford Stein, "Introduction to Algorithms" 邦題 『アルゴリズムイントロダクション 第3版 総合版』 おすすめスコア 17.6% amazon.co.jp より: 原著は,計算機科学の基礎分野で世界的に著名な4人の専門家がMITでの教育用に著した計算機 アルゴリズム 論の包括的テキストであり,その第3版.前版までで既に アルゴリズム とデータ構造に関する世界標準教科書としての地位を確立しているが,より良い教科書を目指して再び全面的な記述の見直しがなされ,それを基に新たな章や節の追加なども含めて,大幅な改訂がなされている. 単に アルゴリズム をわかりやすく解説するだけでなく,最終的な アルゴリズム 設計に至るまでに,どのような概念が必要で,それがどのように解析に裏打ちされているのかを科学的に詳述している. さらに各節末には練習問題(全957題)が,また章末にも多様なレベルの問題が多数配置されており(全158題),学部や大学院の講義用教科書として,また技術系専門家のハンドブックあるいは アルゴリズム 大事典としても活用できる. 本書は,原著の第1~35章,および付録A~Dまでの完訳総合版である.また巻末の索引も圧巻で,和(英)‐英(和)という構成により,「数理用語辞典」としてもまことに有用である. 13. Charles Petzold , "Code" 邦題 『CODE: コードから見たコンピュータのからくり』 おすすめスコア 19.1% amazon.co.jp より Windows プログラミングの雄、チャールズ・ ペゾルド が10年来あたため続けてきたという注目の企画が、ついに1冊の本になった。 本書はコンピュータの動作を根本から解説するもので、データのやり取りを中心に、コンピュータの動作原理を解説している。序盤では 点字 やモールス信号などを題材とするコードの歴史と、実際に通信や演算を行うためのハードを詳細に扱っている。中盤からは、2進数の処理、リレーによる演算の方法、メモリやオートメーション、終盤ではプロセッサの構造から低級言語・ 高級言語 、OSなどにも触れている。 計算機工学、 論理回路 学などの高度な内容にも触れているため、理系の、できれば工学系の知識がある方が望ましい。とはいえ、読み物形式なので、順番に読んでいくことで予備知識がない方でも理解することはできるはずだ。懐中電灯、黒猫、シーソーなど、一見コンピュータと何の関係もなさそうな例をもとに、コンピュータのしくみを明かしているのは、本書の最大の魅力である。 先に述べた内容以外にも、ファイル形式や開発環境、グラフィックに関する解説など、まさしくコンピュータに関わるすべてに言及している。とくにプロセッサやOS、アプリケーションなどの歴史に関する部分は興味深い。数学的な部分にあまり興味がない方にとっても、読む価値は十分にあるだろう。コンピュータの動作や根本原理を知りたいという知的好奇心あふれる読者に、ぜひおすすめしたい1冊である。(斎藤牧人) 12. Steve Krug , "Don't Make Me Think" 邦題 『超明快 Webユーザビリティ ―ユーザーに「考えさせない」デザインの法則』 おすすめスコア 19.1% amazon.co.jp より: 明白で使いやすいサイトを実現するには? ↓ ユーザーに考えさせちゃダメ! Apple 、 Bloomberg 、 Lexus などを顧客としてきた、 ユーザビリティ コンサルタント の第一人者にして激安ユーザーテストの伝道師 ス ティー ブ・クルーグが説く、 ユーザーに「考えさせない」サイトの作り方。 20か国で翻訳、累計45万部超の世界的ベストセラー、ウェブ&モバイル ユーザビリティ の定番書『Don't Make Me Think』の日本語版です。 ちゃんと使ってもらえるサイトにしたいWeb担当者、コンバージョン率を上げたいEC担当者におすすめの一冊。 11. John Sonmez, "Soft Skills" 邦題 『SOFT SKILLS ソフトウェア開発者の人生マニュアル』 おすすめスコア 22% amazon.co.jp より ソフトウエア開発者専用に、「より良い人生」を送るためのノウハウ・スキルを網羅した、生き方バイブル本です。 プログラマー が良い人生を送るためには、技術習得法やキャリア構築法といったノウハウに加え、対人的な交渉・指導・意思疎通などをうまく行える能力や知恵、すなわちソフトスキルが不可欠です!本書では、キャリアの築き方、自分の売り込み方、技術習得法、生産性の高め方といった仕事で成功する方法だけでなく、財産の築き方、心身の鍛え方、恋愛で成功する方法など、「人生全般をより良く生きる方法」を具体的に説明します。 ■序文から抜粋 あなたがこの複雑な産業で活路を開こうとしている若いソフトウェア開発者なら、今手にしているこの本は、多くの知恵と優れたアド バイス を与えてくれるはずだ。 ロバート・C・マーティン(アンクル・ボブ) ■「解説」から抜粋 本書はソフトウェア技術者向けの書籍ではありますが、いわゆるテク ノロ ジー のことはほとんど書いてありません。しかし、「成功者」になるために必要なそれ以外の多くのことが書いてあります。(中略)今こそ私たちがもっと成功に貪欲になれるチャンスなのではないでしょうか。 ■「訳者あとがき」から抜粋 全体を読み通して感じたのは、人の弱さを十分に意識して書かれていること、率直であ ること、上からではなく同じ高さから話しかけてくることでした。(中略)校正のために読み返してみると、株や栄養や腹筋のことなど、「何かで読んだんだけどさあ」という枕で出てくるような話の多くを本書で覚えたことに気づきました。無意識のうちにいろいろな影響を受けているようです。この本、ただものではないですよ。 10. Gayle Laakmann McDowell, "Cracking the Coding Interview" 邦題 『世界で闘うプログラミング力を鍛える本 ~コーディング面接189問とその解法~』 おすすめスコア 22% amazon.co.jp より トップIT企業が出題するコーディング面接にチャレンジ! 人気のあるトップIT企業で行われるコーディング面接に合格し採用されるための攻略本として、グーグル等でエンジニアとして働き、かつ多くの採用プロセスに関わってきた著者によって本書は執筆されました。米国で大人気のコンピュータプログラミングに関するベストセラー書(Cracking the Coding Interview: 189 Programming Questions and Solutions)の日本語版です。 本書で取り上げるプログラミング問題はトップIT企業が求める能力が凝縮されている、面接で実際に使われたものです。そしてなによりも アルゴリズム を中心とした コンピュータサイエンス の基礎知識や活用法を楽しみながら学べる内容となっています。 前著「世界で闘うプログラミング力を鍛える150問」と比べ計算量に関する説明がより詳細になりました。新規の問題はもちろん、既存の問題についても時間計算量・空間計算量の記述が追加され、計算量の見積もりについての話題も参考になるでしょう。また木とグラフ・探索 アルゴリズム に関する説明も充実したものになり、純粋なプログラミング技術書としてのバランスと深みが増しました。 Big-O記法の解説章や発展課題、解き方のヒントの追加、また全ての問題がカテゴライズされより読みやすくなりました。 本書が支持されている理由は「面接」という限られた時間だけにフォーカスするのではなく、その前後における行動までアド バイス してくれている点です。「エンジニアとして日々をどう過ごすか」を考える上で非常に有益でしょう。 自分が プログラマ として現在「どんな分野」に関して、どの程度の「能力」があるのか。これからのキャリアアップに必要な知識やスキルを考える手がかりとして。あるいは本当に優秀な候補者を採用する面接を行うための一冊として。 本書にはそのヒントがたくさん含まれています。 9. Erich Gamma / Richard Helm / Ralph Johnson / John Vlissides, "Design Patterns" 邦題 『オブジェクト指向における再利用のためのデザインパターン』 おすすめスコア 25% amazon.co.jp より オブジェクト指向 における再利用のための デザインパターン 建築の発想を持ち込む オブジェクト指向 はソフトウエア開発の手法として誕生したが,ほかの分野にも広がりつつある。その一つとして注目すべきなのが「デザイン・パターン」の登場である。 デザイン・パターンとは, オブジェクト指向 でソフトウエア設計を行う際に利用するカタログ集である。例えば,経験豊かな プログラマ は以前に解いた問題と,これから新しく解こうとしている問題が類似していることに気づけば,以前に使った解法が応用できる。デザイン・パターンとはこうした解法をだれでも再利用できるように一般化(パターン化)したものの寄せ集めと考えればよい。 この考え方と実現手法は,一般に GoF ( Gang of Four :4人組)本と呼ばれる本書で有名になった。 GoF 本は建築家の クリストファー・アレグザンダー がまとめた都市計画のカタログ集『時を超えた建設の道』( 鹿島出版会 )に強い影響を受けている。この点はたいへん興味深い。 オブジェクト指向 の導入で,ソフトウエアの世界においても 建築学 のように,構造をパターン化できることを示しているからだ。 8. Michael Feathers, "Working Effectively with Legacy Code" 邦題 『レガシーコード改善ガイド』 おすすめスコア 26.4% amazon.co.jp より: あなたは、 Java や.netでレガシーコードを書いていませんか? 本書は、システム保守の現場でありがちな、構造が複雑で理解できないようなコードに対する分析手法・対処方法について解説します。つまり、コードを理解し、テストできるようにし、 リファクタリング を可能にし、機能を追加できるテクニックを紹介しています。レガシーコードとは、 メインフレーム のアプリケーションのことではなく、変更することが困難なコードを指しています。著者は、本書で「私にとって、テストがないコードはレガシーコードだ」「テストコードがあれば振舞いを変えても、すばやく変更、確認することができる。もし、テストコードがなければ振舞いを変更しても、それが正しいのか、悪いのか判断できない」「 ソースコード がきれいで、良い構造であれば十分か?そうではない。もし、テストコードなしで大幅な修正を加えるとしたら、信じられないほどのスキルと明確な理解が必要になる」と述べています。本書は Java 、C、 C++ でサンプルを記述していますが、記載されているテクニックは言語依存するものではないため、他の言語( Delphi 、 Visual Basic 、 COBOL 、 FORTRAN )でも使えます。 7. Robert Martin, "The Clean Coder" 邦題 『Clean Coder プロフェッショナルプログラマへの道』 おすすめスコア 27.9% amazon.co.jp より ソフトウェアのプロになるには本書が必要だ! ソフトウェアのプロとは? プロの行動とは? 衝突・厳しいスケジュール・理不尽なマネージャにどう対応すべきか? いつ・どのようなときに「ノー」と言うべきか? プロはプレッシャーにどう対応するのか? 6. Frederick P. Brooks Jr, "The Mythical Man-Month" 邦題 『人月の神話【新装版】』 おすすめスコア 27.9% amazon.co.jp より ソフトウェア開発の定番書『人月の神話』。「 ブルックスの法則 」で知られる ブルックス 教授によるこの名著が、同教授の35年ぶりの新刊「The Design Of Design」 (邦題「デザインのためのデザイン」)を記念し、従来の縦組みから横組みに変わり、 表紙カバーを新たに新登場。 IBM の大型コンピュータSystem/630、および オペレーティングシステム OS/360 の 開発チームを率いた著者が、プロジェクトで発生した問題点を詳細に分析し、 ソフトウェア開発にまつわる困難と展望について持論を展開したエッセイ集。 原著初版(1975年)の刊行から35年がたつ現在でも、大規模開発プロジェクトにおける ソフトウェア工学 の古典として読み継がれ、多くの読者を獲得している。 とくに、「遅れているソフトウェアプロジェクトへの要員追加は、 さらにプロジェクトを遅らせるだけだ」という ブルックスの法則 は名高い。 開発において「人員×月日」というスケジュール見積もりが適用されている問題を指摘し、 ソフトウェア産業 において広くいきわたっている「人月の神話」を明らかにした。 また、刊行20周年記念して発行された増訂版では、発表当時大きな議論を巻き起こした 「銀の弾はない」をはじめとして、初版刊行以降に発表された著者の代表的な論文4編を収録。 各方面から寄せられたさまざまな議論に対して、著者があらためて自身の見解を述べている。 5. Eric Freeman / Bert Bates / Kathy Sierra / Elisabeth Robson , "Head First Design Patterns" 邦題 『Head Firstデザインパターン ―頭とからだで覚えるデザインパターンの基本』 おすすめスコア 29.4% amazon.co.jp より 初めて学ぶ方、過去に挫折した経験のある方、知識を確固たるものにしたい方を対象に、イラストや写真を使ってやさしく楽しく解説する人気のHead Firstシリーズの デザインパターン 編。 刺激的なレイアウト、思わず膝を叩く見事なたとえ、引き込まれる小話、楽しいクイズやパズルで飽きることなく読み進むことができます。 複雑難解な デザインパターン の概念が面白いほどよくわかる、目からウロコの画期的な書籍です。 4. Martin Fowler, "Refactoring" 邦題 『リファクタリング(第2版): 既存のコードを安全に改善する』 おすすめスコア 35% amazon.co.jp より ソフトウェア開発の名著、第2版登場! リファクタリング は、ソフトウェアの外部的な振る舞いを保ったままで、内部の構造を改善する作業を指します。本書は リファクタリング のガイドブックであり、 リファクタリング とは何か、なぜ リファクタリング をすべきか、どこを改善すべきか、実際の事例で構成され、ソフトウェア開発者にとって非常に役立つものとなっています。 本第2版では、約20年前のオリジナル原稿の構成は変わらないものの、大幅に書き換えられているほか、サンプルコードが Java から Java Scriptになるなど、現代的にアレンジされています。 3. Steve McConnell, "Code Complete" 邦題 『Code Complete 第2版 完全なプログラミングを目指して』 おすすめスコア 42% amazon.co.jp より 本書は効果的なコンスト ラク ションプ ラク ティスについての知識を集めた、実践的なプログラミング解説書です。ソフトウェア開発プ ラク ティスは目覚しい進歩を遂げていますが、一般の プログラマ にはなかなか浸透しません。本書は、業界の第一人者らの知識と、一般の商用プ ラク ティスとの橋渡しをします。10年前の第1版とコンセプトは同じですが、第2版は、全体を通じて オブジェクト指向 の考え方が反映されたものになっています。また、「 リファクタリング 」の章が追加され、サンプルコードは C++ 、 C# 、 Java 、 Visual Basic などにアップデートされています。本書は、ソフトウェア開発の総合ガイドを求めている経験豊富な プログラマ 、経験の浅い プログラマ を教育する技術指導者、正式なト レーニン グを受けたことのない独学 プログラマ 、これから社会に出る学生や新人 プログラマ などを特に対象としています。本書で説明されている研究成果や過去の経験は、高品質なソフトウェアを作成し、問題を少なく抑えて作業をより短期間で行うのに役立ちます。また、大きなプロジェクトを制御し、要求の変更に応じてソフトウェアの保守や修正を適切に行うのにも役立ちます。 2. Robert C. Martin, "Clean Code" 邦題 『Clean Code アジャイル ソフトウェア達人の技』 おすすめスコア 66% amazon.co.jp より コードを書き、読み、洗練する 本書の ケーススタディ を注意深く読むことで、コードを洗練していく過程で行うべき判断について学ぶことができます。プログラムが動作したからといって、プログラミングが終わったことにはならないのです。 1. David Thomas & Andrew Hunt, "The Pragmatic Programmer" 邦題 『新装版 達人プログラマー 職人から名匠への道』 おすすめスコア 67% amazon.co.jp より 経験に裏打ちされたヒントを満載し、実践可能なプログラムの作り方を教える。より効率的、そして生産的な プログラマー を目指す人に向け、具体的なアド バイス を、解決策のシステムを構成するよう関連付けて編集。 鈴木注 1位は 毎年少なくとも一つの言語を学習する で有名な『達人 プログラマー 』でした。原書では20周年版が去年2019年に出版されているので和訳版の改訂にも期待。 コメント欄から抜粋 私はいつも、Scott Rosenbergの「Dreaming in Code」を追加したいと思っています。 Dreaming in Code: Two Dozen Programmers, Three Years, 4,732 Bugs, and One Quest for Transcendent Software (English Edition) 作者: Rosenberg, Scott Crown Amazon The Phoenix Projectにも言及した方がいいんじゃないか? ;) Phoenix Project: A Novel About It, Devops, And Helping Your Business Win 作者: Kim, Gene , Behr, Kevin , Spafford, George It Revolution Press Amazon 挙げられている中で『計算機プログラムの構造と解釈』や『Art of Computer Programming』 など何冊かは読むことには実用的な意味がありません 。 多くの人が推奨していますが、実際に読む人はほとんどいません。 それらは題材としてすでにマイナーな言語を使用し、現在では時代遅れまたは不要な概念を多く扱っています。 プログラミングの心理学 要求仕様の探検学―設計に先立つ品質の作り込み どちらもGerald Weinbergによるものですが、Martin Fowlerよりも質の高い本を書いています。 もう1人の素晴らしい著者はJuval Löwyで、彼の本をすべて推薦します。 特に彼の最新刊: Righting Software これらが次の上位25のリストに載っていても驚かないでしょう。 プログラミングの心理学 25周年記念版 作者: ジェラルド・M・ワインバーグ 日経BP Amazon 要求仕様の探検学―設計に先立つ品質の作り込み 作者: ゴーズ,D.C. , ワインバーグ,G.M. , Gause,Donald C. , Weinberg,Gerald M. , ヤナ川 志津子 , 純一郎, 黒田 共立出版 Amazon Righting Software (English Edition) 作者: Juval, Löwy Addison-Wesley Professional Amazon 素晴らしいリスト。 私もお勧めします: FreemanとPryceの『実践 テスト駆動開発 』 実践テスト駆動開発 (Object Oriented SELECTION) 作者: Steve Freeman , Nat Pryce 翔泳社 Amazon お見事! The Pragmatic Programmerを読んでいない人には絶対にお勧めします。 私が読んだ最初の技術書であり、今でも私のお気に入りです。 素敵なリスト。 Kent Beck の" Smalltalk Best Practice Patterns"が含まれていなかったことが信じられません。 これは信じられないほどの良書であり、 Smalltalk だけの話ではありません。 これはすべての人におすすめできます。 ケント・ベックのSmalltalkベストプラクティス・パターン―シンプル・デザインへの宝石集 作者: ケント ベック ピアソンエデュケーション Amazon 「Getting Real」も素晴らしい読み物です。 Getting Real: The smarter, faster, easier way to build a successful web application 作者: 37signals, 37signals , Fried, Jason , Heinemeier Hansson, David , Linderman, Matthew 37signals Amazon 所感 原書と訳書の表紙を並べて表示してみました。こういうの見比べるのが好きなんですよね……。 というわけでランキングのおさらいです。 1位『達人 プログラマー 』 2位『Clean Code』 3位『Code Complete』 4位『 リファクタリング 』 5位『Head First デザインパターン 』 6位『人月の神話』 7位『Clean Coder』 8位『レガシーコード改善ガイド』 9位『 オブジェクト指向 における再利用のための デザインパターン 』 10位『世界で闘うプログラミング力を鍛える本』 11位『SOFT SKILLS』 12位『超明快 Web ユーザビリティ ―ユーザーに「考えさせない」デザインの法則』 13位『CODE』 14位『 アルゴリズムイントロダクション 』 15位『ピープルウエア』 16位『珠玉のプログラミング』 17位『 エンタープライズ アプリケーション アーキテクチャパターン 』 18位『計算機プログラムの構造と解釈』 19位『The Art of Computer Programming 日本語版』 20位『エリック・ エヴァ ンスの ドメイン 駆動設計』 21位『Coders at Work』 22位『ラピッドデベロップメント』 23位『独学 プログラマー 』 24位『Algorithms』 25位『継続的デリバリー』 頻繁におすすめされるような有名なプログラミング本で、未読のものはあっても知らないものはそんなにないかな、と思っていたのですが意外と知らない本を発見できて嬉しかったです。日本語圏と 英語圏 でもまた違いがあったりするのでしょうか。 読みたいと思っていながら読めていなかったプログラミング本もたくさん思い出せたので、合間を見つけながらせっせと読んでいきたいと思います。 最後に改めて。了解をくれたPierreさん、ありがとう。 Pierre, thank you for your consent. エンジニア 中途採用 サイト ラク スでは、エンジニア・デザイナーの 中途採用 を積極的に行っております! ご興味ありましたら是非ご確認をお願いします。 https://career-recruit.rakus.co.jp/career_engineer/ カジュアル面談お申込みフォーム どの職種に応募すれば良いかわからないという方は、カジュアル面談も随時行っております。 以下フォームよりお申込みください。 rakus.hubspotpagebuilder.com ラク スDevelopers登録フォーム https://career-recruit.rakus.co.jp/career_engineer/form_rakusdev/ イベント情報 会社の雰囲気を知りたい方は、毎週開催しているイベントにご参加ください! ◆TECH PLAY techplay.jp ◆connpass rakus.connpass.com Q&Aコミュニティサイト ↩ 匿名 掲示 板サイト ↩
アバター