この記事の目的と想定読者
株式会社インフル(株式会社ユニエイムから出資を受け、最終的にユニエイムと組織統合しました)では、この春からWebエンジニアの長期インターンを募集し、(夏までで)10名を超える方を採用しました。しかし、当初からなんとなく感じていたのですが、次のような課題があります…
-
ポートフォワードとかalembicの設定とか、ほぼ全員に最初に共通して伝えないといけない事柄について、毎回そこそこ丁寧に説明しないといけないこの課題はqiita:teamで解消することにしました。 - 個々のインターンの方に依頼している作業がかなり違いすぎて、やっている事の全体を把握しにくい
- 海外から夏休み等で来ている学生や、留学する学生(約1/3)は定期的に卒業を迎える為、卒業後に入社した人はその人たちの担当した業務を把握しにくい
インターンの実態を色んな人に説明しにくく、「インターンいいよ」みたいな事ばかり言う語彙の貧しい人みたいになっている(私が)
これらの課題をゆるゆると解決しつつ、**「実際にインターンとして働くとどのような作業をすることになるか」**をリストアップして説明できるようにするため、まとめてみる事にしました。
…というようなことを考えて書き始めたのですが、色々と書き方に迷い、ひとまず技術要素ベースのボトムアップで記述してみました。
想定読者としては、
-
学生:インターンを検討している人/参加している人
→ 技術的な意味で、インフルのエンジニアインターンでどのような事をするのか、なんとなくわかります。また、他の人がどんな事をしていたのか、網羅的になんとなくわかります。 -
その他企業の人:インターン実施を検討している人
→ うまくインターンの学生を集めれば、このような作業を依頼できるかも?という実例を知る事ができます。
以下、私=作業依頼者です。
ちなみに、株式会社インフルというのは、2017年1月創業、3月より本格始動して、自社Webサービスを3つ展開している会社です。各サービスの詳細は割愛しますが、自社サービスのアジャイル的な開発・運営を軸として、たまに受託開発もやっています。
4/30にファーストコミットしたWebサービス(システム)を、6月にはトライアルユースで使用して頂くようなスピード感とFit&Gapが持ち味で、インターンの人にはこれを支える開発作業をして貰っています。(インターンの人が居ないと、開発スピードが1/3〜1/4ぐらいになる程度には依存しています!)
※この記事の続きの記事が(2017年12月版)にあります。
雰囲気は特に変わりませんが、課題対応など細々とした部分で進捗があるので、こちらも合わせてご確認ください。
補足
ここに書いてある事に関しては全て、インフルが採用しているインターンの学生の方が実際に対応できた、ということを付け加えておきます。そもそも、依頼した作業を最終的に完了出来なかった事は、これまで殆ど無かったです。
また、原則として全ての作業が、そのままリリースしているサービスに組み込まれている、ということも付け加えておきます。(もちろん私が責任を持ってコードの確認をしている前提で)
ただし、インターンの方の習熟度や特性に合わせて、言語や作業の内容、指示する粒度は適宜調整しています。
ちなみに、インターンの方の初期状態(入社時点での状態)は、
- 主にPythonやC++、Java等の経験があり
- webアプリはだいたいtutorialをやったことがあるか無いかぐらい
- JavaScriptを真面目に書いたことがある人は殆ど居ない、特にnodeを使った事があった人は居ない
- テトリスに類するゲームを、簡素なインターフェイスで、得意言語で実装するとして、数時間〜2日ぐらいという見立て(ゲームは実際に作った事無い人の方が多い)
です。
以下、入れてるライブラリベースなので、コーディングの量などは全然わからないかもしれないですが、一般的なシステム開発会社に基本設計〜結合テストぐらいの見積を貰って数百万ぐらいする案件の実装・開発部分を、実稼働1ヶ月ぐらいで終わらせるようなコーディング量です。(抽象的?)
実装関連
開発環境構築
ここ(=開発環境構築)の内容は、インターンの人に依頼した作業の結果というよりは、私が説明をして覚えて貰った作業に関する覚書、というのが正しいです。
多段ssh/portforward(ssh tunnel)
AWSのEC2インスタンスに秘密鍵を使って接続します。このとき、configにいろいろ設定をしておくことで、踏み台サーバーを経由しつつポートフォワードするようにします。
※踏み台サーバーとELB以外は、外部から直接アクセスできません。
git/bitbucket(ソース管理)
bitbucketからソースをローカルに落とします。
直接EC2にリポジトリを作っても良い(本番環境ほかはそういう設定)ですが、多分IDEを使った方が作業しやすいのでソースはローカルに置きます。
gitのGUIツールは使わなくてもよいですが、sourceTreeを使っている人が多いのかな…
PyCharm/WebStorm etc.(IDE)
落としたソースを開いて、EC2に自動転送する設定をします。
(ひょっとしたら既にサポートされているのかもしれないですが)sftpで踏み台設定をできない気がしたので、sshで繋いだ時にホスト側の22番ポートを適当なローカルポート(例えば2322)に転送するようにしておいて、localhost:2322にsfrtpします。
SequelPro(MySQL管理ツール)
Amazon Aurora(MySQL互換)に踏み台経由で接続します。
(もし新しいインスタンスを立ち上げていて、データベースが存在しない場合は、create database)
alembic(DBバージョン管理)
最初にソースを落としてきた時や、他の人の更新を取り込んだ場合などは、ソースのみ最新の状態となっていて、データベース(スキーマ)は最新の状態になっていません。なので、データベースを最新の状態にするため、サーバー側でalembicをします。
ローカルで実行しても、特殊な設定(hostsを編集するとか)をしない限りは接続できません!
起動(pythonベース)
pythonベースのソースの場合は、サーバー側でpythonを実行すると、サーバーが起動します。
node
nodeは、ローカルにインストールしてローカルで起動します。
EC2インスタンスが弱い(基本micro)ので、webpackとか諸々はローカルで実行した方が速いからです。
起動(JS/TSベース)
上述の通り、ローカルで起動します。
npm i
ng start
または
npm start
開発環境では、APIサーバー(各種データの取得元・保存先)はEC2またはローカルのモックにして、クロスオリジンな構成にします。なので、CORSについて少し勉強する必要があります。
Python
だいたい1/3ぐらいは、インターンの人にライブラリの選定含めて任せています。私から指定した(既に作っていた)のは、flask + SQLalchemy + redis + WTForm + PyBabel + pytest。
特筆事項があまり無い場合は空欄になっています。。。
flask(軽量WEBフレームワーク)
blueprintを使って、あるサービスの主ファイルの分割をインターンの人にお願いしたら、0.3日ぐらいで終わらせて貰えました。
また、↑のサービスとは別のサービスで、2000行分程度のファイルに収まる雑多なビュー関数・URL群(58エンドポイント)に対して、入社1週間ぐらいのインターンの人にルーティング周りの仕様整理を依頼して、その後2週間ぐらいでユーザー権限別に完全に整理されたルーティング仕様を構築していました。当時実装していた単体テストを全て直した上で。
これは、単体テストをきちんと書いていたので、全面的なソースリファクタをほぼ新人であった人に依頼することができた、という少し稀有な例です。この経験を通して、単体テストを書いておくとそういうこともできるんだね、という事を実感してもらえたのが良かったと思いました。
実際、9割ぐらいのURLを変更する必要があったものの、バグは殆どありませんでした。
SQLalchemy(ORM)
基本ですが、countやjoinを含むSQLやバルクインサートなどを、多くのインターンの人が直接APIの説明を読んで実装していました。
※redis(redisはインメモリDB)
WTForm(フォーム、バリデーション)
項目がDBの内容によって可変となるフォームの雛型を(私が)作ったのですが、一応それを読んで普通に使いこなしていました。
PyBabel(i18n)
※GrabzIt(画像出力API)
適当なURLを指定して、そのURLから画像を出力するという処理を行わせたい、という要件をインターンの人に伝えた上で、phantomJSとかqt(wkhtmltopdf)とか色々試してもらって、最終的に縦書きを自然に出力できるGrabzItを使った処理を書いてもらいました。
※opencv(画像処理)
xlrd(エクセル加工)
エクセルをインポートしてほしい、とインターンの人に依頼して、ライブラリの選定を含めて対応して貰いました。(多分2時間ぐらいで)
apscheduler(スケジューラ)
スケジュール起動するようなメッセージング処理を書いてほしい、とインターンの人に依頼して、ライブラリの選定を含めて対応して貰いました。
pytest(単体テスト)
pandas(データフレーム処理)
Apriori(aprioriアルゴリズム:アソシエーションルール)
「アソシエーションルールの分析を入れて」という雑な依頼をインターンの人に投げたら、入っていました。(多分2時間ぐらいで)
TypeScript/JavaScript
フレームワークとか基本的なものを除くと、だいたいインターンの人にライブラリの選定含めて任せています。
angular(定番)
react
react-redux
とある案件で必要になったので、インターンの人に1日=8時間ぐらいreactからのチュートリアルをやってもらって、ある程度デザインが決まっているwebサービスのクライアント側SPAの初期表示+画面遷移をお願いしました。1日=8時間につき、5〜10項目ぐらい存在して1〜3個のAPIからデータを取得する必要のある画面を、4画面分ぐらい書くペースで書いていました。
d3(データビジュアライズ)
highcharts(チャート)
introjs(チュートリアル的な奴)
snowshoe(電子スタンプ、通信先必須)
電子スタンプの回転角度、親オブジェクトに対する位置、等を計算するロジックをインターンの人に作成してもらいました。私が当初提案したアルゴリズムよりも、簡便さで上回るアルゴリズムを提案してもらい、若干時間がかかりつつもそれをきちんと実装していました。
また、諸般の事情により、JavaScriptのソースをTypeScriptに書き直す作業を依頼したりしました。(あるインターンの人がTypeScriptに触り始めた初日の練習作業として。30分か1時間ぐらいで終わってました。)
wScratchPad(スクラッチ削る奴)
電子スタンプを押した後でスクラッチ風の削れる処理を入れたい、という要望があって、そのライブラリとして私が見つけていたものをインターンの人に渡し、足りない部分を追加実装してもらいました。具体的に足りなかった機能としては、親オブジェクトをtransformのrotateで回転した時にも正しく削る、削った状態の画像をs3に送って保存する、という2つの機能ですが、プルリクを出せるほど綺麗に書いてはいないので、内部でのみ使っています。。。
japan-map(日本地図)
「日本地図を出したい」という雑な依頼をして、インターンの人にライブラリの選定含めてやって貰いました。
jquery-gantt(ガントチャート)
「顧客別の利用状況などを可視化したく、ガントチャート風の表示にしたい」という雑な依頼をして、私が挙げた候補+インターンの人にライブラリを検討して貰った上で、このライブラリを使う事になりました。(古いけど)
jcrop(画像切り抜き)
「自画像などをアップロードするにあたって、画像を切り抜く処理を入れてほしい」と雑な依頼をして、インターンの人にライブラリの選定含めてやってもらいました。
add to homescreen(ホーム画面に追加を促すバルーン)
add to calendar(カレンダーに追加する機能)
bootstrap-tagsinput(タグ入力的な奴)
bootstrap-colorpicker(カラーピッカー、色を選ぶ奴)
image-picker(画像とか選ぶ箱)
ライブラリは私が選定していたかも。インターンの人に、「これを使って画像を選択する処理を書いてくれ」とお願いして、適当に書いてもらいました。
slick(スライダー)
exif.js(EXIF取得)
ローカルでEXIFを取得する処理に使用しています。
テストほか
私が最初に準備していたのはcircle ciとowasp zapで、あとは要件を伝えてツールの選定まで含めてインターンの人にお願いしました。
locust(負荷試験)
「負荷試験をしたい」という雑な要件をインターンの人に投げて、色々調べてツールを選定して貰い、ステージング環境に向けて大量のアクセスを発行するテストコードを書きました。
立ち上げておくプロセス数や、microインスタンス1台あたりで捌けるアクセス量などを見極めることができました。
owasp zap(脆弱性診断)
インストールと、ステージング環境に向けての脆弱性診断をインターンの人にお願いしました。
squash-tm(テスト管理)
「テストマネジメントをしたい」という雑な要件をインターンの人に投げて、色々調べてツールを選定して貰い、squash-tm入りのEC2インスタンスを作ってもらいました。ウォーターフォール的な分類で、結合〜総合テストに相当するレベル感のテストを入れてもらっています(いまのインフル社内ではユーザー受入テストが事実上存在しない)
circle ci(CI環境)
CIに関しては、テスト結果を元にしてテストやプログラムを書き直す対応等は依頼していますが、それ以上の対応は現状依頼していません。pytest/pep8/eslint(tslint)ぐらいを動かしています。
AWSの使っている機能
EC2
ただし、インスタンス作成の作業そのものは、セキュリティと予算の都合上、まだインターンの人にはお願いしていません。
ELB
s3
SES
ElastiCache
Redisです。
Lambda
具体的には、s3にファイルを置く時にサムネイル作ったりとかしています。当初はnodeでやっていたものをpythonに書き換えたのですが、書き換え作業はデプロイまで全てインターンの人にお願いしました。
RDS
Auroraです。
設計関連
要件定義
業務フロー作成
他社の提案資料(あまりフローとして整っていないもの)などをもとに、インターンの人に業務フローを作成してもらいました。
また、顧客との打合せに参加して、業務要件のヒアリングなども実施して貰っています。
新機能の企画
サービスの新機能をインターンの人に検討・実装してもらいました。プレゼンしてもらう時間も設けました。
システム構成図作成
AWSのVPCの中身の概要をインターンの人に伝えた上で、ELB/EC2/RDS/ElastiCacheなどからなるシステム構成図を逆起こししてもらいました。
基本設計
機能一覧作成
各画面が一行に相当するような粒度の機能一覧をインターンの人に作成してもらいました。
CRUD図作成
DBの各テーブルに対するCRUD図をインターンの人に作成してもらいました。
画面遷移図作成
画面遷移図をインターンの人に作成してもらいました。
その他の仕事
基本的な作業の説明
alembicなどの作業の説明や、具体的な実装方法の説明などは、随時インターンの人にお願いしていました。私も横で聞いていますが、致命的な間違いは無いのと、説明している側のインターンの人の細かい理解を確認できるので、細かく訂正しながら理解力や理解の仕方の癖を知ることができました。
みんな進んでインターンに応募するぐらいなので、コミュニケーション能力がある人ばかりで、(わたしが)非常に楽でした。吸収が速いこともあって、一般的な社会人数年目のエンジニアに説明するよりも、ずっとずっと説明が楽でした。
作業指示
あるインターンの人に、別のインターンの人への作業依頼を丸投げした事があります。いわゆるプロジェクトリーダーに相当するぐらいの感じですが、まあ普通にこなせていました。作業依頼をしている人が、「彼は本物のプログラマです」と目を輝かせながら言っていて、微笑ましかったです。
課題
参考まで、整理して改めて認識した課題を列挙します。これまでに書いた事は、基本的に直接手とり足取り何かを教えるようなことはなく、質問があれば答えるというスタイルで全て解決しました。しかし、以下のような課題に関しては、単に質問があれば答えるスタイルでは上手くいかないかも?という事を感じています:
テストとか設計とか
クライアントの自動テスト
これは単に手が回っていないだけです。
結合以上のテストの自動テスト
これも手が回っていないだけ…ですが、テストの所要時間が長くなるのと、維持にもコストがかかるのがちょっと。うーん。
詳細設計の書き方
漏れない設計については、多分体系的な説明をきちんとした方が良いのですが、自社サービスの開発スタンスの都合で、殆ど触れていません。今のインフルの自社サービスの開発スタンス:「コード読めば分かるし、それが一番正確だから、二重管理はしない!」
ただ、今後他社とのやり取りなども必要になるので、ある程度のドキュメンテーションは必須と思っています。
※詳細設計はともかく、少なくとも仕様概要はあったほうが良いと思っています。。
単体テストケースの書き方(境界値とか、C0とか、0件・1件・複数件とか、の概念も含む)
テストについての具体的な方法論とか、絶妙な障害がもたらす問題に関しては本当は細かく教えたいものの、業務的な効率を優先すると、どうしても後回しにしてしまってます。
本当は単体テストが純粋にspecとして機能する状態にしたい。。。
仕事の仕方関連
課題整理・進捗管理
手元で自分の作業をリストアップして処理する+時間を気にして作業をする習慣がある人(3〜4割ぐらい)は良いですが、他の人には自分自身で進捗を管理させるような事は特にやらせていません。(こちらがJootoを使ったり、都度具体的に指示をしたりしているので、主体的にやらなければ彼らがやる必要のない状態にしていました)
顧客からの様々なヒアリング方法
質問をまとめさせたりとか、予習させたりとかはできるものの、実際に何をどんな感じでどう聞くか、あるいは聞いておかないとどうなるのか、みたいな事は中々教えられていません。
「仕事」の仕方、自分自身のコスト意識
新社会人によくある、「お前の仕事はn秒1円 or 1秒n円だぞ」「上司を動かしたら、その上司の時間は1秒n円だぞ」「他の人を巻き込んだら、その時間は(省略)」的な事は、話はしたりするものの、直接的には殆どやっていません。仕事をするという意味では、自分のコストを意識した上で主体的に動く事を意識してもらうべきですが、主に私にそれを意識するよう働きかけるだけの精神的な余裕(俗に言うMP)が無いです。。。(例えばガチで叱ると、めちゃめちゃ疲れる)
まあ、bugsnagに流れるバグの量とか内容とか作業している雰囲気を見ればだいたい詰まっているかどうかが分かるので、それをトリガーにして適当に声をかければ、無駄に時間を浪費することはないので良いかなーという状態です。インターンの人たちの事を考えると、「上司に時間を使わせた時点で恥じろ」みたいなことを言った方が良いのかもしれないですが、元々インターンという形態は仕事よりも「逃げ道」が広いので、変に追い詰めたら逃げる方向に力を使われてしまうんじゃないかなーとも推測。だいたい、私がそれを言うと、萎縮してそれ以外の報告も全てできなくなってしまうので。。。
かといって、いわゆる社会人研修みたいなことをする時間も余裕もなく。
交流関連
勉強会の開催
そもそも、この記事で書いているような内容を、それぞれ担当した個人から発表してもらいたいなーと思っていたのですが、私が絶望的にコミュ障で仕事・調整ができない為にまだ実現していません。
※交流会は、色々と理由をつけて月1回ぐらいで開催しています。
その他、インターンの人たちに対する感想
個人というよりは、全体的な傾向に関する感想です。
素直
変に世間擦れしてなくて、私が作業を依頼する相手としては、とても楽です。例えば、「会社を食い物にしよう」などとは考えない!
事前に何か勉強すべきものはありますか?と聞かれて返答に困る向上心があって偉いです。
勉強すべきものは…、とりあえず基本的には、公式のドキュメントを推奨しています。
angularだとtour of heroesとか。
仕事を盗める
具体的な操作をやってみせると、だいたいみんな、ちゃんと盗みます。
例えばIDEのショートカットキーで、全体検索(grep)を使ってみせるとか。際どい技術的課題についての検索の仕方なんかも、目の前で一度検索したら、特に言わなくてもだいたい身につけてくれます。
逆に適当なコードを書いてたらそれも盗まれたりするので、罪悪感と責任と恐怖を感じます
GitHubとかstack overflowとかを見るのが習慣になっててすごい
stack overflowのコードを完全コピーとかするのは賛否両論ありますが。こういう要件のライブラリ入れて、でGitHubの更新頻度とかも見てちゃんとライブラリを選定してくれた上で、そのドキュメント(たまに英語しかない)をきちんと読んで作業してくれるので、偉い。
「日本の大学」生はおとなしいかも?
ステレオタイプで語ることにあまり意味はないかも?と思いつつ。海外から来ていた日本人学生たちと比較すると、若干おとなしい傾向があったかもしれません。コードを書く量とかスピードは、あまり変わらないですが、何というか、おしとやかな感じの印象を持ちました。私がうまく突っ込んでいないだけかな。。。
海外の方がプログラミングの体系的教育が進んでいる?
ロンドンやアメリカ数カ所(アブダビ含む)では、学校の授業でインデントや関数の長さについての指摘みたいな事を含むコードレビューが当り前に行われているようですが、日本ではそういうのをあまり見たこと無い気がします。
でも、逆の言い方をすれば、そういう教育の仕方が違っていても、日本の大学生でも優秀な人は綺麗に高速にコードを書きますし、海外の大学生で普段そういう教育を受けていても、汚いコードを書く人は汚いコードを書きます。(「汚いコード」を優しく言い換えると、「単純な実装速度を最優先した雑なコード」。当時は実装速度を優先していたので、それはそれで問題無かったのですが。)
一方で、ある日本の私立大学で、以前から筋が良い人が多いのかも?と思っている所があって、そこは大学の教育が良いのかなあと思ったりします。(実態をよく知らないので具体名は控えます。)
起業やマネジメントへの興味は、あったり無かったり
これは完全に人によります。とにかくコーディングが大好き、という人もいれば、コーディングは大好きだけどマネジメントも考えないといけないと思っている、という人も、起業したいから一つの体験としてコーディングをしたい(と言いつつとてもコーディングができる)という人も、将来SIerになる立場として今は実装・開発をやりたい、という人も、色々居ます。
初日にコミットできる
これは環境構築を簡単にしているから、かもしれないですが、基本的に入社初日に必ず何らかの改修をコミット/プッシュしています。このサイクルは今後も維持したいです。
むすび
もっと有給インターンという行為自体が流行るといいなー、と思いました。