社内勉強会はじめました
弊社で社内勉強会をした話を書く
弊社の紹介
本ブログで現在勤務している会社に言及したことがあまり無いので改めて紹介をします。 私は昨年の9月から株式会社HERPでエンジニアをしています。 HERPは採用管理システム(Applicant Tracking System; ATS)を提供している会社です。 主にTypeScriptとHaskellを使ってプロダクト開発をしています。 弊社にはエンジニアが十数名*1在籍しています。 中にはブラウザのレンダリングエンジンにContributeしている人がいたり、計算機科学の研究をしている現役大学院生がいたりします。メンバーの知識に差があるのでそれを埋めるためにも勉強会をやりたいなあという声が社内であがっていました。
また、弊社では「スクラム採用」という採用活動を推進しています。 スクラム採用とは採用施策を人事担当者ではなく現場社員が立案・遂行するという採用活動です。 エンジニアの採用はエンジニアが、デザイナーの採用はデザイナーが介入するといった感じです。 エンジニアがスクラム採用をやっていくにはTwitterやブログでテクノロジーに関する話をしたり、イベントで登壇したりして注目を集める能力があるとうれしい。 社内で勉強会を行うのは知識を発信する訓練として良さそうだというのも社内勉強会を開催した動機のひとつです。
社内勉強会の様子
8月1日に私が企画して社内勉強会を行いました。 1回目なのでひとまず30分ぐらいで終わるように発表者を2名集めて発表7分、質疑応答7分としました。
Cybaiさん:今年の6月にMozilla Whistler All Hands 2019に参加した話をしてもらいました。 hiroqnさん:nixパッケージマネージャーの話をしてもらいました。
主催者としての反省
この手のイベントの企画は初めてだったのですが、やってみた反省としては以下のとおりです。
- 発表準備のケツ叩きは必要
- タイムキーパーは必要
- 発表者は案外集めづらい
あと、今後も社内勉強会を定期的に開催するようにしたいと思っています。 ゆくゆくは社外の人も参加できる形にしていきたいと考えており、他社がどのようにして勉強会を企画・開催しているのかとか、エンジニア勉強会をやる文化を根付かせるためにどんな試みをしているのかとかを調査しています(有識者の方がいればコメントくださると幸いです)。
Scrapbox使うとよさげ?
発表スライドをScrapboxのプレゼンテーションモードで作ると手軽でいいんじゃないかなと思います。実際にhiroqnさんはスライドをScrapboxで作っていました。
パブリックプロジェクトで作ればそのまま公開もできます。今回の発表資料も↓で公開しています。
このScrapbox projectですが、スライド以外にも弊社で使っているフレームワークや技術の解説もまとめています。題してHERP-Technoteです。 今年6月頃からすこしづつ書き始めて現在50以上のページができています。 今後も記事を増やしていく予定なので読んでくださると嬉しいです。
まとめ
- 勉強会やっていきたい
- Technoteもちょくちょく更新されていくので良かったら見てください
FuseBoxというイケてるmodule bundlerがあるらしい
FuseBoxというmodule bundlerがイケてるらしいので使ってみた github.com
どこらへんがイケてるのか
公式サイトやGitHubのREADMEによると以下のような利点があるらしい。
- 早い
- デフォルトでTypeScriptやJSX記法に対応している
- devサーバー内蔵
- HMR(hot module replacement)がサポートされている
- configが楽
実際に使った感想としては、configファイルが簡素な点、で専用のCLIを使わない点、後述のWebIndexPlugin
などが主な魅力だと思われる。
実際に使ってみた
以降は、実際に書いたコードを提示しながら*1、FuseBoxの使い方を説明する。 「ただbuildするだけ→devサーバーを使う→pluginを入れる」のように後半になるにつれて高度な機能の説明になっていく。
とりあえずbuild
まず適当なtsファイルをbuildしてみる。src/
ディレクトレリを作って、その中にindex.ts
という名前で以下のソースコードを保存する。
// index.ts const msg: string = "Hello World"; console.log(msg);
次にyarn
を初期化して、fuse-box
とtypescript
をインストールする。
$ yarn init $ yarn add -D fuse-box typescript
READMEに習って以下のようなconfigファイルを書き、fuse.js
の名前で保存する。
// fuse.js const { FuseBox } = require("fuse-box"); const fuse = FuseBox.init({ homeDir: "src", output: "dist/$name.js", sourceMaps: true, }); fuse.bundle("app").instructions("> index.ts"); fuse.run();
fuse.bundle()
はソースコードを一つのjsファイルにまとめるコマンドで あり、.instructions()
でビルドの起点になるファイルを指定する(webpack.config.js
でいうところのentry
)。
設定ファイルを記述したら、以下のコマンドを実行する。FuseBoxはwebpack-cliの専用のCLIコマンドは用意されておらず、configファイルをそのまま実行する形式を取っている(npm i -g
したくない派の人喜びそう)。
node fuse
すると、dist/
ディレクトリが作られ、中にビルド結果がapp.js
、app.js.map
の名前で出力される。
ちなみに今回のように、
tsconfig.json
を作らずに実行すると、src/
以下に自動生成してくれる。target
やbaseUrl
などの設定項目はfuse.js
に書いた通りにしてくれるのでちょっと便利。
devサーバーを動かす
fuse.js
にdevサーバーを立てる設定を追記する。
ついでに出力されるjsとsource mapをブラウザ向けのものにしておく。
// fuse.js const { FuseBox } = require("fuse-box"); const fuse = FuseBox.init({ homeDir: "src", output: "dist/$name.js", target: "browser@es5", // ブラウザ向けのコードを吐かせる。ついでにバージョンもes5に指定 sourceMaps: {vender: true}, // ブラウザ向けのsourceMapを出すようにしておく }); // devサーバーの設定 fuse.dev({ port: 8888 // port番号。デフォルトは4444。 root: 'dist' // devサーバーのルートディレクトリ。デフォルトはFuseBox.init()の`output`で指定したディレクトリ。 }); fuse.bundle("app") .instructions(`> index.ts`) .watch() // tsを書き換えるたびに差分コンパイルを行う .hmr(); // hot module replacementを有効にする fuse.run();
ES5で出力するようにしたので、index.ts
もES6以降の機能を使ったやつにしてみる。
enum LogLevel { Info, Error, } type Message = { type: LogLevel; message: string }; const showMessage = (m: Message): string => { switch (m.type) { case LogLevel.Info: return `📢 ${m.message}`; case LogLevel.Error: return `⚠️ ${m.message}`; default: throw new Error("invalid message"); } }; const hello: Message = { type: LogLevel.Info, message: "Hello World" }; document.querySelector("body").innerHTML = showMessage(hello);
最後にdist/index.html
を作成すれば準備完了。
<!-- index.html --> <body> <div id="app"></div> <script src="/app.js"></script> </body>
node fuse
を実行し、localhost:8888にアクセスすると「📢 Hello World」が表示される。
ついでにapp.js
を確認すると、ES6やTypeScript特有の記法がES5に変換されていることが確認できる。
// app.js の抜粋 var LogLevel; // TypeScriptのenumで書いた箇所 (function (LogLevel) { LogLevel[LogLevel["Info"] = 0] = "Info"; LogLevel[LogLevel["Error"] = 1] = "Error"; })(LogLevel || (LogLevel = {})); var showMessage = function (m) { // ES6のarrow関数で書いた箇所 switch (m.type) { case LogLevel.Info: return "\uD83D\uDCE2 " + m.message;
WebIndexPluginでindex.html
を自動生成
前章ではindex.html
を手動でdist/
に置いた。しかし、dist/
は自動出力専用にして、手書きのコードは他のディレクトリで管理したいという要求もあるだろうと思われる(私はそうしたい)。
そこで、WebIndexPlugin
というものを使ってそれを実現する。
まず、src/public/template.html
を作る。
<!-- hemplate.html(Emmetのテンプレをちょっと書き換えただけ) --> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>My Page</title> </head> $css<!-- ここにstyleタグが挿入される --> <body> <div id="app"></div> $bundles <!-- ここにscriptタグが挿入される。設定次第で、src=""で別ファイルから読み込むかinlineか選べる --> </body> </html>
fuse.js
にプラグインの設定を追加する。
// fuse.js const { FuseBox, WebIndexPlugin } = require("fuse-box"); // WebIndexPluginもimportする const fuse = FuseBox.init({ homeDir: "src", output: "dist/$name.js", target: "browser@es5", sourceMaps: {vender: true}, plugins: [WebIndexPlugin({ template: "src/public/template.html" })], // これを書き足す });
実行するとdist/
にindex.html
が自動生成される。ちなみに、WebIndexPluin
の引数でtemplate
を指定しない場合、適当なhtmlファイルを自動生成が作られる。便利。
まだまだあるぞ
まだ色々紹介したい機能があるが、長くなったので記事を分けたい。 残っているネタは以下の通り。
AltCSS
を使ってみたJSX
を使ってみたfuse-box/sparky
で静的ファイルのコピーをしてみた
ついでにwebpackあたりとの比較もやってみたい(未着手)。
ただ、7月17日時点で、依存ライブラリに脆弱性が見つかっているようなので本格的に使うなら次のバージョンを待った方がよさそう*2。
*1:清書の段階で修正した箇所もあるためgitのlogと不整合な箇所もある
*2:version 4の準備が進んでいるらしく、hot fixするのかv 4公開のタイミングで直すのかよくわからない。7月17日時点でdependencyのバージョンを上げるissue/PRは出てないのでcontributionチャンスかも?
弊社でCycle.jsに寄付した話
Open Collectiveを使って業務で使っているOSSライブラリに寄付をした話をする。
Cycle.js
会社でCycle.jsというフロントエンドフレームワークを使っている。
Cycle.jsはステート管理やをひとつの関数として実装して、 ブラウザ上の操作やHTTP通信などの"外界"の動作を関数外の処理に任せるというアーキテクチャを採用している。
弊社プロダクトのフロントエンド部分はほとんどCycle.jsで実装しており、大変お世話になっている。 そこで、Cycle.jsのOSSコミュニティに資金援助をしよういう話が社内であがった。
Open Collective
Cycle.jsはOpen Collectiveというサイトで寄付金を受け付けている。
Open Collectiveは投げ銭サービスの一種で、主にGitHubでOSSコミュニティ向けに作られている。
寄付する側での会員登録、寄付の方法を説明する。
会員登録
個人で会員登録をする場合、メールアドレスと名前を入力するだけで登録できる。 パスワード入力は不要で、登録メアド宛に送られてくるmagic linkを開くことでログインする。*1
法人として登録する場合、上記に追加して
の入力を求められる。 GitHub OrganizationやTwitter IDを入力しておくと、団体のアイコンを自動で取得してくれるみたいなのでちょっと便利。
お支払い
次に寄付の方法を説明する。
まず寄付先のコミュニティのサイトを開き、「コントリビュート」のボタンをクリックする。
すると、コミュニティが指定した寄付のプランが表示される。 ここでプラン通りに寄付をしても良いが、ページ下部の「Or make a custom financial contribution」を選んで自分で寄付額を決めることもできる。
自分で寄付額を決める場合、金額と寄付の頻度(1回、毎月、毎年の3パターン)を入力する。
寄付金の支払い方法は以下から選べる。
銀行振込で海外送金するのは色々大変そうなので、実質クレカとPayPalの二択になると思われる。
実際に寄付してみた
社長にお願いしたら1000ドルぽんと出してくれた :sasuga_shacho:
そして公式サイトに載った。
さいごに
Cycle.jsはかなりイケてるフレームワークなので、ガンガン開発してほしいですね。
開拓馬 バージョン 24.0.0を公開しました
24歳の誕生日なので去年からの差分をリリースノートっぽく書いた
- 自力で生活費を稼ぐ機能を追加しました
- TypeScriptを扱う機能を追加しました
- 余剰資産を投資信託で運用するように変更しました from Folio
- 研究意欲がないのに大学院に行ってしまう不具合を修正しました
- トレーニングジムに週1~2回通いヘルスケアに勤しむ機能を追加しました
- コーヒーの好みを苦味が強いものから酸味の強いものに変更しました from LIGHT UP COFFEE
- 認知行動療法を導入することで自己肯定感が急激に低下する不具合を解消しました from デビット・D・バーンズ
- 引っ越しによりロード時間*3を短縮しました
- 食洗機を利用して時短家事を行うようになりました(めっちゃ便利)
- 図書館を利用することで読書量を増やしました
- web予約機能を利用するようになりました(イマドキの図書館は便利ね)
- 蔵書リクエストを出すようになりました
- Nintendo Switchで遊ぶようになりました from Nintendo
- 昨年11月に購入してから400時間ぐらい遊んでる
- スマホゲームに手を出すようになりました
- 最近のおすすめはAuto Chess*4, Brawl Stars, アイドルマスターシャイニーカラーズ
- SEKIROクリアしました*5
- 欲しいものリストで誕生日プレゼントをねだる機能が追加されました
研究と鬱と休学の話
これはEEICアドベントカレンダー2日目の記事です。
研究する気のない人が大学院に入って精神状態がボロボロなった話とそこから這い上がった話をします。
TL;DR
- 人は心が荒むとスピリチュアルに頼りがち。でも認知行動療法に頼ったほうがいい
- つらくなったら学生相談室にGO
- 「勉強をしたい」と「研究をしたい」は別。大学院は後者のための場所
研究室と研究生活について
学部4年(去年)の4月から、電子情報工学科のIIS-Lab(矢谷研究室)に配属されました。 その後、大学院に進学した後も在籍し続け、1年半ほどこの研で過ごしました。
IIS-Labの研究内容は公式サイトを見ればわかるので、研究室の雰囲気や学生の過ごし方を軽く説明すると、
- 毎週水曜日に全体ミーティング、また週一で先生と1対1でミーティング(コアタイムはこれだけ)。
- 一人1プロジェクト。解決すべき問題を探すところから実験計画まで、全部自分で決める。
- 研究の進捗管理はGitHubのissue、業務連絡はSlack。
- 論文はOverleafで書く。共有リンクを渡せば、先生も上級生もわりとガッツリ添削してくれる。*1
- 発表練習が手厚い。卒論発表や輪講の直前はミーティングで発表練習をやる。
- 学生居室がキレイ。(ベンチャー企業のオフィス感)
- 修士1年の夏に企業のインターンに行くことが推奨されている。
- 1/3ぐらいが留学生。*2
- 計算資源はMicrosoft Azure。研究室でパートナー契約的なものをしてるらしく、高いインスタンスを借りても大丈夫っぽい。(書き忘れていたので2019/01/15追記)
自分で考えたテーマで研究したい人、研究のモチベーションが高い人にはとてもいい環境だと思います。 逆にそうでない人をきっぱりと休学・退学させてくれるのもいいところなのかな……(ごまかしで卒業できてしまうのよりは間違いなく良い)
気の乗らない研究生活。鬱の傾向が現れる
そんな素晴らしい環境に身を置きながらも、研究生活を送るにつれて私の精神はすり減っていきました。
その原因は研究の進捗が芳しくなかったことです。 まず、研究テーマを見つけるという段階から躓きました。 どのような研究をやりたいかというビジョンを明確に持たないまま4年生になってしまったため、やりたい研究が思いつかないという状態に陥りました。 IIS-Labでは、研究テーマは各人が自分で決めるという方針だったため、テーマが降ってくる*3こときも期待できず、ただ途方に暮れる状態でした。 結局、なんとかひねり出した微妙なアイデアを元に研究っぽい何かをでっち上げるというような酷い卒業研究でした。 こんな具合で卒業研究は散々な結果だったのですが、大学院入試には受かっていたためそのまま大学院に進学し、修士の研究でもテーマが見つからないという問題に直面し……
毎週のミーティングで先生に報告できるような進捗を作らなければという重圧や、修論発表の期日までに成果を出せないかもしれないという漠然とした不安と戦う毎日でした。 こうした不安は大学にいる時間だけでなく、買い物している間やご飯を食べている間、寝る前の布団に潜っているときも、趣味の登山の最中ですら、常にこうした不安からは逃れられない状態でした。 自由な時間はたくさんありましたが、心から休める時間は1秒たりともありませんでした。
そんな生活を送っていたら不眠症になり、保健センター精神科*4で診てもらったところ「鬱の傾向*5がある」と言われました。
認知行動療法、マインドフルネス、スピリチュアル
こうして鬱の傾向にあることが発覚したのですが、そこから抜け出すために色々な「あがき」をしました。
まず認知行動療法に取り組みました。 認知行動療法というのは、出来事に対するネガティブな思い込み(自動思考)を言語化し、合理的な思考に修正することで精神を安定させる手法で、鬱やパニック障害の治療方法のひとつです。 精神科医デイビット・D・バーンズの名著「いやな気分よさようなら」や「フィーリングGoodハンドブック」*6を読み込みました。 そこに記載されているノートテイキング手法を試したり、日々認知の歪みを意識して生活したりすることで、ネガティブな自動思考を徐々に和らげていきました。 他にも認知行動療法の亜種であるAcceptance Commitment Therapy(ACT)についても調べ、できる範囲で実践しました。
他にもマインドフルネス(瞑想)にも取り組みました。 マインドフルネスとは「何も考えない」状態を作ることでストレスを和らげる手法です。 基本的に道具を使わなくてもマインドフルネスは可能なのですが、ガイドがある方がやりやすいと考えたので、HeadSpaceやPauseといったアプリを使いました。 ちなみにHeadSpaceのようなMindfulness-based Applicationは学術研究の対象として注目されてきているようです。 コンピュータサイエンスを用いてWell-beingを追求するという目標の元、HCIと精神医学を組み合わせた学際的な研究は最近流行ってきているみたいです(マインドフルネスは決してスピリチュアルやオカルトのたぐいではないぞ)。 「ウェルビーイングの設計論*7」等の書籍に詳しく書いてあるので興味を持った方はご一読してみることをおすすめします。
他にも、南米のスピリチュアルな儀式*8を試したり(今思い返すと相当キテた)、 ちょっとした一人旅に行ったり*9、 半ばヤケになって色々試しました。
認知の歪みを意識すると気分が落ち込みにくくなるという発見は今でも役立ってます。
東大の学生相談ネットワーク
学内の学生相談ネットワークもフル活用しました。 大学生活を送るうちに心を病む人というのはわりと多いらしく、ほとんどの大学には学生相談室という施設が設置されています。 東大の場合、学生相談室の他に、精神保健支援室(保健センター精神科)、コミュニケーション・サポートルーム、なんでも相談室、ピアサポートルームという施設が存在し、まとめて学生相談ネットワークと呼ばれています。 私はピア・サポートルーム以外は全部利用して精神の安定させていきました。 せっかくなので使い方とかどんな雰囲気かというのを書いておきます。
- 学生相談室
- スクールカウンセラーの方と相談できる場所
- 基本的には毎週 or 隔週ぐらいのペースで通院(通室?)する
- 予約制
- ネット予約だと1~2週間後になる場合が多い
- 実は電話予約だと融通が効く場合がある
- 精神保健支援室(保健センター精神科)
- コミュニケーション・サポートルーム(コミュサポ)
- なんでも相談室
- なんでも相談できるらしい
- 一度行ったが、学生相談室を紹介されただけだった
- 精神状態の悩みは「学生相談室 or コミュサポ行きましょうね」になるような気がする
- 工学部学生相談室
- 学生相談ネットワークの管轄ではなく、工学部が独自に設置している学生相談室
- カウンセラーじゃなくて事務員的な人が常駐してる?
- 1回行ったけど正直微妙だった
まとめると、保健センター精神科でおくすりをもらいつつ、学生相談室とコミュサポのどちらか or 両方でカウンセリングを受けるのが良いんじゃないかな。 悩みを言語化したり、自分の状態をより深く理解したりすることはとても大事です。
どうやら自分は研究をしたいわけではないらしい
そんなもろもろの「あがき」や学生相談ネットワークの支援によって現在の私の精神状態はかなり安定しています。 そして今は何をしているかというと、大学院を休学してスタートアップ企業でエンジニアをしています。 今やってることについては他の記事*11で語るとして休学に至った心境についてお話します。
鬱の傾向が晴れて今の自分の状況が冷静に捉えられるようになった私は極めて単純な心理に気付きました。 つまるところ、自分は研究をやりたいわけではなかったのです。 大学に入ったときは講義を受けて色々なことを学びたいと考えていましたし、大学院入試をした動機の中には他の研究者が書いた論文を読むのが好きという要素も多少ありました。 しかし、自分が論文を書いて他の研究者に読ませることには全く興味がないということに気付きました。
本当にやりたいことは研究ではなかった、他にやりたいことがあるはず、仮にやりたいことがまったくなく自分の人生に意味がないとしても研究するよりはマシな時間の潰し方はある。。。 と、あれこれ考えるうちに、嫌々ながら研究を続けるより休学してエンジニアとして働いたほうが良いのではないかという結論に至りました。
- 自分はお金とスキルを得られてうれしい
- 先生は私の指導に当てていた時間を自由に使えてうれしい
- 企業は私という労働力を得られてうれしい
などなど、私が休学して働くことであらゆるリソースが正しく使われるようになるわけです。*12 もちろん修士卒の肩書が遠のくというデメリットもありますが、研究に対するモチベーションが低い自分が、なんちゃってMaster of Engineeringで不当に高く評価されるのは、今後の人生において良い結果を産むはずがありません。
そんなことを考えた私は、次の日には休学届を完成させ、次の日には現在のインターン先に面接に行き(あっさり採用してくれた弊社に感謝)、あっという間にエンジニアに転生していました。 こうして研究する気がない学生が一人消え、人手不足のIT業界に働き手が一人増え、世界は少し良くなったとさ、めでたし。めでたし。
*1:研究室見学では論文執筆環境はあんまり語られることがないが、それなりに重要な要素だと思う
*2:今年秋入学で3人入った。彼らが秋入学したのと入れ違いで休学したので、どんな人なのかあまり知らない
*3:教授や院生が研究テーマを考え下級生にやらせる現象
*4:学内の病院的な施設
*5:精神科医による診察結果であるが、診断書が発行されるレベルの本格的な診断ではないため「傾向」というファジーな表現がされている
*6:この2冊は鬱の状態で読むには内容的にも物理的にもやや重いのでそれっぽい入門書を図書館で借りたほうがいいかも
*7:この本は私が発注した(ドヤ顔)ので工学部2号館図書館に蔵書されている
*8:瞑想をして精霊を呼ぶ的なやつ
*9:レンタカーで四万温泉にドライブして事故る(駐車場で隣の車を擦った)。レンタカー屋の保険2100円で全部解決できた上に警察に通報して事故の後処理をするという貴重な体験ができたのは良い買い物だった
*10:バラマキではなく医学研究の一貫である。念の為
*11:退学アドベントカレンダー13日のエントリ
*12:このあたりやたら大げさに書いているが、休学決めた日は鬱の傾向が裏返って軽い躁状態になっていたのか「俺は休学して世界を正しくするぞおおおおおぉ」と本気で考えていた
クックパッドインターンでちょっぴり成長した
10 day 技術インターンシップに参加してちょっぴり*1成長してきました。かなり楽しかったので体験記を書きます。
前半5日間
前半の5日は講義形式でwebアプリケーションの開発について学びました。
初日はオフィス見学と環境構築で、2~5日目で以下のようなことを学びました。
- 事業開発
- サーバサイド(Ruby on Rails)
- フロントエンド(React Native、Typescript)
- クラウドインフラ(AWS、Docker 内製デプロイツールの itamae と hako のハンズオン*2 )
個人的にはクラウドインフラの回が一番楽しかったです。 EC2やRDSのインスタンスを立てたり、ロードバランサを置いて負荷分散をしたりといったことを体験しました。 これらは学生が個人でやるには限界があり、ここで体験できたのはとても良かったと思います。 サーバの設定内容をコードの形式で保存しChefツールで環境構築を自動化することで、サーバ環境構築の冪等性を確保するという概念を知ることもできました。
また、実習として、ISUCON形式でアプリケーションの処理速度をインターン参加者同士で競うということも行われました。 私は2位に入賞することができ、賞品としてレシピ本をもらいました🥈
後半5日間
後半はOJT*3コースとPBL*4コースに分かれて参加者ごとに異なる活動をしました。 OJTは実際にクックパッドの開発現場に参加するコースで、PBLは与えられた課題を解決するようなアプリケーションをチームで開発するコースです(やや期間が長いハッカソンのようなもの)。 私はPBLコースに配属され、「食材の購入を支援するアプリを作る」という課題に3人のグループで挑戦しました。
我々のチームは「休日に1週間分の食材を買い込んで、平日はそれらを使って料理する」というシナリオを想定し、1週間分の献立を決めると必要な食材の総量を計算してくれるアプリを作成しました。 自分は主にクライアントサイドの開発担当としてひたすらReact Nativeを書きました。 React Navigationで画面遷移を実装したり、Native BaseでUIを設計したり、コンポーネントはできる限りSFC*5になるように書いて使いまわしやすくしたり実践的なReact Nativeの開発ができました。
ただ、ライブラリの選定や設計方針を予め相談した方が良かったのかもしれません。今回のアプリではヘッダ部分をReact Navigationが生成するものを使いましたが、個人的には使いづらいように感じる部分もありました。 React Native Navigation等の他のライブラリを使用する、ヘッダ部分もNative Baseで実装するという選択肢をあまり考慮せず、なんとなくで決めてしまったのは良くなかったと思います。
仮に今回作ったものを実際に事業として動かすのであれば、デザイン面*6と技術面*7での課題を解決するためにユーザインタビューや機械学習モデルの構築などが必要で、事業開発のほんの一部分しか体験できていないようにも思いました(インターンの期間中にユーザインタビューまでやるのは無理そうだけど)。
参加前はOJTコースで現場の業務環境を体験したいと考えており、PBLコースに配属されたのを残念に思っていました*8。 しかし、アプリの設計から実装まで技術レベルが同じぐらいのメンバーでグループ開発するという体験はそんなにできることではないため、それはそれで良い体験になったのではと思います。
感想
いろいろなことが体験できた10日間でした。 Ruby on RailsやReact Nativeといったフレームワークを初体験したり、インフラエンジニアリングという分野のことを知ったりすることができました。
正直、今回のインターンそれ自身による成長はそこまで大きくは無いと思います。本当に成長するのは今回触れた技術をアルバイトなどで活用したときになるのではと思います。 しかしながら、今回のインターンを通じてweb系エンジニアの方々の働き方を垣間見たり、同期の学生達が様々なことに挑戦していることを知ったりして、勉強していくモチベーションが高まりました。
このインターンで成長したというよりは、今後成長する足がかりができた感じがしました。(植物に例えるなら、幹が伸びるというよりは新しい枝が生えたのかな)
学んだこと
- Ruby on Rails
- React Native
ほぼ初見でしたが、2週間で多少使えるレベルにはなったかなと思います。 特にReact NativeはPBLコースの5日で沢山書いたので、その気になれば自力でアプリひとつ作れる程度にはなったかな? Typescriptやweb版のReact.jsの理解も深まりました。
- 新規事業開発
企業がどのようにして新規事業を立案したり、ユーザのフィードバックを得たりしているのかを体験できました。大学では得られないものだったと思います。 研究のテーマ探しやユーザスタディなどでも役に立ちそうだと思いました。
新しく興味を持ったこと
- インフラの最適化 ISUCON
AWSへのデプロイや、クラウドインフラの最適化は独学では体験しにくい分野なので体験できてよかったと思います。 インフラエンジニアという職種を知ることもできました。 また、社内ISUCONを体験して本家ISUCONにも興味が湧きました。
- Rust
インターンの内容とは無関係ですが、参加者にRustaceanがいて布教されました。 Web Assemblyと組み合わせて使ってみたいです。
その他
クックパッドはオフィスにキッチンがある変わった会社です。
そのキッチンを使って、インターン参加者や社員の皆さんとごはんを作りました。
大勢で料理をしてみんなで食べるというのはとても楽しかったです。それに料理も美味しかったです。餃子とか唐揚げとか中華スープとか🥟
3日目の餃子パーティー
最終日の懇親会
*1:圧倒的成長というが界隈で使われていますが、「圧倒的」という部分に嘘っぽさとブラック労働的な苦労自慢のニュアンスが感じられて好きではないので「ちょっぴり成長」したことにします
*3:On-the-Job Training
*4:Problem Based Learning
*5:Stateless Functional Component
*6:献立を立てる→必要な食材を計算というコンセプトなので、献立を立てるという体験を楽しくさせるデザイン上の工夫が必要だと考えられる。また、世間一般の消費者は休日にまとめ買いや献立を予め決めるといった行動をどの程度行っているのかを分析し、このアプリが本当に必要とされているか見極めなければならない
*7:クックパッドのレシピに記載されている材料欄をもとに買うべき食料を算出しているため、食材を1人分に正規化したり、「適量」とか「お好み」とかいった表現をいい感じの数量に変換したり等で、提示する食材量の妥当性を確保する必要がある
Python & Serverless FrameworkでLambdaファンクションをサクッと作ってデプロイする
Serverless FrameworkはAmazon AWSの開発&管理を補助するフレームワークです。 最近アルバイト先でserverlessを用いたアプリケーションに関わり、その際に使いかたを軽く勉強したので、ブログに書き残しておきます。
環境
- Node.js 10.6.0
- Python 2.7.15
- serverless 1.29.2
Installation
ServerlessはNode.jsのアプリケーションとして配布されており、npm
コマンドからインストールできます。
npm install -g serverless # 確認 serverless --help sls --help # slsという短縮コマンドが自動でエイリアスされるらしい
サービスを作ってデプロイ
インストールが完了したので、簡易的なLambdaのファンクションを作成してAWSにデプロイするところまでやってみましょう。 今回は毎朝8時にLINE Notificationを送ってくれる目覚ましファンクションを作ってみます。
サービスの新規作成
sls create
コマンドでサービスを新規作成できます。
このとき-t
オプションでアプリのテンプレートを、-p
オプションでサービスを保存するパスを指定できます。
テンプレートはaws-python
*1、保存先は適当な作業ディレクトリ上のlambdaMezamashi
というディレクトリにします。
cd /path/to/working/dir #適当な作業ディレクトリに移動 sls create -t aws-python -p lambdaMezamashi cd lambdaMezamashi ls # => handler.py serverless.yml
コマンドを打つと、lambdaMezamashi
というディレクトリが作成され、handler.py
とserverless.yml
という2つのファイルが自動生成されます。
handler.py
はLambdaのファンクションを書くファイルで、serverless.yml
は設定ファイルになります。
とりあえず動かす
アプリが完成したのでとりあえず動かしてみます。
テンプレートにはhello
という関数名で簡単なメッセージを返す関数が定義されています。
sls invoke local -f {関数名}
で指定した関数名の関数をローカル環境で実行できます。
sls invoke local -f hello # => { # => "body": "{\"input\": {}, \"message\": \"Go Serverless v1.0! Your function executed successfully!\"}", "statusCode": 200 # => }
LINE Notificationを送る関数を記述
LINE Notificationの使いかたはこちらの記事でも解説しています。
まず、LINE Notifyのページからアクセストークンを取得し、環境変数LINE_NOTIFY_TOKEN
に書き入れます。
export LINE_NOTIFY_TOKEN=XXXXXXXXX # bash zsh等の場合 set -x LINE_NOTIFY_TOKEN XXXXXXXXX # fishの場合
次に以下のようにhandler.py
を書き換え、LINE NotifyのAPIを叩くコードを追加します。
# -*- coding: utf-8 -*- import os import json import requests def mezamashi(event, context): output_url = "https://notify-api.line.me/api/notify" token = os.getenv("LINE_NOTIFY_TOKEN", "") headers = {"Authorization" : "Bearer "+ token} payload = {"message" : "こんにちは"} response = requests.post(output_url ,headers = headers ,params=payload) return response.json() def hello(event, context): body = { "message": "Go Serverless v1.0! Your function executed successfully!", "input": event } response = { "statusCode": 200, "body": json.dumps(body) } return response
次にpip
コマンドでrequests
をインストールします。
pip install requests
次にserverless.yml
を書き換え、mezamashi
関数に関数名を割り当てます。
service: lambdaMezamashi provider: name: aws runtime: python2.7 environment: # LINE Notifyのアクセストークンを記入 # invoke localで実行する場合はこれを記述しなくても動作するが、デプロイ時に必要となる LINE_NOTIFY_TOKEN: XXXXXXXXXXXXXXXX functions: hello: handler: handler.hello mezamashi: handler: handler.mezamashi
そうしたら、serverless invoke local
を用いて動作確認を行います。
sls invoke local -f mezamashi # => { # => "status": 200, # => "message": "ok" # => } # (LINEに通知が来る)
スケジュール実行の設定
Lambdaファンクションの実装が完成したので、これをスケジュール実行するように設定を書きます。
serverless.yml
のfunctions
の部分にイベント設定を追記するだけです。
functions: #<中略> mezamashi: handler: handler.mezamashi events: # イベントの設定を記述 - schedule: cron(0 23 * * ? *) # cron式で日本時間の朝8時を指定
ついでにAPI Gatewayも使う
LambdaはAPI Gatewayと組み合わせることでwebアプリのバックエンドとして使用するケースもよくあります。 少し脱線しますが、ymlを用いてLambdaファンクションをAPI Gatewayと結びつける方法も説明しておきます。
events
の項目に- http: {メソッド} {APIのURI}
の形式で記述します。
こうすることでデプロイした際に自動でAPI Gatewayが作成されます。
functions: hello: handler: handler.hello events: - http: GET hello
オフラインでテストする
ファンクションが書けたので早速デプロイと行きたいところですが、その前にローカルホストでLambdaファンクションをホストして、APIのテストを行う方法を解説します。 これは、業務でデバッグやAPIのテストコードを走らせる場合にも必要なことなので覚えておいて損はありません。
まず、必要なプラグインをインストールします。インストールはsls plugin install -n {プラグイン名}
で行います。どうやらこのコマンドはnpm i --save-dev
をラップしてnode_moduleをインストールしつつ、serverless.yml
にプラグイン情報を追記してくれるものらしいです。
sls plugin install -n serverless-offline npm install serverless-offline-python --save-dev # slsコマンドからインストールできないためnpmを直接使う
次にserverless.yml
の末尾に以下のように書き込んでserverlessとプラグインを紐付けます*2。
plugins: - serverless-offline - serverless-offline-python
serverless-offline
とserverless-offline-python
をインストールしたことで、serverless offline
というコマンドが使えるようになります。これによりローカル環境でcurlコマンド等を用いてAPIのデバッグが可能になります。
sls offline #=> Serverless: Starting Offline: dev/ap-northeast-1. #=> (中略) #=> Serverless: Offline listening on http://localhost:3000 # =====他のterminal窓から以下を実行===== curl localhost:3000/hello #=> helloファンクションが動く
ちなみにserverless-offline-scheduler
というオフライン環境でスケジュール実行のデバッグができるプラグインがありますが、Node.jsで書いたものしか動かないみたいです*3。
デプロイする
最後にデプロイの方法を説明します*4。
AWSアカウントの設定
最初にAWSアカウントの設定をします。
AWSのマネジメントコンソールにログインし、IAMから新規ユーザーを追加します。
ユーザー名を適当に設定し、「プログラムによるアクセス」にチェックを入れます。
「既存のポリシーを直接アタッチ」から「AdministratorAccess」を選択します*5 *6。
ユーザーの作成が完了したら、「アクセスキーID」と「シークレットアクセスキー」を控えておきます。シークレットアクセスキーはこのときにしか確認できないため、忘れた場合には再度アカウントを作成する必要があります。
これを、sls config credentials
コマンドを用いて設定します。XXXXXの箇所は適宜アクセスキー、アクセスキーシークレットに書き換えてください。
sls config credentials --provider aws --key XXXXX --secret XXXXX
デプロイ、実行、削除
アカウントの設定が済んだら遂にデプロイです。
Serverless Frameworkはsls deploy
コマンドを実行するだけで簡単にデプロイできるようになっています。
しかし、今回のようにPythonで実装している場合は、自分で書いたコードだけでなくサードパーティ製のライブラリも一緒にデプロイする必要があります。
serverless-python-requirements
というプラグインをインストールするとデプロイ時に自動でこの作業をやってくれるため、今回はこのプラグインを利用することにします。
sls plugin install -n serverless-python-requirements # プラグインのインストール pip freeze > requirements.txt # 依存関係をrequirements.txtというファイルに書き出す
上記のコマンドを実行したら、デプロイします。
sls deploy #=> Serverless: Installing requirements of requirements.txt in .serverless... #=> Serverless: Packaging service... #=> (中略) #=> service: lambdaMezamashi #=> stage: dev #=> region: ap-northeast-1 #=> stack: lambdaMezamashi-dev #=> api keys: #=> None #=> endpoints: #=> GET - https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/dev/hello #=> functions: #=> hello: lambdaMezamashi-dev-hello #=> mezamashi: lambdaMezamashi-dev-mezamashi
これで完成です。毎朝8時にLINEに通知が来るようになりますし、https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/dev/hello
のURIにcurl
コマンドやAjax通信でアクセスするとhello
ファンクションをWeb APIとして叩くことができます。
デプロイしたアプリの削除も簡単に行うことができ、sls remove
コマンドを実行するだけです。
sls remove #=> Serverless: Getting all objects in S3 bucket... #=> Serverless: Removing objects in S3 bucket... #=> Serverless: Removing Stack... #=> Serverless: Checking Stack removal progress... #=> ............................. #=> Serverless: Stack removal finished...
さいごに
今回はServerless Frameworkの使い方を軽く説明しました。 Serverless Frameworkは他にもDynamoDBやS3といったサービスを操作することができ、その名の通りサーバレスなwebアプリケーションを構築することができます。
S3でwebページをホストし、Lambda & API Gatewayでバックエンドの処理を行い、DynamoDBやCognitoでユーザ情報を管理するという構築にすればどんなWebアプリでも作れそうですね。
参考資料
- 今から始めるServerless Frameworkで簡単Lambda開発環境の構築 | Developers.IO
- Rate または Cron を使用したスケジュール式 - AWS Lambda
- Serverless - AWS Guide
*1:was-python3だとローカルで動かす際にpyenv等を用いてver 3.6のPython環境を用意する必要があります。今回は面倒なので2.x系で我慢
*2:# sls plugin ~~ コマンドを走らせた際に自動で追記してくれるため、serverless-offline-python以外は不要かも
*3:実際にソースコードを確認したところ、Lambdaファンクションが記述されたjsファイルをrequireで読み込んで実行するという実装がされているようだった https://github.com/ajmath/serverless-offline-scheduler
*4:これ以降の部分で解説するコマンドを実行するとLambdaファンクションがAPI Gatewayを通して全世界から実行可能な状態になります。Lambdaファンクションに脆弱性が存在した場合には思わぬ被害を被る可能性があることを心に止めておいてください。
*5:公式ドキュメントでもAdmin権限を設定する(https://serverless.com/framework/docs/providers/aws/guide/credentials/)という解説されています。
*6:Serverless Frameworkは開発中でやれることがどんどん増えています。そのためAdmin権限でないと機能に制限がかかり、開発が面倒になる可能性があります。Amdin権限で開発しつつ、製品を公開する際に権限を必要最低限に絞るような運用が望ましいと思われます。