seri::diary

日常

リードエンジニアを3ヶ月やって得た開発マネジメントに関する教訓

ここ3ヶ月ぐらい同じRails案件でリードエンジニアとして仕事をしています。 何気にマネジメント的なことをやるのが初めてだったので色々と戸惑うことがありましたが、だいぶ慣れてきて知見が溜まってきたので、自分のしごとの振り返りも兼ねてまとめておきます。

リードエンジニアのお仕事とは

会社やチームによって全くと言っていいぐらい異なると思いますが、私の場合は以下の様なことをしてきました。

開発スタート時

要件確認

  • 仕様書を読んで全体像やどこから着手するかなどを考える

Railsアプリのベース部分の実装

  • rails new
  • DB周りの設定
  • 初期モデルクラスをDB定義に基づいて作成
  • factoryも使いそうなものについてのみ作成
  • rspecrails_config等諸々の設定
  • ローカル環境動作用のseedsを整備
  • 使いたいGemを追加
  • 共通で使うCoffeeScriptのライブラリを思いつく限り実装
  • CoffeeScriptの実装方針が人によってブレるとイヤだったので早い段階でサンプルになるような実装を入れた

情報共有

  • 開発環境構築に必要な情報をgithubwikiやREADME.mdに記載
  • 連携する外部APIなどを事前に検証し、問題がある場合は関係者に確認して解決して対応方法をwikiに記載

開発中

コア機能の実装

  • ひと通りのControllerとviewを実装してひと通り画面が動くように。細かい調整は個別にissue立ててメンバーに割り振り
  • 要件がふわっとしててクライアントに確認が必要な機能や重たい機能の実装

issue量産

  • 各機能ごとに親issueを切り、それに紐づく子issueを作って管理した。

例: 「A機能」が親issueで「Aデータ登録」「Aデータ編集及び削除」「Aデータ一覧」「Aデータ詳細画面」「AデータValidation」が子issueといった具合

その時description内で #100みたいに親issueのIDを参照させておくと、親issueの一覧に子issueのリストが表示される格好になるので進捗管理に便利である。

  • タスクはなるべく親機能ごとに割り振ったがデッドロックになってしまう所もあってやりながら調整した。

他のメンバーのレビュー

  • Railsのレベルはバラバラだったので、Rails経験が浅いメンバーには「何故こうしないといけないのか?」と細かく説明するコメントをつけるよう心がけた
  • 要件自体があまりしっかり決まっていなかったので、かならずローカル環境で動作させて、動作自体に違和感がないかまで含めてチェックした
  • specが落ちていたらまずspecが通るように直してもらってからレビューした
  • Turbolinksの動作原理を理解していないメンバーが数人いたようなので参考資料を読んでもらうよう頼んだりもした

クライアントとのコミュニケーション

  • 要件で不明確な部分の質問
  • 工数的に厳しい場合の代替案の提案
  • 問い合わせ対応

インフラ作業

  • サーバに入れるのが自分だけだったので追加でimageMagickをインストールしないといけないとか、ステージング環境のログを見るとかは全部自分でやっていた

得た教訓

開発方針を統一できるように最初の段階でサンプルになるような完璧な画面を作ってしまうべき

specをどの程度の粒度で書くか、とかConcernに何を載せるか、といった「決め事」が統一出来ずに開発後半では画面によって大分差が出てしまった。

大体のメンバーは自分が実装した所を手本に進めてくれていたが、それも完璧ではなかったので(例えばValidationは後で実装する、とか書いてたらそれまで真似してvalidation処理抜けの画面が量産されて死ねた)、やはり最初に完璧な手本となる画面を実装してしまうべきだった。

特にRailsだと、この機能はControllerにベタ書きか、それともconcernに切り出すか、みたいな判断基準が人によってかなり差がある。

放っておくとfat controllerになったり機能が重複しまくってたりということがいとも簡単に起きて後で泣きを見る羽目になるので、なるべくそういう事故を防ぐためにも最初にサンプルとなる実装をリーダークラスの人間が実装してしまうべきだと考える。

issueを細かく切りすぎず、ある程度大きいまとまりでどばっと渡してしまうべき

これは完全に失敗だったなと思ったのだが、とある機能の画面で以下のようにissueを分けて、それぞれ別の担当者に振ったことがある

  • A入力画面の細々した修正
  • A入力確認画面の細々した修正
  • A入力プレビュー画面の細々した修正
  • A入力最終確認画面の細々した修正
  • A登録画面の細々した修正

そしたら本来共通で実装すべきユーティリティ系のクラスをそれぞれが別々に実装したり、前後の画面で辻褄が合わなくなって自分が全部調整する羽目になったりと、あとで整合性を取るのに凄く労力を要してしまった。

他にあまりタスクが無い時期だったのと、ベースとなる部分は全て自分が実装し終わっていたので大丈夫かと思っていたが、完全に判断ミスだった。

画面の前後でちょっとずつ実装スタイルが違うよりはA機能全体で統一性が取れていた方がレビューもラクだしコードの変な重複が発生する可能性も低い。

実際、開発後半はある程度デカい機能をまるっと投げて、PRのdescriptionでtaskをチェックボックス付きリストにしてもらってそれを一個ずつ消化してもらうスタイルに変えた。上記の例で言えば「A機能の登録・編集・削除全部」みたいな粒度である。そしたら開発効率も品質もかなり上がったように思う。

開発の進め方は最初にきちんとルール化しておくべき

PR駆動の開発の仕方が理解できていないメンバーがいたりして、まぁそんな初歩的なことを教えるのも失礼だし、慣れれば勝手に他の人に合わせてくれるだろと思ったら、数週間経っても全くPRも作らないしcommitも適当だしみたいなスタイルで開発を進め始めたメンバーがいた。

さすがに一人だけ足並みそろえていないのはまずいので、口酸っぱく「作業が終わったらPRを出してください」とか「commitはもっと細かく入れてください」とか「間違ったcommitが入っていないかチェックしてからPRを出してください」とか言い続けて改善してもらったのだが、これが普段の業務において意外なほど大変だった。

少しイライラもしていたのだが、見かねたマネージャーに「長年やってきた人のスタイルはそう簡単に変わりません」と窘められることもあった。確かにその通りだし、自分もたまたまPR駆動で開発するのに慣れているから出来ているだけということもあるだろう。

そんな訳で、今後は開発スタート時にその辺の教育コストを削減できるように、Githubの使い方やらPR駆動のスタイルなどをまとめたドキュメントを作っておいて、それを最初に参照してもらった上でスタートできるようにしようとしている。

具体的には以下のような感じでまとめていく予定である。

丁寧にレビューすれば人は育つ(と思った)ので時間かけてでも丁寧にレビューすべき

何度もレビューの指摘→修正のやり取りをしないといけないケースもあって、そういう時はさすがに「もうめんどいから俺で巻き取るか」といった感情が芽生えてきやすい。この案件もそういう時が何度もあった。

でも、それをやって自分一人で全部巻き取っていたら開発はスケールしないし、費用対効果も悪い。なのでなるべく「一度指摘したことは2回目以降はちゃんとやってもらいたい」と思い、レビュー時に指摘する時も

「これだとXXのケースで動かないので○○としてください」

だけで終わるのではなく、

「これだとXXのケースで動かないので○○としてください。なぜなら△△で□□でほげほげで。。」

みたいな感じで、なるべく理由もセットで指摘するようにした。

そうすれば似たような場面でも応用効かせてくれるかという期待を込めていたのだが、実際一ヶ月も一緒に開発していると段々と効果が現れたのか、同じ指摘は段々と2回しなくても勝手にちゃんとやってくれていたりというケースが増えてきた。

もちろん変わらない人もいたが、一部のメンバーはちゃんと一度指摘したことを守ってくれるようになったので、レビューする側としてはかなり楽になってきた。

ただ、これらの指摘事項は当然自分自身が実践するべきで、多少めんどくさいからと自分が手を抜いていたら「アイツ他人には厳しくて自分は甘えてんじゃん」ということで効果は半減していたように思う。そういうこともあって、なるべく他人に厳しくする分自分のコードにも厳しい目で実装してきたつもりだが、これは自分自身のトレーニングにもなって良かったと思う。

レビューばかりすると自分の担当分が進まない

PRでレビューを依頼されるとすぐに対応して次のタスクを振りたくなるものだが(少なくとも私は)、レビューばかりしていて本業が進まない、という典型的なパターンに自分もハマりかけた。

これに対する解決策としては以下の様なことで対応してきた

  1. すぐにレビューしなくてもやることがすぐ枯渇しないように常に大量にタスクを積んでおく
  2. 本当にすぐ見ないといけないレビューでなければ後に回す
  3. 自分の1日の作業時間においてレビューに割く時間と作業に割く時間を決めておき、それを守る

一番のリスクは「自分がレビューしないことでそのメンバーのタスクが進まない」というロック状態を作り出してしまうことだが、それを回避する方法としては1が意外と有効だった。

レビューする時間を短縮するというのは品質に関わるので避けた方がよく、どちらかと言えば期限を決めてタスクをどかどかと積んで「上から順番にやっていって~」という風に任せてしまった方がラクだと感じた。

この方法を行うリスクとしては、知らないうちに進捗が悪くなっているとか、間違った設計で実装を進めてしまっているということがあるが、なるべくはやくWIP PRを出してもらうことで大体解決していた。

若者と転職

このエントリーはしょぼちむ Advent Calendar 2014 の21日目の記事です。
前日は @fukai_yasu さんの記事でした(まだ未登録?)。その前は@setoazusaさんのしょぼちむにテストファーストについて説明してみるでした。

しょぼちむご本人とは東京で働いていた頃に3回ぐらいプライベートでお酒の席でご一緒させて頂いたぐらい?の関わりでしょうか。何となくjava一派ということで仲良くさせて頂いていました。

お酒の席ではしょぼちむ氏に「いつ辞めるの?」と転職を持ちかけるネタでいじるのが一部界隈では定番なようなので、「若者と転職」というタイトルで駄文を書かせて頂きます。
しょぼちむ氏の参考になれば幸いです。

概要

私は2014年12月現在で28歳になります。
23歳で社会人になったので社会人としては丸5年半やってきたことになりますが、この5年半で3回転職をしています。
平均すれば1つの会社に1年と10ヶ月弱しか勤めていません。
人によっては「だから今どきの若者は…」と眉をひそめられそうな数字ではありますが、それぞれの転職には私なりの考えがあってのことだったりするので、その辺の考えについて説明しつつ、自分の転職感について述べたいと思います。

自分のこれまで

私の社歴をざっくり説明すると以下のようになります。

  • 2009年4月〜2011年11月 某SIerでSE
  • 2011年12月〜2012年12月 某制作会社でエンジニア兼SEのような何でも屋
  • 2012年12月〜2014年6月 某自社サービス会社で自社サービスの開発エンジニア
  • 2014年7月〜 ハートレイルズwebサービス受託開発エンジニア

過去3回の転職の経緯についてはそれぞれ退職or入社エントリーを書いてるのでそちらを参照ください。

それぞれの会社で働いて得られたものをまとめてみると以下のようになります。

SIer

  • 社会人としての基礎スキル(特に電話の取り方からタクシーの乗り方までビジネスマナーについて細かく叩きこまれたのは後々役に立った)
  • IT全般の広く浅い知識
  • 分かりやすいドキュメントと分かりにくいドキュメントの違い
  • 伝統的な日本企業ってこういうものなのかという知見
  • SI業界の現状と課題
  • Oracleを触る貴重な経験

某製作会社

  • 社員5人の会社で働く経験
  • 「自分1人しかエンジニアがいない」という後がない状況での開発をしたことによる精神的な耐性
  • PHPで何でも作る経験(画面からバッチまで)
  • 謎設計の自社フレームワークに泣く経験
  • 前任者が書いたクソコードと戦う力
  • クソコードからドキュメントを起こして正しい仕様を整理しなおしてバグを直してリファクタリングする経験
  • レコメンドエンジンの知識(代理店販売してたので導入サポートをしていた)
  • Objective-Cを1ヶ月で勉強して初めて作って納品したiphoneアプリがいきなり有料アプリとして販売されるというロックな経験
  • 要件定義〜見積もり〜設計〜開発〜テスト〜納品までを全部一人でやるという全フェーズの経験
  • アメリカ人との英語でのメールコミュニケーション(代理店販売しているパッケージ仕様の問い合わせを英語でやってた)

某自社サービス会社

  • 「システムを作ること == お金になる」が成り立たない世界でのエンジニアの会社への貢献
  • 公開中のサービスを◯◯時間バグらせて放置すると☓☓万円の損害になるというお金の考え方
  • ざっくりとした仕様から自分で必要な機能を考えて作る経験
  • すさまじい無茶ぶりにどうにかこうにか頭を捻って形にしてリリースする経験
  • 営業、マーケティング、運用サポート、経理といったエンジニア以外の色んな職種の人の役割、コミュニケーションの取り方
  • 毎月中途採用社員が10人ずつ入ってくる急成長する企業で働くという経験
  • java
  • struts2
  • spring
  • SAStruts
  • dbflute
  • aws
  • fluentd
  • mongodb
  • solr
  • elasticsearch
  • kibana
  • チケット駆動開発の経験
  • gitでやらかした時にどうにかするスキル
  • コードレビューをする、されるという経験
  • 開発現場から離れた技術サポートの仕事の経験
  • 社内外向けの勉強会を会社のオフィス使って開催してアウトプットする経験
  • 40人が参加する開発合宿を企画運営する経験

3回転職をしてみて思ったこと

最初のSIerについては面白くなくて飛び出した感が強いのも正直な所なのですが、振り返ってみればこれまで務めてきた会社で学びがなかったものは一社もなく、それぞれの企業で自分が出来ることを増やした上で転職してきたのだなと今にして思います。

転職する目的というのは人によって沢山あると思いますが、何にせよ「プラス思考の目的」が無いと上手くいかないのではないかと思っています。

給料が安い、仕事が面白くない、人間関係が悪い、といったマイナス思考の目的だけで飛び出しても、また次の会社で同じトラブルがあった時に対処する術を身につけていないのでまた辞めるしかありません。 Team Geek にも書いてありますが、組織というのは組織の問題を解決してくれる人を求めている訳で、自分が課題だと感じたことにどうアプローチしてきたかという実績が無いと企業から見て魅力的な人材にはなれません。

それは本人にとっても会社にとっても不幸だと思うので、自分は必ずプラス思考の目的が無ければ転職はしませんでした。
プラス思考の目的があれば、直面した課題を上手く解決するモチベーションが湧くか、プラス要素で相殺して我慢できます。 (自分は我慢できないタイプなので大抵課題には口を出してしまうのですが…)

最初のSIerには2年半いて、最初の1年目にして「仕事が面白くない…つらい…」とずっとぼやいていましたが、自分がやりたいこと、目指したいことがはっきりするまで辞めませんでした。 それは前述したように、マイナス思考の目的だけで飛び出しても問題は解決しないし、なんかカッコ悪いと感じたからです。(なお、当時見つけた「やりたいこと」は自分でインフラの面倒もコードも書けるようになってwebサービスを作ることでした)

転職するという行為自体について考えれば、文字通り職場を変えることになるので基本的にリスクが大きいわけです。何度その会社の社員と面接をしても、その会社の空気や思想というのは入社して働いてみないと分かりません。

だから、自分が実現したいことがはっきりとしていて、その会社に転職すれば自分にとってプラスになる、と思えるのであれば積極的に転職すれば良いのではないでしょうか、というのが自分の考えです。

逆に、そういうのが見えなければ転職すべきではなく、するべきは自分が感じている課題を解決することだったり、自分のキャリアを考えることだと思います。

課題を解決するために

いくつか方法があるかと思いますが、自分にとって良かったと思えた方法が、他社の人にその人の会社の状況について聞いてみることです。 隣の芝は青いと言いますが、自分が抱えている問題が自分の組織だけの問題なのか、はたまた他も同じような課題があるのかという判断は社外の人と話さないと区別がつきません。

エンジニアの場合、大抵twitterFacebookやっているので、面識がない人でもコンタクトを取るのはさほど難しくありません。(実際、一度も会ったこと無いのにいきなりDM送って飲みに行って仲良くなったエンジニアが何人かいますw)勉強会の懇親会とかでも良いと思います。

あとは転職エージェントにコンタクトを取ってキャリアについて相談してみるのも良いと思います。自分も2回目の転職は転職エージェントに相談した上で紹介してもらっています。

対象は誰であれ、自分一人で抱えていても仕方がないのでなるべく普段接していない人との接触が重要かと思います。内輪だと大抵愚痴大会になってしまうのでw

自分のこれから

どんだけ年を取っても、自分が手を動かす、あるいは常に動かすことができるエンジニアとしてのスキルと知識を保ち、それらをコアにビジネスにコミットしていける人間でありたいと考えています。

今は自分が持っているスキルを「お客様の事業を行うためのwebサービスの受託開発」という形で発揮し、お客様の様々な事業に関わりながらwebサービスでどういう価値を社会に提供出来るのか、ということについて勉強している最中です。

とにかく案件の数をこなして、

  • それを自分がどれくらいのスピードとクオリティで開発できるのか
  • どう開発したら上手くプロジェクトが回せるのか
  • チームの生産性を上げるにはどうすればいいのか
  • どうやってメンバーのスキルを上げていくのか

ということについての方法を学びたいと考えています。

自分が目指すポジション

ここ5年以内に目指すキャリアパスとしてはエンジニアのマネージャーとしてのポジションを目指しています。プロダクト開発をリードする立場というよりは、チーム内のメンバーのマネジメントをするポジション、のようなイメージです(伊藤直也さん的な?)

ビジネスより技術が好き!でスタートしたこのキャリアですが、結局ソフトウェアは人が開発するものであって、どんな開発現場でも人の問題が絡んできます。社員のほとんどがエンジニアという現職でも人の問題は起きるし、これまでの経験においても人の問題でプロジェクトが上手くいかなかったりしました。

そういう時に、エンジニア間で起きる問題を上手く解決し、適切にリスクを考慮して意思決定をしてくれた人が前職には数名いたのですが、彼らのような振る舞いはどんな開発チームにいっても必要になる振る舞いで、またそれが出来る人が非常に少ないと感じています。 大体エンジニアは自分含めて変な人が多いですし、そういう人の気持ちを理解できる立場でありつつ、上手くまとめて開発をワークさせる仕事はビジネス的に価値があると感じているし、何よりそういう人に自分が憧れました。

そういうポジションで働くことが出来るのが今の会社なのか、はたまた別の会社になるのか分かりませんが、その時はその時で自分にとって最善の選択をしたいと思います。

自分がなりたい自分になるために

これまでの自分の転職の目的は、どれも「自分がチャレンジしたいことをするため」という感じでしたが、それが実現できたのも自分がそれぞれの企業でスキルを磨いてきたからだと思っています。 なんだかんだでエンジニアはスキルが重要なので、やりたいことをやろうと思ったら常に自分を成長させ続ける必要があると考えています。

@kwappa さんの「The Art of Job Hopping」というスライドにも以下のように書かれています。

I'm happy because I could escape
I could escape because trained day by day

日々努力を怠らず、これからも一人のエンジニアとして自分を鍛錬し続けたいと思います。

2014年総括

mixiやってた頃から毎年こんなのを書いてる気がするので今年も書いてみます。

今年初めて出来たこと

  • ガロリアマンドリンオーケストラに所属し東京での音楽活動が出来た
  • マンドリン合奏コンクールに出た。コンクールというものに出たのは21年前に出たピティナ以来なので初体験ということにしておく。
  • ガチのハッカーがビズリーチにjoinして一緒に仕事した
  • 自分のキャリアの中で初めて事業に直接関与しない部署に所属し後方支援の仕事をした(2014/1〜2014/6)
  • 社内勉強会で毎週LTするのを3ヶ月続けた
  • 新卒に3日でjs + jquery教えるという無謀なことをしたら案の定「早過ぎる」という苦情を新卒から受けて涙目になる
  • fluentd + elasticsearch + kibanaを現場に導入してSlow query駆逐に貢献した
  • Swiftを触った(βの頃)
  • リモートワーク始めて自宅引篭り属性が付与された

職場

  • Rubyを学んだ
  • CoffeeScriptを学んだ
  • Railsを学んだ
  • 仕事でRailsを使ってアプリをこしらえた
  • GithubでPR駆動開発をした
  • RubyMineのキーバインドが使い物にならないのでこの後めちゃくちゃカスタマイズした
  • Kotolin勉強会でメガネが似合う某Kotolinアイドルとのじゃんけんに勝利しInteliJ IDEA Ultimateのライセンスをタダでもらった
  • 男友達とだけで箱根旅行した

ふね

  • 練習のためだけにクソgemを書いたが封印した

今年やろうとしたができなかったこと

  • 前職で社内の技術支援の仕事をしていながらほとんど成果を出せなかった
  • OSS活動するぜとかgem作るぜとか言ってたが何一つ公開できなかった
  • 2014年中に新しいwebサービスを公開しようとしたが何一つ公開できなかった
  • Swiftiphoneアプリ活動再開するぜとか言ってたが何一つやらなかった
  • Kotolin書かなかった(しょぼちむさんたろうさんイケメンさんごめんなさいごめんなさい)
  • アマチュアギターコンクールに挑戦しようとしたが時間的に余裕が無く参加できなかった
  • クラシックギターの独奏レパートリーを常に10曲ぐらいにしようとしたが1曲も増えなかった
  • クロスバイクで多摩サイ爆走しようとしたがあまり乗れなかった
  • 今年入ってから体重70キロを超えていたことに危機感を覚えて60キロ台に戻そうとしたができなかった

今年の反省点

  • 悪い意味で内向的になり過ぎて自分の力だけで成果を出そうとして失敗した局面が多かった
  • プライベートで色々やろうとしすぎて中途半端になってプログラミング活動と音楽活動の両立に失敗した
  • ブログあまり書けなかった(その分Qiitaは結構書いた)
  • 勉強会でほとんど発表できなかった
  • 自分の気持ちを落ち着ける時間を蔑ろにしていつも予定を詰め込んでいたせいか心が不安定な時が多く周囲に迷惑をかけた
  • プライベートの時間をダラダラ過ごしすぎてしまいプライベート活動に割ける時間が少なかった
  • リモートワークで働き過ぎて常に今年10月以降は日常的に疲労感が抜けなくなっていた
  • 赤城さんとケッコンカッコカリできなかった
  • 食生活悪すぎて大して食べてないのに体重増えすぎた

来年の展望

  • 自分がやりたいことを実現するために自分の力だけで実現しようとするのではなく周りをきちんと巻き込む
  • プライベートの時間を有効活用することを心がけ、ダラダラニコ動観たりして時間つぶさない
  • 何に集中するかを選択して「今やるべきではない」と判断した活動は一切しない
  • ヴァイオリン始める
  • 1日1日を大事に生きる。気がつけば20代最後の年なのでもはや人生は残り僅か。
  • 今時のフロントエンドjsを真面目に学ぶ。まずはAngularjsとgulp入門する(今更感すごい)
  • 仕事でのDeveloperProductivity向上のために積極的にできることをする
  • 勉強会LTしないなら出ない、出るならLTする
  • クラシックギターのソロ曲のレパートリーでネタ曲5曲、ガチ曲5曲の計10曲用意できるようにする
  • アマチュアギターコンクール2015のテープ審査に応募する
  • gemリリースするぞ!
  • Qiitaだけでなくブログを毎週書いてなんでもいいからアウトプットし続ける
  • 赤城さんとケッコンカッコカリする
  • 青葉ともケッコンカッコカリする

盛岡に引っ越して一ヶ月が経った

一ヶ月が経ったらブログに所感を書こうと思っていたんですが、思いの外書くことがなくて困りましたが、とりあえず生存報告も兼ねて書いてみます。

寒い

「盛岡とは言え10月ならまだそこまで寒かないし東京圏から引っ越してもそこまで気温差ないだろう」と思ったら引越した初日に台風に直撃されたこともありめちゃくちゃ寒く、翌週から普段着てるものにプラス1枚着る生活に。盛岡先輩パネェっす。
最近も日々寒くなりつつ有りますが、まだファンヒーターを出さずとも重ね着で何とかしのいでおるレベルであります。

普段の生活は殆んど変わらない

自宅で仕事してるので当たり前ですがw
食事はだいたい自炊、たまに外食。週に1回仕事後にマンドリンオケの練習。そんな感じです。

2つの勉強会に参加しました。

「IWDD」

エンジニア・デザイナー向けの毎月開催されている勉強会で、次回で97回目を迎える歴史の長い勉強会です。

参加者は盛岡市内or近郊?で働くフリーランスのエンジニア・デザイナの方が中心のようでした。

自分は前回の第96回に参加して、簡単な自己紹介のLTのようなもの+岩手県内のエンジニアコミュニティ事情の情報交換をさせて頂きました。

このブログでも書きましたが、岩手でrubyのコミュニティが無いようだったのでiwate.rbみたいなのを開催したいという野望があったので、今時点での需要調査みたいなものも兼ねてやってみたんですが、

  • 岩手県内の勉強会は参加者が少ない
  • そのため大体どの勉強会に行っても同じ顔と会うw
  • iwate.rbも昔あったけど参加者が少なかった
  • なのでIWDDでまとめてやるのが早いのでは?

…というような感じだったので、とりあえず次回のIWDDで一枠もらって、私がrubyについて何か語って反応を見てみる予定です。

私もruby歴というかrails歴半年とかそういうレベルなので、とりあえず今まで自分が勉強してきたことのまとめ的な「rubyのここに惚れた」みたいな、渋谷javaでも話したようなネタをまたやってみたいと思いますw (そういえば1年半ぐらいのスパンで仕事で使うメインの言語変わってるんですね私)

「いわてTitanium勉強会」

Titaniumのハンズオン+フリートークという構成の勉強会で、今年から始まった新しい勉強会のようです。

こちらの勉強会は参加者の年齢層が非常に若く、今年で28の私が最年長という、何とも若々しいコミュニティで、岩手県立大学の現役の学生、或いは卒業生が中心(というかみんなw)でした。

開催しているのは盛岡市内のベンチャーである株式会社チイキットのメンバーで、先日こちらの会社の @isseniumさんと呑んだ時に教えてもらい参加しました。

スマフォアプリはネイティブでiphoneアプリandroidアプリの両方をちょろっとやったことある程度で、Titaniumは環境構築でハマって挫折した経験しかない私でしたが、流石にハンズオンということもあり変なトラブルにハマることなく定番のTodoアプリの実装を通してTitaniumのAlloyフレームワークの使い方を知る、という内容でした。

初めてTitanium触ってみましたがviewをHTML + CSSライクに書けるのは直感的というか学習コスト低くて良さそうですね。
ただTitanium Studioの最新版が少し不安定なのと重たい(Ecipseベースだから?)ので、みんなどうしてるんかなと思ったらTitanium Studioは使わないで好きなエディタで書いてコンパイルはTitaniumのCLIツールでやる人が多いんだとか。
jsではなくCoffeScriptでロジックを実装する場合もCLIツールでビルドという流れのようなので、gruntでビルドするような場合とかも考えるとエディタとしてTitanium Studio使わない方が自由度高くて良いのかも、という気がしました。

今後について

まだ盛岡でノマドしてないので今月はどこかでやろうかなと。

先月は固定回線の開通が引越し日の4日後とかになってしまったので、それまでテザリングでしのいでいたせいで月初にLTEの7GB制限ギリギリになってしまいとてもノマド出来る状態ではありませんでしたw

11月になって晴れて堂々とテザリング使えるようになったので、仕事に余裕がある時はどこか行ってノマドしようと思います。盛岡市内はタダでWi-fi使える所は少ないのですが、とりあえず王道のスタバで気分転換兼ねてやってみようかなと思います。

不要品処分で役に立ったサービスまとめ

f:id:serihiro:20141002075144j:plain

ここ3ヶ月ぐらい盛岡への引越し準備を進めていたのですが、引越しに伴う不要品処分で利用したサービスなどを紹介します

買取・不要品無料回収サービス

バイクランド

f:id:serihiro:20141002080842p:plain

  • バイク買取サイト
  • 一括見積りサイトでまとめて見積もりを出してもらった所、一番査定額が高かった
  • 担当者の方が査定額が高くなるポイント・下がるポイントを明確に説明してくれたので金額に納得できた
  • 走行距離1万キロで中古で買ったHONDA VTR250 2009年式を買った額の7割ぐらいで買い取ってもらえた

ドクターヘルメット

f:id:serihiro:20141002080845p:plain

  • バイクのヘルメット買取サイト
  • 送料着払い
  • 配送用のダンボールをタダで送ってれる
  • 2年前に5万ぐらいで買って常用利用してたAraiのヘルメットが1万ぐらいで売れた

ブックリバー

f:id:serihiro:20141002080846p:plain

  • 古本・DVD・ゲーム等の買取サイト
  • 送料着払い
  • ダンボールは自分で用意する
  • 事前に買い取って欲しいISBNをwebサイトのフォームから送ると1営業日ぐらいで査定額をエクセルシートでメールで送ってもらえる
  • 2~3年前に発売されたアニメのBlue-rayとかアメリカのホームドラマのDVDボックスとかをやたら高く買い取ってもらえた

ブックスドリーム 専門書アカデミー

f:id:serihiro:20141002080849p:plain

  • 専門書・技術書などの買取サイト
  • 送料着払い
  • 配送用のダンボールをタダで送ってれる
  • 依頼すれば書籍毎の査定額を教えてもらえる(今回は使わなかった)
  • 高価買取りの書籍リストをwebサイトに掲載しており、実際そのリス トにある商品を買い取ってもらえた所掲載通りの額だった
  • 主に技術書やビジネス本を売ったが、普通の古本屋に出すよりは遥かに高く買い取ってもらえた

パソコン回収.com

f:id:serihiro:20141002081123p:plain

  • ITメディアの記事で取り上げられていたので使ってみた
  • 一部の商品は出張買取無料なので梱包不要
  • 電話したらやたら回収がかなり混んでいて電話した日から2週間後じゃないと予約できなかった
  • 回収日当日の時間指定はできなかった(私は在宅人間なので関係ナシw)
  • 15inch液晶とプリンタとXBOX360を無料で回収してもらった

住所移動に伴うサービス

引越れんらく帳

f:id:serihiro:20141002081918p:plain

  • 電気・ガス・水道・ネットなどの住所移動手続きをネットから一括で出来る東京電力が提供するサービス
  • 現住所での利用停止・新住所での利用開始手続きができる(但し提携業者のみ)
  • 自分が引っ越す盛岡の業者には対応してなかったので、今使っている電気・水道・ガスの利用停止手続きに利用した

タスク管理

Githubのissue

f:id:serihiro:20141002082331p:plain

  • 自分の適当なprivate repositoryのissueで管理していた
  • メモは全部コメントに残しておいた
  • 仕事中に業者から電話がかかってきてちょろっとメモりたい時とか確認したい時に便利だった

その他

24インチのディスプレイとミドルタワーのPC本体を運ぶためにデカい箱を買ったら素材もしっかりしてて良い感じだった

引越しの準備で得た知見

  • 一括見積もりサイトを使うと大量の業者から平日の朝からジャンジャン電話がかかってきて最高にめんどくさかったので余程の理由がない限りオススメしない
  • ネットの回線を移動させようとしたら前入所者の回線が契約されたままですぐに移動手続きができなくて手続き開始が10日ほど遅れたので、出来るだけ早めに回線移動の手続きを始めた方がよい
  • 郵便の転送サービスは転送が始まるまでに1週間ほどのバッファが発生するので早めに申し込んだ方がよい
  • 同じ部屋に3年も住むと意外と要らないものが大量に貯まっていることがあるので定期的に不要品は処分した方がよい
  • 単身引越であっても500キロ以上の長距離移動になると引越し代が凄まじい事になる
  • 地方都市限定の話かも知れないが、8月中旬に独り暮らし向けの物件探しをしても殆んど物件がないのでつらい

次回は盛岡から更新します

エンジニアとしての不安

(完全にぼやきですw)

エンジニアとして働くようになってからはや3年が経ちます(SE時代の2年半はコード書いてないのでノーカン)。

SE時代に憧れていた「コードを書いて飯を食う」ということが少なからず出来るようになってきてはいますが、それでも毎日自分の出来なさに落ち込むことが多々あります。

前職でも入社直後にDIとInterceptorをフルに使いまくったjavaのコードの追い方が分からなくて全然仕事が進まなくて落ち込んだり、しょうもないバグを埋め込んでリリース当日にパニクったりと色々やらかしてきた歴史があります。

それでもずっと続けていればミスもなくなり出来ることも増え、以前は苦労してやっていたことがラクに出来るようになったりと、成長のようなものを感じることはあります。そういう状態が続くとまぁ気持ちのよいものです。慣れた言語、FW等の環境で全力疾走出来る時ほど気持ちいい時はありません。

しかしエンジニアたるものとしては同じ環境で同じものを作り続ける訳にはいかない訳で、最近、また前職の入社直後のような「前に進めない」壁を感じています。

具体的には、ゼロからwebアプリを設計して作ることが難しいと感じています。考えてみれば今までアーキテクトとしてゼロから基板を作ったことが殆んど無かった。

今は主にRailsで仕事をしていますが、Railsでwebアプリを「とりあえず」作ることは至極簡単です。 java + strtus2より遙かにシンプルで分かりやすい。 すぐに動くものが作れる。 Ruby on Rails Guidesという素晴らしいドキュメントがある。

問題はRailsで作るwebアプリ全体のアーキテクチャで、 どういうルーティングでどういうコントローラを設計するか、 モデル(ActiveRecord::Baseのサブクラスの方)にどこまで業務ロジックを乗せるか、 helperやconcernをどう使うか、などなど。

考え出せばキリがない。考えても考もしっくり来る設計が出来ない。本当にこれでいいのか?という手探り感。 これがどうしても拭えません。

この辺も慣れの問題なのかなぁとは思いますが、今の所はよく分かっていません。 とりあえずRESTで設計することに慣れていないのでRESTの思想を勉強していく必要は感じていますが、それ以上に何が必要なのか。。良く分かりませんが、良くわからない以上は実践で学ぶしかないので今やってるプロジェクトをとにかく進めるしかない。

こういう壁に当たると、自分はよく伊藤直也さんのブログのエントリー「エンジニアの不安と壁」というエントリーを読んで自分を奮い立たせてきたのですが、今は何故かあまり楽観的に考えられないというか、色々と悩ましく考えてしまいますw

たまたま9月はやたら忙しくて(勉強会開催、引越の準備や色々調整、マンドリンオケ本番、友人との旅行の幹事、会社の合宿の幹事)肉体的にも精神的にも疲れてるせいか分かりませんが、10月は多少ゆったり出来る事を少しは期待したいと思います。

今更ながらTurbolinksを初めて仕事で使ってみたので色々調べてみた

f:id:serihiro:20140802065933j:plain

※このエントリーで使用している検証環境の各種バージョンは下記の通りです。

  • Railsのバージョンは4.1.4
  • Rubyのバージョンは2.1.2p95
  • Chromeのバージョンは36.0.1985.125 m

※このエントリーの最終更新日は2014.8.11です

2013年辺りのRails4について書かれたブログを読むとTurbolinksに関するエントリが結構多いんですね。

ざっとググって1ページ目に来るのがこれらのエントリー。

そして同じぐらい目にするのが「Turbolinksをオフにする方法」

Railsを使ってなかった頃からtwitterとかでちょいちょい流れてくるTurbolinksの記事を流し読み程度に読んでいたのですが、色んな人が解説エントリを書くほど注目されている一方で、何故か無効にする方法がやたら充実しています。
使っていいのダメなの??ということが外から判断できないということで、どんな恐ろしい機能なのかとjavaを書きながら横目でチラチラを見守っていたのですが、遂に今の職場で使う機会に巡りあいました。これも何かの運命でしょうか。

で、良い機会ですのでTurbolinksについてじっくり調べてみました。 さらに身を持ってその仕様を体験するためにちょっとした実験をやってみたのでその結果をご紹介します。

なお、本エントリーはRailsでアプリを作る人がturbolinksを使う時に気をつけること、というレベルでまとめたので、Turbolinksの実装の詳細についてはあまり触れていませんが、冒頭で紹介したリンク先の内容に詳しく記述されていますのでそちらを読むとさらに理解が深まると思います。

Turbolinksとは

Githubの本家リポジトリrails/turbolinks · GitHubでは以下のように説明されています。

  • Turbolinksはあなたのアプリケーションを早くするよ!
  • ブラウザにjs,cssをリコンパイルさせずに現在のページをActiveに保ってbodyとtitleとheadだけを書き変えるよ!
  • pjaxと似てるけど、Turbolinksは何も考えずにbodyをガバっとreplaceしてくれるのでサーバ側で特別なことをせずにpjaxを使うのとほぼ同じような恩恵を得られるよ!
  • もちろん(現在のページをActiveに保つということは)ブラウザ上でjsの長時間のプロセスを持続することになるので、処理の肥大化やメモリリークに気をつける必要があるけど、あなたがファンキーなことをしなければ多分大丈夫だよ!

要するにページ遷移(GETのみ)を通常のページ移動ではなくajaxで取得したhtmlでbodyを入れ変えるだけの処理に差し替えることで高速化するgemです。 似たようなことをしてくれるライブラリとしてpjaxというjqueryライブラリがあります。

Turbolinksにおけるjsの取り扱い

しかし手放しで何も考えずに入れとけばちゃんと動くというものでもないようです。

  • 最初にロードしたページがActive状態であり続ける
  • jsのプロセスが持続する

この事実を考慮すると今まで書いていたjsがそのまま動くのかちょっと不安になります。

例えばこんなコードはTurbolinksを使ってるページでもページ遷移毎に実行されるのでしょうか?

<script>
window.onload = function(){
  console.log('nya-n');
});
</script>

window.onloadの実行タイミングはページ全体がロードされた後のはず。 ってことは、最初の1ページ目の表示では問題なくwindow.onloadが発火しそうですが、Turbolinksが有効になっているページでページ遷移した時は動くのでしょうか? ついでに頻繁に使う$(document).ready

迷ったら実験しましょう。

実験 各イベントはいつ発火するのか

rails4.1.4で簡単なサンプルを作りました。
サンプルコードのリポジトリこちらです。

$ rake routes
Prefix Verb URI Pattern      Controller#Action
  root GET  /                index#index
 other GET  /other(.:format) index#other

/views/index/index.html.erb

/views/index/other.html.erb

/assets/javascripts/index.js.coffee

rails sして実際にアクセスしてみます。

実験1  index/indexのURLを指定してアクセス

f:id:serihiro:20140810144656p:plain

  1. ベタ書きしたjsの即時関数
  2. assets配下のCoffeeScriptに書いた$(document).ready
  3. ベタ書きした$(document).ready
  4. page:change
  5. page:update
  6. assets配下のCofeeScriptに書いた$(window).load
  7. ベタ書きした$(window).load

実験2 リンクをクリックしてindex/otherへページ遷移

f:id:serihiro:20140810145149p:plain

  1. page:before-change
  2. page:fetch
  3. page:receive
  4. ベタ書きしたjsの即時関数
  5. ベタ書きした$(document).ready
  6. page:change
  7. page:update
  8. page:load

実験3 リンクをクリックしてindex/indexへページ遷移

f:id:serihiro:20140810145730p:plain

  1. page:before-change
  2. page:fetch
  3. page:receive
  4. ベタ書きしたjsの即時関数
  5. ベタ書きした$(document).ready
  6. page:change
  7. page:update
  8. page:load

この結果から以下のことが言えます。

  • $(window).loadはページの初回表示時のみ実行され、リンクをクリックして遷移した場合は実行されない
  • $(document).readyはページの初回表示時のみ実行され、リンクをクリックして遷移した場合は実行されない
  • テンプレートファイルにベタ書きしたjsはページ遷移毎に実行される
  • テンプレートファイルにベタ書きした$(documebt).readyはページ遷移毎に実行される
  • テンプレートファイルにベタ書きした$(window).loadはリンクをクリックして遷移した場合は実行されない

assets配下のCoffeScriptに書いた処理はTurbolinksの管理配下の挙動になり、テンプレートファイルに書いたjsはページ遷移毎にそのまま実行されるようです。
こちらの記事にも書いてありますが、ページ遷移の度にロードされたhtml内のbodyタグ内のjsタグを取得して、新規のjsタグを組み立て再度差し込んで実行させているようです。

処理的には、turbolinks本体のCoffeeScriptを読み込んだ時にAタグをクリックした際にxhrオブジェクトを作ってxhrオブジェクトからリクエストを飛ばす処理をbindしているのですが、ページ遷移時の詳細な挙動はQiitaのこちらの記事に詳しく説明されています。 CoffeeScript側のソースだけなら436行しかないのですぐ読めますので気になる方は一度全部読んでみると良いと思います。実装自体は割と素直に書いてありますので読みやすいです。

Turbolinks導入のメリット

最初に書いたようにTurbolinksを導入することの利点はページロードの高速化です。html全体を再ロードしないため、ブラウザ上での体感速度向上が期待できます。

Turbolinks導入のデメリット

これまで書いてきたjsが動かなくなる可能性が高い

通常のwebページとjsの挙動が大きく変わるためこれまで作ってきたjsが上手く動作しない可能性が高くなります。
これまでRails3で作ってきたrailsアプリケーションをrails4にアップグレードした途端に正しく動かなくなるといったことが簡単に発生します。

ページ遷移してもmetaタグが更新されない

ページ遷移してもCSRF-Token以外のmetaタグが更新されないという挙動になっています。

そのため、普通ページ毎に内容が異なるogタグ等もページ遷移しても更新されません。 しかし、実際にfacebookのいいね!ボタンをクリックしたりした場合においては、フルロードしたコンテンツを各SNSが取得してくれるはずなので問題無いのでは?というようなコメントがついています。DHHも「それが必要なユースケースは聞いたことがない(I haven't heard a compelling use case yet)」とコメントしています。

既存のjsが動かなくなるケース

既存のjsをそのまま使おうとした時にどんな問題が起きるか具体例を上げて説明します。

$(document).readyにイベントをbindする処理を書いてたら最初にアクセスしたページではbindされるが遷移したらbindされない

$(document).readyはリンククリックでのページ遷移では発火しないので、同じjsファイルを読み込んでいるのに「外部リンクから最初にやってきた時しか正しく動かない」ということが起きます。

$(document)に同じイベントが多重bindされて正しい挙動にならない

全ページで読み込むjsで(例えば共有しているテンプレートファイルにベタ書き)即時関数で以下のbind処理を記述したとします。

<script>
$(function(){
  $(document).on('click', '#button', function(){
    console.log('ニャーン');
  })();
});
</script>

で、何度もページ遷移してから#bindをクリックするとページ遷移した分だけconsoleに「ニャーン」と表示されます。猫好きの私歓喜!とか言ってる場合じゃありません。

これが発生する原因は、最初に書いたとおりjsのプロセスがずっと継続するため、$(document)のオブジェクトはページ遷移してもずっと同一のものが生存し続けています。
そのため、ページ遷移する度にbindするようにすると、同一の$(document)オブジェクトに再度bindしてしまうため、何重にも同じイベントがbindされることになります。 私も最初この挙動にハマって小一時間悩みました…。1回のアクションでajaxリクエストが複数回飛んでるっぽい?などの分かりにくい問題が起こります。

なんでみんなオフにしたがるのか?

既存アプリにTurbolinksを導入する場合、「デメリットの方が多くなるケースが多い」ということに尽きると思います。 具体的には * jsをTurbolinksの挙動に合わせて修正するコストが高い * Turbolinksの挙動を正しく理解していないと簡単にトラブルになる * フロントエンドを担当するエンジニアへの負担が大きくなる といった所が問題になりそうです。想像の範囲ですが。

それでもTurbolinksを有効にする場合に気をつけること

urbolinksを使用する際のjs実装について気をつけることについて説明します。

ページ遷移の度に実行したいjsの実装

lightboxやmasonryなどのデザイン系のjQueryプラグインを適用するケースによくある「ページ遷移の度に実行したい」場合。 多重実行されるとやっぱり挙動がおかしくなるので、「複数回実行はさせたくないがページ遷移毎に1回だけ実行したい」という要件になります。

これを実現するにはいくつか方法があります。

1. テンプレートファイルにベタ書きする

毎回実行されることが保証されていますのでテンプレートファイルに記述すれば良さそうです。ただ、jsはassetsで管理してapplication.jsの1ファイルにまとめてロードするというrailsの作法からはちょっと外れる形にはなります(これも厳密に守るのはかなり難しい作法ですが)

2. $(document).readypage:loadの両方で実行されるようにassets管理下のjs,coffeescriptに記述する

$(document).readyはページ初回表示時にのみ実行され、page:loadはページ遷移時にのみ実行されます。ページ初回表示時には実行されません。

なので、同じ処理を両イベントでbindしておけば、常にページ遷移ごとに一回だけ実行されることが保証されます。

以下のように記述します。

$(document).on 'ready page:load', -> 
  console.log 'ready and load'

これでページ遷移毎に実行され、かつ一回だけ実行されます。

ただし、ブラウザバックで戻った時にはpage:loadが実行されないので、ブラウザバックで実行されなくて困る処理はpage:changeにbindする必要があります。 しかし、turbolinks使用時にブラウザの戻るボタンをクリックした場合、turbolinksが内部でキャッシュしているpageCacheからページが復元され(turbolinksはURLの書き換え等にhisotry APIを使っています)、pushStateが使えない場合はリダイレクトされる(location.hrefを書き変えてます)ので大体の場合において問題は起きないと思います。

イベントのbind

難しいのはこっちで、いくつか方法が考えられますがどの方法を取るにしても開発チーム内で話し合って決めておく必要があります。 主な関心事としては「多重bind」をいかに防止するかということになりますが、逆に多重bindされても問題がないようにイベントのハンドラを実装しておくというの手です。

まず前提条件としてテンプレートファイルにベタ書きせず、assetで管理されているjs、CoffeeScriptのファイルに記述することが条件になります。
テンプレートファイルにイベントをbindする処理を普通に書くとページ遷移毎にイベントがbindされるので$(document)の場合は上手くワークしません。 テンプレートファイルにjsを書かなければいけないケースはControllerから値を渡すようなケースに限定して、使わないように開発チーム内で取り決めをしておく必要があります。

1.$(document)にbindする場合

ajaxで後からロードするhtmlに対してイベントを定義しておく場合などによく用いられるケースです。

assetでapplication.js1つにjsがまとめられる場合は、$(document).ready内でbindするように記述します。

■/assets/path/index.js.coffee

$(document).ready ->
  $(document).on 'click', '#popup', (e)->
    alert('popup') 
  $(document).on 'hover', '.menu', (e)->
    e.currentTarget.addClass('hovered')

上述の通り初回表示時にのみ実行されるため、初回表示時に$(document)にbindする全てのイベントがbindされその後ページ遷移しても実行されません。
これにより確実に一回だけイベントがbindされます。ページ遷移毎に$(document) にbindするように実装すると上述した通り同じイベントが同じDOMに何重にもbindされて不具合を起こすケースがあります。

イベントのbind自体は$(document)に直接bindするのが一番早いようですし、パフォーマンス的にも問題は起こりにくい方法だと考えられますので、特別な理由が無い限り、イベントのbindは$(document).on({event}, {selector}, {callback})の形式に統一してしまうのが良いのではないかと思います。
参考:高速で安全なjQueryを書くために今できること | Dress Cording

ページごとにjsを読み込む場合は、そもそもturbolinksのページ遷移にならず通常の遷移になるので気にする必要はないですが、turbolinksの恩恵を受けられなくなります。

2.指定のセレクタにbindする場合

$(document).'ready page:load'でbindするようにすればページ遷移毎に実行されますので、これで対応出来ると思います。

こんな面倒なことしてられるか!俺はRails4でも今までどおりに開発させてもらう!という場合

特定のリンク時のみturbolinksで遷移せず通常のページ遷移をするようにする場合

aタグにdata-no-turbolinkという属性を付けます。 例:

<a href="/user" data-no-turbolink>User List</a>

全ページでリンククリック時のページ遷移にturbolinksを使わない場合

gemファイルとturbolinksを読み込んでる箇所をjs,htmlから削除します。turbolinksのソース読み込んだ時にAタグにbindingされるんでそりゃそうですが。
詳しい手順はこちらを参照。

まとめ

以上、簡単ですがturbolinksの挙動と実際に使う場合の注意点について述べました。
文中でも書いたとおり、これまでの色々なweb上でのjsの常識が通じなくなりますので、既存のjsを流用する場合はかなりの手間が必要になります。
またAngular.jsなどのフロントエンドフレームワークを使う場合においても対応が必要なようです。

そのためjsを多用したSPAを作る場合や、開発メンバーが不慣れな場合はturbolinks自体使わないという選択肢もアリだと思います。正直私も最近初めて使ったのですが最初は色々なものが動いたり動かなかったりでなんじゃこりゃと思いました。

ただ、Rails4から標準で有効になっている以上、Railsの作法の一つとして実装されているものだと考えています。
今後のバージョンアップでどうなるか分かりませんが、今後Railsで新規アプリを作っていくのであれば、うまい付き合い方を知っておいた方が結果的にRails Wayの恩恵をより受けられるようになっていくのではないかと勝手に考え、今回の機会にまとめてみました。