プログラムの効率的な読み方

casstteの延澤です。
今回はプログラムの読みかたについて書いていきます。

まず既存のシステムに新規の機能を追加する時に、

「あなたはどのファイルから開きますか?」

この質問について答えていくのが今回のブログの内容になります。

何故読み方が大事なのか

出来るエンジニアは平凡なエンジニアに比べて100倍生産力が違うと言われています。自分は出来るエンジニアは読むのが速いため設計・実装の時間に十分な時間が取れるから生産力が違うという意味で解釈しています。
逆に考えると読む時間が遅いと設計・実装の時間が足りず、考慮漏れなどを起こし二度手間を発生させる確率が高くなることに繋がります。 ともかくエンジニアの作業はコードを書いているイメージが先行しますが実は他人のコードやドキュメントを読んでいる時間がほとんどです。

また、学生時代はプログラミングが得意だった人も就職してみると当初思ったほど最初に仕事が出来ないことがあります。これは圧倒的に他人のコードを読む時間が不足しているのも理由の一つです。
なので当たり前すぎて軽視されがちな読みかたについて書きます。

読むためのコツ

0. サービスのコア機能を確認する

これは作業に当たる前に絶対にやるべき作業です。あなたが今回担当するサービスのコア機能については実際に使ってみることです。ここで言うコア機能とはそれがなくなったらそもそもサービスとして提供出来ない機能のことです。
大体のサービスは幹となるコア機能と補完する機能群であるためコア機能さえつかめれば一気に全体の把握が楽になります。問題はコア機能はロジックが複雑なためコードを理解するのが大変なことです。最悪、直接触らないのであれば概要が分かっていれば大丈夫です。
さらに言うとこのサービスは誰にどのような価値を届けるのかを意識しておくことです。登場人物や価値を理解していると読むスピードが大幅に違ってきます。

1. 現在の動きを確認する

今回改修する箇所の動きを確認しましょう。その際におすすめなのは現在どのようにデータが変わるのかこの時点で理解しておくことです。
また、新規機能追加の場合ではどのような流れで新規機能が使われるのかを意識しておきます。

2. 用語を確認する

プログラムでは特定の機能について特定の単語で表していますのでしっかり意味を確認しておきましょう。特にあなたが新人であるならば積極的に発言して確認することです。
しかし、特定の単語が別の意味で使われていたり、特定の機能が複数の単語で使われていたりするケースは注意が必要です。こういう場合は予めバグが紛れそうだなと考えて注意しておきます。

3. ライブラリのドキュメントを確認する

今どきのサービスでFrameworkやライブラリを一切使っていない現場は少ないでしょう。もしあなたがそのFrameworkやライブラリについて使用するのが初めてであるならばしっかりと公式ドキュメントを読んでおきましょう。勘所としてはこのライブラリが何を解決するのかと哲学も理解しておきましょう。ここを意識していないと間違った使い方をするため技術負債を増やします。

4. コードジャンプ機能を使う

これは賛否が分かれるところですが、コードを追っていくならコードジャンプ機能はあった方が楽です。私はIntelliJ IDEAの有料版を使っています。
その他にもMacであればDashというAPI Document Browserと連携させてさらに効率化させています。

Dash for macOS - API Documentation Browser, Snippet Manager - Kapeli

5. 設計について理解する

レイヤードアーキテクチャ、Clean Architectureなど全体の設計に関わるものから、Design Patternを通したクラス関係については理解しておくと読みやすいです。この辺がキレイに作られているサービスは必要な読む箇所と影響範囲も分かるので理解が早くなります。ただ、現実問題としてここがしっかりとキレイに作られているケースは何だかんだ稀です。。

6. 頭を整理する

コードをずっと読んでいると頭がこんがらがってくることもあります。その結果何度も同じコードを読んでしまいループします。
そこでおすすめなのが途中でメモを書いたり図に起こしてしまうことです。特にオススメなのが図です。下手な図でいいのでコードや仕様の関係性を書いてみると案外スッキリします。私はよくホワイトボードにシーケンス図やベン図を書いて理解しています。

まとめ

上記の中で個人的に一番重要なのは「0. サービスのコア機能を確認する」です。コードの読むのが遅い人はそもそもサービスの理解が深くないケースが多いです。全体像を把握していないのに詳細なソースコードを読んでも中々頭に入ってこないです。
全体像を理解した上でコードが実際にそうなっているのか確認してみると理解しやすいです。そうやって考えるとこの記事の一番上にあった「あなたはどのファイルから開きますか?」という質問に対しては、まずいきなりファイルを開かないが正解になります。
昨今、入社試験などでアルゴリズムの問題を出すことが多いですが、個人的にはプログラムの読解をさせた方が実務の能力を図るのに適していると考えてます。読解させた上で仕様を読み取れるのか、設計が良いのか悪いのか議論した方が試験内容としては面白いと感じます。

企業勤めでは評価と年収に相関性はそこまでないんじゃないかな

cassetteの延澤です! 以下の記事を読んで少し引っ掛かることがあったので記事を書きます。 logmi.jp

簡単な要約

技術力ばかり上げていたら、相手から求めていることとの乖離が起きて評価が上がらないよというお話。後半の時間と目標については前半の話とあんまり関係ないのでここでは無視します。

評価と年収に相関性はそこまでない

9割同意する内容なんだけど、年収1000万円との関連性があまりよくわからなかった。相手の評価が良かったからといって年収が上がるということは考えづらい。例えば、平均年収500万円ぐらいの企業で働いていた場合いくら優秀でも年収1000万円に手が届くのは難しいじゃないのかな。この人は評価と能力が良ければ年収も上がると考えているけど、自分は個人の能力よりも以下の三点で年収は決まると思う。

  1. 業界年収
  2. 企業業績
  3. 企業文化

1. 業界年収

業界の平均年収というのは大体決まっていて大きくそれることはない。何故かと言うと業界首位の会社が粗利で業界2位の会社に倍の差をつけていたとしても社員の平均年収に2倍の差があることは聞いたことがない。これって談合なんじゃないのかと個人的には考えている。

2. 企業業績

どんなに優秀で救世主な人材であっても会社の業績が悪ければ年収は伸びない。まあ金がないからしょうがいないよね。シリコンバレーではそもそも投資金額が桁外れに多いから企業業績関係無しに給料が払われる。すごい文化だな。

3. 企業文化

よくあるのが企業の文化として特定の部署が強いということ。例えば、Googleではエンジニアが部門が強いためエンジニアとしては働きやすいし年収も高い。自分はかつて働いていた部門の幹部がウチの部門はコストセンターだって言っていて萎えたことはある。謙遜するのもいいけどWeb企業の開発がコストセンターだって言い切られると流石に苦笑した。
なので会社の認識としてこの部署は利益を生み出していると考えているかどうかで大きく変わる。

年収とは

何を言いたいのかというと個人の能力や成果なんて上記の3つの要素に比べれば鼻くそみたいなものだ。そういう不安定な要素で年収なんて決まるのだから自分がやりたいことをしてお金を稼いだ方がいい。他人の評価ばかりを気にして成果を上げる人生って楽しいのかな。

まとめ

自分は上記の不安定な要素を嫌ってフリーランスになったのも一つの理由だ。能力と稼ぎは直結するし例え駄目でも納得感はある。
他に能力的なことを言うと関数型言語最高と普段言っている自分が言うのもあれだがプロジェクト管理の経験はやって損はないと思う。視野が広くなるし管理者が自分に何を求めているのかも分かる。自分が関わるプロジェクト失敗の確率がかなり減るのでオススメです。

ReactとVue.jsを状態管理から見た選び方

今回はReactとVue.jsのどちらを選定するかについて状態管理という観点で書いていこうと考えてます。

結論

いきなり結論ですがReactは関数型視点でコンポーネントを設計していく。Vue.jsはオブジェクト指向視点でコンポーネントを設計していく。
以上終わり。

と、さすがにこれだけだと何のこっちゃという話なので整理していきたいと思います。

そもそもJavaScritptとは

JavaScriptは言語の中でもかなり特殊な言語です。具体的に言うと関数型っぽくも書けるしオブジェクト指向っぽくも書ける言語です。結果的にプログラミングスタイルが定まっていないため一部混乱をきたしています。そういうある意味カオスなところがこの言語の持ち味です。ただ、その影響もあってライブラリの設計思想にも影響が出ています。

ReactとVuejsのコンポーネントの設計方針

Reactはコンポーネントに状態を持たせないステートレスなコンポーネントの設計を推奨しています。つまり、stateを使わずにpropsを使え。コンポーネントにライフサイクルを持たすなと推奨しています。stateやライフサイクルはコンポーネントに副作用をもたらすためです。
Vuejsはコンポーネントにステートレスな状態を持たせることが推奨していません。別に否定もしてませんが。ただ、現実問題としてVue.jsのコンポーネントにステートレス状態にさせることにそこまでメリットをやはり感じません。

コンポーネントの状態について

結局、コンポーネントにおいては状態をどう扱うかが肝になってきます。逆に状態を持たないアプリケーションであれば無理してコンポーネント化しなくてもいいのではないかと個人的に考えてます。
そのため、ReduxやVuexのなどの状態を管理するライブラリを使用することとセットで考える必要があります。

ReduxとVuex

ReduxはReactのstateの状態を持たせないステートレスなコンポーネントを強制することができます。ReduxはElmという関数型言語から影響を受けているためこのような作りになっています。つまりReduxの冗長な書き方は関数型から影響を受けていると考えればある意味納得できます。私も初めて触った時は処理が分散していてなんとも見通しが悪いなと感じました。しかし、処理が固まっていて欲しいと考えるのはオブジェクト指向カプセル化の考えが染み付いているためだと後になって気づきました。 その反面、Vuexについてはスッと学習コストもなく覚えることが出来ました。同期処理ならここ、非同期処理ならここというようにVuejsの延長線上で考えれます。恐らくオブジェクト指向のままで考えると便利なライブラリです。

ReactとVuejsの選定基準

1. 関数型とオブジェクト指向での基準

開発者がオブジェクト指向型言語出身のメンバーであればVue.jsを使った方がすんなり開発できます。例えば、Ruby on Railsをよく使用しているエンジニアが参加するのであればこちらをオススメします。特に開発メンバーのJavaScriptのスキルがそこまで高くないのであればこちらの方がリスクが低いです。 逆に中心的なフロントエンドエンジニアがプロジェクトに存在するのであればReactがいいでしょう。

2. 大規模サービスかどうか

Vue.jsは状態を持ってしまうので、Reactと比較すれば大規模なサービスでが苦しくなってきます。ちゃんと設計すれば問題ないという指摘もありますが、バックエンドに比べて変更が多いフロントではアーキテクチャで固めた方が保守しやすいです。

3. 設計の難易度

Reduxのフレームワークは非同期処理以外はどこにロジックを記述すればいいか明確です。デメリットとしてはよく言われているようにボイラーテンプレートが多くなります。
反対にVuexは処理をどこに持たすのか自由なため設計次第ということになります。そのため、初期の学習コストは低めですが保守コストはVue.jsの方が高いです。

私はどちらを使うことにしたのか

私はサーバサイドを関数型のElixirを使っているのでReactを使うことにしました。スタートダッシュではVue.jsの方がメリットが高いので迷ったのですが思想は共通していた方が後々良いと判断しました。後は、別の仕事でも使用していたので学習コストはゼロだったのも理由です。

PhoenixでpryをDockerと併用して使う

久しぶりに普通の技術ネタを一つ。
今、ElixirのPhoenixを使って開発をしています。PhoenixRuby on Railsの弟分みたいな存在でRailsを使用したことある人なら学習コストが低めで開発出来ると思います。
そこでpryをdockerと併用して使う方法の説明になります。

Docker 起動

$ docker-compose run --service-ports app sh

説明するとappはPhoenixが起動しているコンテナでshコマンドでログインしています。肝となるのが--service-portsオプションでこれがないとHostのポートとマッピンが出来ません。portの設定はdocker-compose.ymlで設定してください。

Phoenix起動

$ iex -S mix phx.server

mix.exsファイルがあるディレクトリで以上のコマンドを実行することでREPLになります。 あとは、breakしたい箇所で以下のコードを実行します。

require IEx
IEx.pry()

あとは、Allow? [Yn]みたにpryに接続していいか聞かれるのでyを入力すれば止まります。

コマンドのリファレンス

IEx.Helpers

6年間SEO対策に携わってみて

タイトルは釣りだ。流石に6年間ずっとSEOをやってきたわけではない。しかし、SEOについてエンジニア側から発信の情報は少なかった。その中で私がSEO対策をしていて気づいた原則を今回書いていきたい。

SEOは最適化であって上位にあげる手段ではない

SEOの本来の目的はGoogleの検索ボットに正しくインデックスするために情報を整理することである。ただ、企業が行うSEO対策の目的は検索順位を上げることである。いきなり本題であるがこれは全く似て非なるものであって本来のサービスの実力以上に検索順位が上がることはない。勿論、例外はあるだろう。そのパターンは競合サービスがペナルティを受けていたり相当SEOに対して手を抜いているのでたまたま検索上位にいるだけであって持続性はない。とにかく弱小サービスが業界上位のサービスに対してSEOで勝つことは基本的に不可能である。。 これはユーザー視点から考えてみれば当然である。例えば賃貸物件を検索する時に大手サービスではなくローカルな不動産屋が検索順位を独占しているのと一緒だ。ただ、当事者で作業している時にはこの視点がすっぽり抜けていたり、企画の段階でそもそも論を言い出しにくい雰囲気はある。

裏ワザはない

SEO対策をやっていると実は何か裏ワザや革新的な手段があるのではないのかと考えることがある。確かにひょっとしたら裏ワザは”あるかも”しれない。この”あるかも”というのが厄介で断言できないことが多くの悲劇を生み出している。 結局、Googleの社員でもないのでその裏ワザを見つけ出すのは宝くじに当たるようなものであり再現性は低い。

小技はあんまり効かなかった

SEO対策と言っても内部構造を大きく変えることやページのタイトルの修正も含めて大小様々な施策がある。しかし、大体は出来る小さな施策から手を打っていくことが多い。ただ、小さな施策は効果検証がしにくいし効果もあまり出なかった。要するに安物買いの銭失いという状態である。結局多少効果もあるだろうが多少なため費用対効果が薄かった。

じゃあ、効果あることは何だ

エンジニアたるもの公式ドキュメントを見よう。その中の対策はまず一通り行う。ただ、公式ドキュメントの内容を実施したとしても競合サイトとは差別化しにくい。。いや本当だろうか? 「質の高いコンテンツを提供しよう」というところだ。要するに動的に自動生成したようなページではなく独自性のあるコンテンツを提供しようということだ。ユーザー視点から見れば本当にそうで、自分だって動的に自動生成したようなページを見ることはない。結局、お金をかけて地道にページに付加価値をつけることが近道である。そういう当たり前の面倒くささを回避してアイディアや知恵で乗り越えようとするからおかしな話になってくる。だから、SEOというのはお金がある企業がやるような対策であって小さい企業が真剣にやるようなことではない。

余談

SEO施策は何度もやっているが退屈な仕事であるし、殆どのエンジニアの偽らざる本音だろう。だからこそやるならしっかりとキーワード選定も含めた戦略を立てて実行したい。ここには書いていないことは少しはあるがそこは内緒ということで〜

現実的なオブジェクト指向でツラいところ

cassetteの延澤です。
最近、Elixirにハマっている。モダンな言語らしく痒いところに手が届く良い言語だなと感じる。個人としては今まで色々な言語で書いてきて得意な言語はあるけど、好きな言語というのはなかったので良かった。関数型だがモナドを用いないやり方で副作用に対してアプローチしていくというのはすごく面白かった。で、興奮冷めないうちにオブジェクト指向と関数型について比較した内容を書く。Elixirについては書かないw

オブジェクト指向で書くということ

オブジェクト指向で書くことの問題の一つとして状態を持つことが挙げられる。例えば、Aというオブジェクトのaメソッドの中でB, Cのオブジェクトのメソッドが呼ばれていた。A, B, Cというオブジェクトはそれぞれ3つの状態があったとする。すると、aメソッドをUnitテストする場合、3 × 3 × 3の状態の組み合わせになり27パターンのテストをしなければいけなくなる。実際には27パターンの中でもあり得ない組み合わせなどがありもっと少ないが、その見極めをしなければいけない。いや、mockやstubを使えばもっと効率的に出来るという指摘もあるがそれを使うかどうかはまた別の話だ。

状態を上手く管理したいのであれば疎結合に作りカプセル化することである。その上でテストしやすくすることが求められるだろう。その実現としてDIコンテナ・デザインパターンも使用して高いレベルのクラス設計することが重要になっている。事実、オブジェクト指向を前提とした設計を扱う書籍はかなり多い。

オブジェクト指向で書く現実問題

私が考える問題は以下である。

  1. 状態の準備
  2. クラス設計の高いレベル
  3. Web業界の事情

状態の準備

Unitテストを実行する前に多大な準備が必要なケースが多い。上記で書いたようにオブジェクトの状態が特定の状態でないと正しく動かないケース。小さいアプリケーションではそこまで問題ではないが複雑で規模の大きいアプリケーションになると大きな負担となってくる。また、膨大に準備することはテスト実行時間にも影響が出て来る。

クラス設計の高いレベル

状態の準備が大きく必要だが疎結合で作られていないことが多い。そのため、適切な設計をすることが重要になってくる。私も過去に概念分析・UML作成・クラス設計をしてきちんとやった経験もある。そこで感じたのはやっぱり辛いなということだ。そもそも概念分析の必要性やクラス設計の意図を伝えることが大変だった。前提知識が違うため何でそういう意図の設計なのかを伝えるのに時間がかかる。メンバーからすればそこまで複雑な設計にしないといけないのという疑問もあった。また関連する資料も作成したりするのでコストも高かった。正直、設計についてはそこまで辛くないが人に正しく伝えるというところが何だかんだ一番大変。

Web業界の事情

Webのサービスのシステムに本当に高いレベルの設計が必要かどうかが分からない。 それによってどういう影響があるかというと、Webでは設計期間をあまり取らずプログラミング主体なことが多い。設計が弱いため時間が立つと技術負債に陥りやすい。何が言いたいかと言うとオブジェクト指向で複雑な要件をシステムに落とし込むには高度な設計が必要なのに現実は出来ていない。
そのため、3〜4年経ったスタートアップでは技術負債により開発スピードが途端に落ちるケースが多い(この技術負債をどう返したかという記事はよく見かける)。現実問題としてはシステムを一からリライトは難しいのでマイクロサービス化に取り組むことが多い。。

関数型のメリット

上記のことを全て解決してくれる銀の弾丸ではないが関数型を用いることによって参照透過性は得ることが出来る。まあ検索すれば沢山オブジェクト指向と比較した記事があるのでわざわざ言及はしない。主張したいことは設計のテクニックで複雑性を解決するのではなく、言語の機能で解決する方がスマートではないのかということ。

で?関数型言語は普及するの?

しないと思う。明らかに現金よりキャッシュレスでのお会計の方がメリットあるのに中々普及しないのと同じ理由である。ライブラリが少ないなどの問題もあるかもしれないが、人々の意識の方がより根深い問題だと思う。それに、関数型を使える経済的メリットが少ない。関数型言語を使えることで大幅に年収がアップするなら勉強する人も多くなるがそういうわけでもないし全ての問題を解決してくれるわけでもない。

それでも普及させるには

社会全体に普及させるのは困難である。しかし、技術選定として関数型言語オンリーにするアプローチがある。よくサービスによってオブジェクト指向の言語と関数型言語のアプリケーションが混在していることがある。しかしこれだとリソースの効率性から人員をオブジェクト指向と関数型で分業してしまうことがある。大企業であれば別だがスタートアップでは分業はデメリットが大きい。しかも、採用面でも募集がやりにくい。
だから、システム要件に合わせるのではなく本当にやりたいのであれば関数型言語に統一した方が良い。私はサービスが成功するかどうかは技術アーキテクチャと関係ないと感じる。成功するサービスはPHPだろうがJavaだろうが成功する。つまり、Scalaを使おうがElixirを使おうが成功するサービスは成功する。 RubyPHPなどは扱える人が多く募集しやすいが、反面転職されやすい言語とも言える。そう考えると関数型にオンリーとするのはそこまで悪い選択肢ではない。

2017年度の振り返りと2018年度に向けて

総括

前職を退社して今月でちょうど1年になるので今年度の振り返りと来年度の目標を書く。 結果で言えば技術は大きく飛躍した。しかし、本来自分がやろうと考えていたことに関しては色々と見直さなければならない。来年度も今年度の延長線上で進めていくのは何とも面白くないので見直すところは沢山ある。

技術が大きく飛躍した

まず、技術について。前職ではとにかく技術負債との戦いがメインだった。今あるシステムを安全に運用して新しいものに作り変えていくことが主。そのためマネジメントや設計について深く勉強することが多かった。簡単に言えば技術で物事を解決していくのではなく、人やプロセスで解決することが多かった。
しかし、今年度は言語で言えばRubyPythonJavaScriptを主に使用することが多かった(前年はPHPオンリーでしかも5.2を使っていた…)。特にJavaScriptは後半になってからよく書く機会が増えいった。そのおかげでクライアントサイド全般についてかなり詳しくなれたのは大きな収穫だった。また、JavaScript関数型言語に分類されないが、関数型っぽく書くことが出来るため関数型の書き方について何年か越しでついて大きく理解することが出来た。
インフラ面においてもDockerを使用する環境が多かったので便利さを大いに実感した。今後環境構築においてはDockerを利用して構築することにする。なんだか前職をディスってしまう書き方だがマネジメントの経験をして本当に良かったと実感はしている(スタートアップでは中々経験出来ないので個人的にマネジメントは自分の強みとなっている)

ビジネスにはいまいちだった

これは本当に反省。やっぱり思い通りにならなかった。
別に諦めてしまった訳ではないがテスト管理ツールの作成があと一歩のところでずっと足踏みしている。反省としては以下。

  • 1カ月で作れる規模にすれば良かった
  • SPAを多用したこと
  • 外部要因として利用するシーンと接しなくなったこと

まず1カ月で作れる規模にすればよかったのは本当に同意でモチベーションの管理が難しくなった。一応機能を削ったMVPを設定して作ったのだがもっとバッファを持たせれば良かった。またSPAを多用したことによって単純に作業量が倍になった。
特にサーバサイドは初挑戦のPythonDjangoの組み合わせでフロントはVue.jsを使った。思いのほかDjangoの学習量もキツかった上にゼロからモダンなJavaScriptの環境で作業したので大きく時間がかかった。(ただ、このおかげでフロント技術について一気に詳しくなったので経験には繋がったが…)
トドメはスタートアップで仕事しているとテスト管理ツールを使うイメージがあまり湧かなかった。。前回記事を書いたようにしっかりテストをするというよりも、テストコードを書いて重要なフローを検査すれば大きな問題にはならなかった。
反対に成功した面としては企画や仕様の検討、マークアップは事前にやっておくことで開発に集中することを実感したのでこれは上手くいったと感じている。

今年度の目標

去年はフリーランスの常駐の仕事がメインだったので常駐以外の分野に進出したい。今の現場は本当に恵まれていて楽しいが将来への投資も必要だと感じている。特に今まではWebメインの開発が主だったので幅を広げたいと考えている。
戦略としてはニッチなスキルに投資をするのではなく、大きく需要のあるスキルの掛け合わせで価値を高めていきたい。

ブロックチェーン分野に携わる

今年はブロックチェーンについての仕事が出来たらと考えている。今年やりたいことの優先順位の中では一番高い。何故やるのかは詳細にここでは書かないが要するに風上に乗る戦略。今後、どういうサービスが流行るのかは残念ながら自分はあんまり分からない。しかし、ブロックチェーンの基礎を知っていれば自分の方向性が見えた時に舵を切りやすい。

クライアントの分野に引き続きやる

今年はフロントでReact, Vue.jsに携わることが出来たので来年度も仕事で携わりスキルとして固めたいと考えている。本当はiOSAndroidのどちらかやりたいのだがブロックチェーン分野を優先してやりたいのでリソースとしてキツい。。(誰か仕様を考えてくれればやってもいいのだが…)
ただ、アプリは現状需要が大きいが同時に経験年数による参入障壁も高い。上手くいけば安定した仕事には繋がりやすいので投資はしたい。