2019年12月19日木曜日

今更ながら達人プログラマーを読んだので感想

今更ながら達人プログラマーを読んだので所感を備忘録として残しておきます
読んだのは翻訳版です


はじめに

本書内ではいくつのサンプルコードが出てくるが主に C++ や Java になっている
具体的なコーディング方法などが紹介される場面もある
そういった場面では基本的に C++ や Java がベースになっているので自身で使われている言語のニュアンスと少し食い違うケースがあるかもしれない
Perl や Ruby などの高級言語もちらほらでてくるがメイン言語としては使われておらずコードジェネレートの際のパーサスクリプトなどに使われいる

また本書はある程度プログラミングの知識と経験のある人向けかなと感じた
タイトルに「今更」とつけているが今更と思うくらい後に読んでも全然大丈夫だと思う

本書内で出てくるワードがわからない場合は検索しながら読み進めると良い

特に重要だと感じたフレーズ

  • 二重化しないためのコードジェネレート
  • コード、モジュール同士の結合度を最小に抑える

印象に残った言葉、フレーズ

  • プラグマティズム、実践的な
  • 十分に幅広いバックグラウンドと経験が基盤にあってこそ、特定の状況に応じた優れた解決策を選択できる
  • 達人プログラマーの性格「新しい物好き」「研究好き」「批判的」「現実的」「何でも屋」
  • 弁解の代わりに対策を提案
  • good enough でいい、やりすぎない、やめ時を知る
  • 自分の知識に対して定期的に投資しなければならない
  • DRY (Don’t Repeat Yourself)、二重化、重複は NG
  • 片方を変更しても他方に影響を与えない場合、それらを直交していると呼ぶ
  • 曳光弾を打つ -> 常に目標やゴールを見据えながら開発する、プロトタイピングではない
  • プロトタイプの真の目的は学びにある
  • OS やデータベースのバグは少ない、まずは自分たちのアプリを疑う
  • 完璧なソフトウェアは存在しないし作れない
  • DbC (Design by Contract) 契約プログラミング、契約に従わない実装を防ぐことができる、呼び出し元/先の責任分界
  • コードの修正時、どういった影響があるのか分からないという理由で、開発者達が及び腰になってしまう
  • 偶発的プログラミング、おそらくそうであろうという環境やコンテキストを想定して開発してしまうこと
  • 要求は掘り起こすもの
  • あなたが作った 200 ページにも及ぶドキュメントを承認しているかもしれない、しかしいったん実際に稼働しているシステムを見た途端、星の数ほどの変更を要求してくる
  • テストのカバレッジを 100% にすること自体を目的にしてはいけない
  • 状態のカバレッジをテストすること

これらを踏まえて疑問に思った点や自分なりに考えた点は以下の通り

疑問点、所感

割れた窓理論について

細かいことを気にしすぎると返ってコストの問題などで大変なことになりそう
だったら 1 から作り直すなど大きな枠で変革するほうが良いのではないのかと思った
腐敗の加速のほうが速いことも可能性としてあると思う (それ以上に速く沈下できるようになれというメッセージなのかもしれないが)

あとは単純に割れた窓に気づくことができないケースがありそう

考え方はプログラマ以外にも通ずるところがあると思う

「自分の知識に投資しよう」とか「情報を伝達しよう」といった考え方はプログラマ以外にも通ずるかなと感じた
ただ伝達する際に「WISDOM を考えよう」とか「質問をするタイミングを考えよう」という教えがあったが、質問するためにそこまで考えなければいけないのであれば自分で調べたほうが早そうな気がした
そして伝達に e-mail をオススメしている感があったのでそれも、うーん、、という感じだった
たぶん重要なのは証跡を残そうということだと理解した

二重化を防ぐためのコードジェネレータ

例えばヘッダファイルを自動で生成したりクラスファイルをデータベースの構造から自動で生成するようにしようという感じ
最近だとフレームワークが頑張ってくれるケースのあるので導入は簡単な気がする
ただコードジェネレータにバグがあるという可能性を考えるとあまり頼りすぎるのも良くない気がした
この辺りは「邪悪な魔法使い」の部分でも言及されていた
要するに中身がよくわかっていないコードジェネレータは中身を理解するまでは使うなということ
また本書内ではいろいろなケースのコードジェネレータが出てくるがそれらの二重化はどうやって防いでいるのか気になった

ドキュメントドリブンに開発する際にドキュメントが変更されるとテストも必ず変更する必要があるからドキュメントを変更するとテストも自動で変更される仕組みを作るというアプローチは良いアプローチだと思った

あと二重化している箇所に気づくのは結局人によるレビューしかないのかなと思った
そういうツールも現代だとあるのだろうか
このあとで紹介してる「直行性」に関しても同じようにどう気づくのかがポイントかなと思った

というか完全に二重化していない直行しているシステムなんて作れるのだろうか
しかもそれを開発の初期段階から意識してできるのだろうか (できるようになれば達人ということだと思うが)
またコードジェネレートに関しては本書内で至るところに出てきた印象があり筆者としてもかなり推したい手法なんだと感じた (Perl)

具体的なアプローチに落とし込めるか

前述の二重化や直行性を解決するのにコードジェネレータを使ったり AOP のアプローチを使おうという紹介はある
それらを読んで実際のプロダクトに適用する際に具体的なアプローチにまで落とし込めるかがポイントかなと思った
愚直にコードジェネレータや AOP のアプローチを適用しても良いがたぶん大変なことになるので自分たちのプロダクトにあった同じようなアプローチを選択できるのかがポイントかなと思った

例えばコードジェネレータは swagger を使ったり AOP のアプローチは DI (Dependency Injection) ならできそうだなーといった具合に具体的なアプローチを自身で見つけられるかが重要かなと感じた

プロトタイピングのコードは絶対に使い捨てでなければならないのか

個人的にはプロトタイピングで使った言語やフレームワークレベルでは流用して良いと思っている
データモデルや UI の部分も全く同じなのであれば使って良い気がする
むしろ使わないと二重化のルールに抵触しそうな気がする
もしかするとプロトタイピングに関しては二重化や直行性は無視して作れということなのかもしれない
だから使い捨てなのだと

そもそもプロトタイピング=コーディングすることだと思っているのが間違いなのだと思うが

道具の使い分け

IDE だけではなくてシェルも使うと便利だよという話
頭ごなしに IDE を否定しているわけではないが IDE だけだと不便なこともある
自分も Swift を書く場合は Xcode を必ず使っているがファイルを検索するときやリポジトリに push するときはターミナルアプリを使っている
また Ruby を書くときは emacs + tmux でターミナルウィンドウ内を行ったり来たりしてコーディング、ビルドを繰り返している
要するに達人なのであれば適材適所、状況にあった最適なツールを選択すべしということなんだと思う

ただ一つ腑に落ちなかったのはエディタの拡張性の話で確かにキーバインドや face などは拡張できたほうが操作性はあがるのだけれども、その拡張がされていないと操作できなくなるリスクが伴う
なのでできる限りデフォルトの設定に慣れておきどうしてもという部分だけを拡張するようにしたほうが個人的には良いと思う

本書が emacs 推しなのはよかった

テストに関して

本書内では具体的なテストの手法などについては書かれていない
代わりに「テストがしやすいコーディングの方法」や「バグとの向きたい方」などが書かれている

テストもバグ取りの一種だと自分は理解し結局の目的は「問題を修復すること」にある

個人的にテストに関しては DHH の「TDD is dead. Long live testing」の考えが好きでシステムテストに重点を置くようにしている (参考)
本書ではユニットテストについて具体的に触れているところはないが目的である「問題を修復すること」は同じだと思う

またテストのコストやテストにおける二重化や直行性についても特に触れられてはいなかった
テストケースやデータを自動生成しようという話はあった
個人的な意見だが TDD まで厳密にとは言わないがコーディングしたらそれと同時に最低限のテストを書いておいたほうが安定したコードになる気がする
本書内でもコーディングの終了=テストの終了という表現が使われていた

デメテルの法則

厳密に守ることができるのだろうか
またそれに気づく方法が経験しかなさそう
参考

すべてのコンテキストを網羅することはできるのか

本書内で「コンテキストの事故」というトピックで紹介されていた
「GUI ではなく CUI も想定しているか」「英語以外の言語に対応できているか」「ユニバーサルデザインに対応しているか」などが紹介されていた
おそらく洗い出したらきりがないとと思う
開発中のアプリケーションに対してすべてのコンテキストを洗い出して対応することはできるのだろうか
またそれらは本当にユーザが求めているのかの判断も難しい気がする

想定していないコンテキストがあるとそれが偶発的プログラミングの元になりバグを生み出す可能性になるのはわかるがすべてを網羅するのは難しいと感じた
またすべての内容を理解しながらコーディングを進めるのも必要ではあるが難しいケースもあるかなと感じた

リファクタリング、最適化

二重化/直行性やの結合度を最小化は当然としてアルゴリズムのオーダーの見直しやリソース/コストの見積もりと削減なども重要だなと感じた
プロファイリングなどを使ってコーディングの段階から意識したほうが良さそう

リファクタリングの前に必ずテストが用意されているという点も重要だと思う
意外とテストとリファクタリングを同時に行ってしまうケースはあると思う

リファクタリング時のミスをなくすという意味でやはり IDE は便利だと感じた

精神論

途中「本能に任せる」とか「経験から考える」「準備できるまで様子を見てみる」といったフレーズが出てくる
こういったのは経験からしか判断できないことが多いのでまずは考えないでもいいのかもしれない

別の箇所で「形式方法論」というツールなどを使ったアプローチを紹介している
デメリットもあるがそちらのほうがスタートは切りやすいと思う

チームの機能的分担

分析、設計、コーディング、テストという単位ではなくシステムの機能単位でコントロールするほうが良い
そのほうが全員がシステム全体を把握することができる
無理に機能単位でコントロール必要はないと思うがメンバー全員が分析、設計、コーディング、テストなどすべてを網羅的に把握しているほうが良いと思う

ビルフローなどの自動化についても触れられているが最近だとアプリケーション開発においてはデファクトで導入されているケースもあると思う (Github Actions や Circle CI など)

その他、あまりピンとこなかった話

  • ミニ言語
  • 見積もり
  • プレーンテキスト
  • 表明プログラミング
  • リソースの開放
  • ホワイトボードシステム (kvs 的なことだろうか、タプル空間)

最後に

本書を読んで自分なりに判断した「達人プログラマー」とは
幅広い知識と豊富な経験から算出される最適な答えと手法を導き出せる人 かなと思う

あと付録C のクイックリファレンスガイドがかなり役に立つので見返す時にオススメ

0 件のコメント:

コメントを投稿