プログラマが知るべき97

最終更新日

データサイエンティストとか、エンジニアの条件って何なのか、考えながら少しずつ読んでいます。そのまとめになります。

エンジニアの要件て何でしょう?

大学で情報系の勉強をしていなければ技術者になれないとか、そんなこともないと思います。今の自分に何が求められているのか、キャッチアップするべきことを明確にしていきたいです。

※新卒1年目の時の記事です。

Contents-list

1. 分別のある行動:自分の行動の結果をよく考える。

→技術的負債はできるだけ早く返済する。

技術的負債(Technical debt)→故意の技術的負債・不注意から発生する技術的負債

〇故意の技術的負債の存在は常に忘れないようにし、できるだけ早く返済すべき

→タスクカードに書く・問題管理システムへの登録をする

✧WBSとか課題管理票を作成し対応

2. 関数型プログラミングを学ぶことの重要性

◯自分の書くコードの品質を高めることができる

参照透過性(Referential transparency)が高い≒入力が同じなら、常に得られる結果が同じになる→可変な変数による不具合への対策(小さな関数を多く作り、個々の役割を限定する)

〇オブジェクト指向システムも参照透過性を高めれば利益は大きい

✧意識はできている

3. ユーザが何をするかを観察する(あなたはユーザではない)

→頭で考えて1日過ごすより、わずか1時間でも観察したほうが得るものは多い

偽の合意効果:物の見方の誤った思い込み(ex. プログラマとユーザ)

→割り込み・手助けをせず、観察する

〇ユーザは基本的に大体同じようなことをする
〇ユーザが求めていることを知るには言葉を聞くよりも、行動を観察するほうがいい

✧ダッシュボードづくりのときに意識できるかも

4. コーディング規約を自動化する

コードを私物化しない→コーディング規約は可能な限り自動的かつ強制的に守られるようにする

〇コードの整形処理をビルドプロセスに含める
〇静的なコード解析ツールを使用する
〇ツールの設定により固有のアンチパターンも見つけ出せるようにする
〇テストの計測結果判定も自動的に行われるようにする

→ガイドラインの設定が重要

✧PEP8に沿って整形するblackを導入検討(納品物を最後に整形して渡す)

5. 美はシンプルさに宿る(美しいコードとは、突き詰めればシンプルなコード)

→開発速度を落とさずに長時間にわたる保守が可能になる

プラトン

〇プログラマがコードを書くときに留意すべきこと

→可読性・保守性・開発効率・(言葉で表現するのが難しい)美しさ

→「メソッドのコードは5-10行くらいの長さにすべき」

6. リファクタリングの際に注意すべきこと

→開発に関わる全ての人の時間と労力を大幅に節約できる

〇リファクタリングにあたり最初に既存のコードベースと、そのコードに対して書かれたテストコードの洗い直しです
〇ゼロから書き直さない
〇一度に大幅な変更を加えるより、少しずつの変更(インクリメンタルな変更)を数多くするべき
〇各イテレーションの最後には、既存のテストが通るか必ず確認する
〇個人の好みやエゴを入れない
〇新技術を使いたいというのもそれだけではリファクタリングの十分な理由にはならない
〇人間は必ずミスをする、ということを忘れない

✧できていない。リファクタリングの時間をとるべき

7. 共有は慎重に:「コンテキストが重要」

コンテキスト:文章などの前後の脈絡。文脈。

◯再利用はコンテキスト次第

ex. コードの再利用を検討し、ライブラリ化すると依存関係が生じた。コンテキスト(役割の違い)によってむしろ、保守コストが増えて大変な手間になった。

→コンテキストが不適切だとメリットよりもコストのほうが大きくなる。安易にコードの共有をススメるべきではない

✧やたらに関数化するのもいいけど処理の目的が異なる場合には検討する

8. ボーイスカウト・ルール:来た時よりも(少しでも)美しく。皆のためになるから

→「モジュールをチェックインする際には、必ずチェックアウト時よりも美しくする」

〇他人が書いたコードを改善しようと思えば、まったく違った配慮が必要になる

→チームメンバーが助け合い、そして互いのコードをきれいにする。

9. 他人よりまず自分を疑う

→なんやかんや自分のコードが原因なことがほとんど

〇どこがエラーなのか→

完全にありえないことをすべて除くと、事実が残る

10. ツールの選択は慎重に

→既存のツールを適切に組み合わせる

〇組み合わせのメリット
→バグが少ない・無料で入手可能・ゼロから作るより安い

〇組み合わせの課題
→ツールごとに前提条件が異なる・ライフサイクルが異なる・過度な依存による制約・フリーソフトだからと言って無料ではない・ライセンス

〇「まずは最低限のツールだけを導入する」

11. ドメインの言葉を使ったコード→何が書いてあるのかすぐに理解できるように

〇業界特有の表現に配慮した命名法を
→金融やweb業界などでは「トレーダー」, 「ポートフォリオ」などの特定の表現が存在する

〇プログラムに「暗黙の了解」はいらない
→コードの表現する概念はできるだけ一目でわかるようにする

12. コードは設計である→優れた設計には優れた設計のできる「人間」が要る

〇技術発展によって建設や医療の現場ではロボットによるコストダウンが進む
→設計の速さは市場原理から求められ続けるのでコストの低下により品質が低下する

〇ソフトウェア業界では遷移の速さに設計が追い付いていない
→「自動テスト」で耐えうるものであると証明するべき

13. コードレイアウトの重要性

〇目立たない部分を作る
→コード中の繰り返し部分はパターン化して「背景」としてしまう

〇レイアウトに語らせる
→機能の説明は名前だけでなくレイアウトも。改行やインテンド、グルーピングは何らかの意図を表す必要がある。→「フォーマッタ」をつかう(手でやらない)

〇コンパクトにまとめる
→画面に1度に表示できるものが多くなれば、スクロール量やファイルの切り替えが少なくなる。できるだけ多くの要素を一度に見渡せるように。

14. コードレビュー→コードの質を上げ、欠損を減らす

〇チーム全員に同じ知識を共有させること、また、コーディングにおいて全員が守るべきガイドラインを確立すること
〇レビューは建設的であるように心がけ、辛辣な批判は絶対に避ける(レビューは楽しいものにする)

15. コードの論理的検証→自分の理解を深められるし、共有すると全員の利益となる

〇「形式的証明(formarl proof)」:ソフトに誤りがないことを論理的に検証する方法
〇「半形式的証明」の手法
→10行くらいのブロックにわけて個々のセクションが正しいかチェックする
→各セクション内の機能は一つに絞り込まれているか確認する

〇実践するべきコードプラクティスの例
・goto文は避ける
・変更可能なグローバル変数は作らない
・変数のスコープは可能な限り小さく・ローカルオブジェクトは使う直前で宣言する
・オブジェクトは可能な限り不変オブジェクトにする
・縦横にスペースを入れてコードを読みやすく・関連部分にはインテンドを入れる
・関数には特性や機能がわかる名前を付ける
・セクションを入れ子にするときは関数にする
・関数はできる限り短くし、「24行制限」を守る
・関数の引数はできるだけ減らす(最高4つ)
・カプセル化してインターフェースを小さくする
・クラスを不変で保つようにするので、「setter」は非推奨

16. コメントについてのコメント

〇「このコードはどういう目的で書かれたものなのか」
→初めて読む人にわかりやすくすること

17. コードに書けないことのみをコメントする

〇「書かなくてよいこと」を見極める
→消されて読まれなかったら本末転倒・・・

〇コメントの内容はすぐに陳腐化する

18. 学び続ける姿勢→技術はすごい速さで進化している

〇市場競争力の維持のために「学び続ける姿勢」が重要
・書籍・雑誌・ブログ・Twitterにあたる
・本当に身に着けたい技術は手を動かす
・常に自分よりレベルの高い人と仕事をする
・自分の「良き師」を探す
・フレームワーク・ライブラリに対する知識を深める
・バグや問題について深く理解するように努める
・学びの共有
・勉強会に参加する
・カンファレンスに積極参加!
・コードに弱的分析ツールを実行する
・達人プログラマを読む←
・生産性を高める工夫を忘れない(通勤時間とか)
・学校に通う

19. 誰にとっての「利便性」か

〇APIについて。咀嚼できないので保留

20. すばやくデプロイ、こまめにデプロイ→早い段階からプロセスのテスト・リファクタリングに取り組んで生産性を上げる

〇デプロイは本番環境でのデバックのしやすさ等を確認するうえでも重要
〇製品の開発サイクルからデプロイを行って適切な環境を確認する
→ターゲット環境でのデモができるようになって初めてソフトはビジネス上の価値を持つ

21. 技術的例外とビジネス例外を明確に区別する

〇2種類の例外
→「技術的例外」・「ビジネスロジック的例外」

技術的例外はトップレベル、アーキテクチャレベルでフレームワーク的に処理する。ビジネスロジックは対応方法を組み込んでおく必要がある。

22. 1万時間の訓練(日々の努力?)

○身につけたい内容は細かく、具体的に分割して反復する(完了させることが目的ではない)
○自分の能力を少し超える課題に取り組むことが重要である。失敗すれば修正する繰り返し

23. ドメイン特化言語

○DSLによって専門用語に対応することが可能

内部DSL:汎用プログラミング言語の書き方を工夫して、見かけ上の構文を自然言語に近づけた言語

外部DSL:?

24. 変更を恐れない

○リファクタリングのメリットはプロジェクトの中で何倍もの利益になって帰ってくる→コード変更を恐れず、積極的にシステムを改良していく姿勢
○具体的なポイント
→インターフェース定義・モジュール再構築・コピペ部分のリファクタリング・依存関係を減らしてシンプルにするなど

25. 見られて恥ずかしいデータは使わないこと

〇変数に「うんこ」を入れるなと一緒。

ex. Fu**,

→社用・私用に関わらず「公になっても問題にならないか常に考えること」

26. 言語だけでなく文化も学ぶ

「毎年、新たなプログラミング言語を1つは学ぶこと」から派生

〇言語にはその言語独特の文化というものがあり、真に学ぶにはこの理解が必要
→新たな言語から新たな発想を得て、同じ問題に対して、違った解決策を見つけられるようになるのが大事。新たな言語を学べば、従来から使っていた言語でも、より美しいコードが書けるようになることが多いのです。

27. 死ぬはずのプログラムを無理に生かしておいてはいけない

〇ずっと動かしていて、様々なプログラマが関わっているプログラムに注意
→「汚れている・汚している」可能性がある。

ex. 例外を全て内部でキャッチして、ユーザに見せない処理をしているな

対策:最小限の例外処理と通知をするだけの単純なシステムから始める

28. 「魔法」に頼りすぎてはいけない

〇人は良く知らない他人の仕事を簡単だと思ってしまう癖がある
→「魔法が解けた」時に、マネージャーやプログラマ以外の人の仕事の重要さがわかる。大事なことは誰かが「魔法をかけ直す」必要がある。

29. DRY(Don’t Repeat Yourself)原則

〇繰り返しを避けることの原則(重複は無駄である)
→コードは単一さ・明確な・信頼できる表現になっていなければならない

〇作業の重複は自動化で防ぐ→てまも省ける上、問題も起きにくい

〇関連する原則

OAOO(Once and Only Once), OCP, SRP(単一責任原則)という有名な原則。

30. そのコードに触れてはならない!

〇システム開発プロジェクトにあたっては、分業して手を出さない

→開発サーバとステージングサーバの両方にアクセスできる

〇システムの破損に対して、本番環境でそれを修理しようとしてはいけない。

31. 状態だけでなく、「ふるまい」もカプセル化する

〇カプセル化は重要

クラスは正しく使用するのが最も難しい

オブジェクトは状態と「ふるまい」の両方をカプセル化できる

ex. ドアオブジェクト:「開く」・「閉じる」

ex. Customer, Order, Itemの3種のオブジェクト

→「Customer」:信用限度とクレジットのバリデーションルールを保持する

→「Order」:Customerオブジェクトを知っていて、addItemメソッドはcustomer.validateCredit(item.price())を呼びだして、信用調査を委譲する

〇状態のカプセル化ができていても、ふるまいのカプセル化ができていないと意味がない。

32. 浮動小数点数は実数ではない(要勉強)

〇浮動小数点は実数の近似値であり、誤差が生じることは避けられない(「丸め」による)

→もともと科学技術計算を効率的に行うものなので、どういう時に丸めの誤差が出るかをよくすること

33. オープンソースプロジェクトで夢を実現する

〇オープンソースプロジェクトで好きなソフト開発にとりくまないか

→やる気のある人にチャンスをくれる

メリット:多くの人の仕事ぶりを目の当たりにできる参加するプロジェクトを決めて、使っているツールに関して学ぶ

34. API設計の黄金律(業務上かかわりが薄いので割愛気味)

〇APIを提供するときは、API自身のテストだけでなく、必ずそのAPIを利用するコードのユニットテストも書く

35. 超人の神話

〇何も情報を与えられずに質問に答え、問題を解決できる超人はいない

・よく知らない人の質問

ex. XYZという例外が発生したんですが、何が問題なんでしょうか?

→超人のイメージを持たれると自分の価値を下げてしまう。超人ではなく、積極的に自分以外のエキスパートを育てようとする意志を持った人がエキスパート

36. ハードワークは報われない

〇プログラマは懸命に働いても意味がないことがある

+働かずに済む努力をした方がはるかに大きな貢献をすることもある

〇もっと効率的に仕事する方法を模索するべき

→プロには、備えるための時間、知識と技術を高める時間が必要(入念な準備と効率化のための努力、そして日々の反省と絶え間ない変化が必要)。

37. バグレポートの使い方

〇バグレポートに書くべき3つのこと

・バグの再現方法(できるだけ詳しく)と発生頻度
・本来の仕様(バグがない場合の望ましい動作。こうあるべき、という自分の意見でOK)
・実際の動作(完全でなくても、自分の記録した範囲で詳しく書く)

バグレポートの目的は対話

バグが発生するに至る過程を全て記録する必要がある(35と共通)

(注:バグ数は何かの単位、基準ではない)

38. 余分なコードは決して書かない(Less is more)

今必要のない、余分な機能を削って、コードベース全体の「エントロピー」を下げる

→余分なコードの保守にかかる手間は雪だるま式にふえる

→要件を決めるのはプログラマではなく、顧客である

39. 最初が肝心

〇ユーザが製品を使い始める段階でつまずかないよう、十分に配慮がなされているかどうか

手間のかかることはしたくない

説明が不十分なものやわかりにくいソフトは使われない

→有用性が同じであれば、手間のかからないものの方が有利

40. プロセス間通信とアプリケーションの応答時間の関係

〇応答時間を左右するのはIPCの数> データ構造とアルゴリズム

IPC:Inter Process Communication

リップルローディング:データグラフ取得のために、何度もデータベース呼び出しを繰り返すこと。→リモートIPCの数を減らすのが大事

HOW?:必要なデータだけを最低限のインタラクションで取得。IPCを並列化

41. 無駄な警告を排除する

〇ノイズを排除し本当に対応するべき警告を1つだけ出す

→真に意味のある警告を見逃さないように

ビルド時に警告が1つでも出たら必ずその場でつぶす

警告への対応方法
・原因のコードを修正する
・警告が目に触れないように隠す
・警告ポリシーを変更する

42. コマンドラインツールを使う(IDEのメリットすら知らない気がする…

〇コマンドラインツールを使うとビルドプロセスについてよくわかる

今はIDE(Integrated Development Environment:総合開発環境)が主流

デメリット
・IDEの裏側を知ることができない

メリット
・makeファイルを書くにはコンパイル、アセンブル、リンクなどを知る必要がある
・ 置換はgrep, sedなどのコマンドがはるかに便利
・スクリプトを作成するとテスト作業などが簡単に自動化できる

43. プログラミング言語は複数習得すべき

〇プログラミングの習熟度はどれだけ多くのプログラミングパラダイムに親しんでいるかで大きく変わる

→かじった程度ではだめその言語を使って正しくプログラムを書く

パラダイムの種類

・手続き型, オブジェクト指向, 関数型, 論理型, データフロー型

パラダイムの違いで複数言語習得の難易度は変わる

同じパラダイム(C, Pascal, Fortran)

〇第二の言語は最初の言語と違う言語を選ぶべき

→同様のアルゴリズムを実装するにしても様々なやり方があることに気付くのが大切

44. IDEを知る

〇昔は全部「テキストエディタ」だった

→IDEは1990年代に生まれた。当時は商品、今は無料

IDEとは:テキストエディタにコンパイラ、デバッガ、コードフォーマッタなどのツールの機能を組み込んだようなもの

コードのリファクタリング機能が秀逸

viやUNIXは習得に時間がかかるけどかなりおすすめ(学習曲線は急勾配だけど…)

プログラマにとってIDEはブロートーチ(簡易型溶接機)(当然使えるべきものの意味)

45. 限界を知る

〇お金や時間など、リソースの「限界を尊重する」べき

ソフトウェア技術者の場合自分自身, PJのメンバ, 予算, 時間, ハードウェア, ツール, データ構造, アルゴリズム, アーキテクチャ, 性能などなど

→プログラムの実行時間などには配慮をするべき

46. すべきことは明確に

〇大項目を小項目に分解する

→作業単位に分割して時間管理する

時間以内に解決しないときは加えた変更を破棄し、一旦作業を白紙に戻した方がいい時もある

1. まず、自分の作業を明確にし、完了する期限を必ず決める
2. 終了しなさそうならその間に書いたコード、コードに加えた変更は全て破棄する
3. 再度小目標を立て直して作業内容を検討し、初めからやり直す
4. 模索段階で書いたコードを決してレポジトリに入れてはいけない

47. 大量のデータはデータベースで

〇大量の永続データはRDBMSにデータを保存するべき

ex. MySQL, PostgreSQL

組み込みデータベース:SQLite, HSQLDB(ライブラリとしてアプリケーションに直接リンクされる)

→アプリケーションのパフォーマンスの向上に寄与

48. いろいろな言葉を学ぶ

〇プログラマにとってコミュニケーションはとても重要

コンピュータに理解できる言語をうまく操る+他人と話しながら進めるチームワーク

〇優秀なプログラマはプログラミング言語のみならず、自然言語も非常にうまく使うことができる

〇話す相手の言葉を知る(ex. 会計士とか他の業種)

ソフトウェア業界の外にいる人とコミュニケーションをしてみれば他の世界の言葉を知ることの重要さがわかる

→大事なのは自分が話すこと以上に、相手の話に耳を傾けること

49. 見積もりとは何か

〇目標達成のために時間やお金、リソースの必要量を判断をする

〇以下3つの正確な理解が必要

見積もり:「事実の裏づけに基づく測量」が必要
 →信頼のおける数値や過去の経験などに基づく予測のこと
ターゲット:実現したいビジネス上の目標を明文化したもの
 →ex. 「システムBは同時に400人のユーザが利用できなければならない」
コミットメント:ある機能をある期日までに一定以上の品質で提供することを約束する
 →ex. 「製品を次のリリースまでに検索機能を可能にする」

→プロジェクトに関わる人たちが「見積もり」という言葉の意味を正しく認識しない限り、どれだけ素晴らしい見積もりをしても無意味

50. Hello, Worldから始めよう(内容が高度でわかりません、)

問題の解決のためには、シンプルな方法をとるのが〇

51. プロジェクト自身にしゃべらせる

〇XFD(eXtreme Feedback Device)を活用する

→異常があれば即ランプや音・音声などで知らせる仕組み。

うまく使えばプロジェクトのご意見番になる

52. 「その場しのぎ」が長生きしてしまう

〇「暫定ソリューション」は既成事実化してしまう

対応は3つ

・暫定ソリューションは一切作らない
・体制を変える
・暫定ソリューションを不要にしてしまう、有用性の高いソリューションを作る

→大事なのは自分に変えられることと、変えられないことを冷静に見極めること

53. 正しい使い方を簡単に、誤った使い方を困難に

〇ユーザの利便を第一に

設計が良ければインターフェースは使いやすく、生産性は向上する

設計が悪ければインターフェースがストレスやミスの原因になる

〇よいインターフェースとは

・正しく使用する方が操作ミスをするより簡単
・誤った使い方をすることが困難

→作る前に使ってみるというのが有効(GUIならモックアップを作ってみる)

使いやすいインターフェースは「自然である」=「常にその状況で一番しやすいことをしていれば、自動的に正しい使い方になる」

54. 見えないものを見えるように

〇ソフトウェアは「ほとんど透明」

目に見えない…

ex. ソフトウェア・Googleの裏側・デバック作業・進捗

コードはユニットテストを書くことによって、その堅牢さ、難しさを可視化できる

進捗は掲示板やカードをうまく使えば可視化できる(未着手・進行中・完了済み)

開発はインクリメンタル開発をすることで、進捗が目に見えるようになる。

→ソフトウェア開発プロジェクトを進める際はいつでも、目に見える証拠がたくさんあるという状態を維持すべき

(おまけ)開発プロセス

インクリメンタル:繰り返しの中で新しい機能を追加していく

イテレーション:繰り返しの中で大まかに作成済みの機能を磨いていく

ウォーターフォール:枠を確実に作成し、後半に一気に機能を実装する

55. 並行処理に有効なメッセージパッシング(ワカラン)

メッセージマッチングに対応したライブラリ・フレームワークを使う

56. 未来へのメッセージ

〇誰のためにコードを書くのか?→ほかに読む人にわかりやすいコードを書くこと

簡潔で美しいコードを心がける。取り組む問題が難しければ、ソリューションもわかりにくくなるものではない

57. ポリモーフィズムの利用機会を見逃さない

(※ここはプログラミングの思想と直結するので書籍で勉強した方がいいとおもった)

〇オブジェクトやメソッドの特性、動きをコンテキストに応じて変えることができる

“poly”[多数]と”morph”[形]に由来する

ex.「このコンテキストならあのオブジェクト、あるいはメソッドを使う」

→if-then-elseブロックは全てポリモーフィズムが使えないか検討した方がよい

58. テスト担当者はプログラマの友人

QA(Quality Assurance:品質保証), QC(Quality Control:品質管理)

〇テストとデバックを繰り返して、リリース前にあらゆるバグをみつけること

→些細なことで腹を立てないこと、恥をかくどころか、高く評価してくれるよ。

些細で簡単なミスが見つかり、顧客の目に触れるとプログラマとしての資質を疑われても仕方ないので気を付けること!

59. バイナリは常に一つ

バイナリ:PCが処理するメッセージ

〇みんなが常に同一のバイナリを使用するようにする

どの環境でも同じバイナリを使うことで、トラブルを回避できる

〇環境に関する情報もバージョン管理の対象とする

環境設定の変更によって生じるトラブルを把握するため

→git, bazaarを利用する

60. 真実を語るはコードのみ

→大量のコメント<バージョン管理システムへのチェックインの際に添えるメッセージに書く

〇読んでわかりやすいコード

1. わかりやすい名前(機能がイメージできる)

2. 依存関係を持たせない

3. 良いソリューションが浮かんだら即リファクタリング

→自分の目に触れるコードをわかりやすくしておけば、あらゆる作業が円滑に進むようになる!

61. ビルドをおろそかにしない

ビルドプロセス:ソフトウェアのビルド(英: build)は、プログラミング言語で書かれたソースコードファイルや各種リソースファイルを独立したソフトウェア生成物に変換するコンピュタ上で実行されるプロセスまたはその結果を指す。(wiki)

ビルドスプクリプトは重要。不適切に書くと保守と改善が難しくなる

→ビルドプロセスも開発チームの仕事

62. プリミティブ型よりドメイン固有の型を

〇データの型付けの重要性(ex. 1999年9月23日火星探査船の話)

〇ドメイン固有の型を使う方がよい場合→コードの品質の向上につながる

ex. Velocity_In_Knots →単位がノットであることがわかる

ex. Distance_In_Nautical_Miles→距離のデータを扱う型。海里とかもわかりやすく書ける

〇利点

・コードが読みやすくなる。FloatとかStringなどの型名より意味が分かりやすい

・テストがしやすくなる・機能がカプセル化され、他から独立するため、個別のテストがしやすくなる

・コードの再利用が容易・同じコードを複数のアプリケーションやシステムに簡単に再利用する

→ドメイン固有の型を積極的に使ってソフトウェア品質を高めるべき

63. ユーザの操作ミスを防止する

〇入力してほしいのは情報であり、データではない

ユーザとシステムの間のコミュニケーションを円滑に

システムはユーザの操作ミスに対し寛容であるべき

ex. 日付の入力フォーマットの指定

→アンドゥ機能でユーザの操作の傾向を把握し、入力時にどのように判断を下しているかを知ることが重要

64. プロのプログラマとは

〇「自分が責任を取る」という態度、責任感

キャリアと製品の質に責任を負う

・自分の力で自分を高め、成長していく
→会社が教育を受けさせてくれるというスタンスは完全に間違い

・プロのプログラマは自分の書いたコードに責任を持つ
→徹底的にテストし、「絶対に問題が見つからない」と思えるまで、コードをQAには回さない

・プロのプログラマはチームプレイヤー。一人一人が自分の仕事だけではなく、チーム全体のアウトプットに責任を持つ

〇最善の努力をしていい製品を作る

65. バージョン管理システムを有効に使う

〇プロジェクトを構成する要素は「とにかく何でもバージョン管理の対象にするべき」

操作は2つだけ:コードの変更をリポジトリにコミットする・作業ディレクトリでアップデートする

プロジェクトのバージョンが固有のIDで管理できるようになる

〇開発メンバの守るべきルール

・意味のある変更ごとに逐一コミット
・コミットの際にはメッセージを添える(どこを、なぜ変更をしたのか)
・ビルドを壊すコミットをしない

→プロジェクトを円滑に進められるようになる

66. いったんコンピュータから離れてみる

〇コーディング中は論理が優占し、創造的な解決策は見つからないもの

ex. ルールベースからひらめきで正規表現を使って文字列を検証することにした

→じっとコンピュータの前に座って考え込んでいるより良いアイデアを思いつくもの

67. コードを読む

〇他人の書いたコードを読むことは自分の成長につながる
→問題解決の方法が自分と違う場合が多い

「そのコードが読みやすいかどうかを考える」

→反省をする

〇読みやすいコードを見つけたら、よく調べ、できるだけ多くのことを学び取る(OSPには質の高いものが多い)

以前書いたコードを読み返すのも勉強になる。一番いいのはとにかくコードを読むことです。

68. 「人間」を知る

〇ソフトウェア開発プロジェクトは人と人の共同=「人のビジネス」
→プログラマこそ人とのかかわり方を大切にするべき

プログラマはツールに注目するが、ユーザは機能のみに興味をもつ→意識の「ずれ」がある音を認識する

〇お互いに理解しあうには「定義の共有」ではなく「経験の共有」が必要。

→共通する部分がないと、理解しあえないという。。

69. 車輪の差異発明の効用

〇車輪の再発明の失敗は成功よりも貴重な経験

→ソフトウェアの核になる部分を自ら実装する機会となる

本を読み知識を入れることは大切だが、優れたプログラマになるためには経験を積むことがどうしても必要。現場を見て、自分の手で何かを作る経験。これが必要

70. シングルトンパターンの誘惑に負けない

シングルトンパターン:多くの問題の解決に役立つパターン(シングルトンとは、オブジェクト指向プログラミングにおけるクラスのデザインパターンの一つで、実行時にそのクラスのインスタンスが必ず単一になるよう設計すること。)

〇実は多くの問題を抱えている。使わないほうが良い

・「必要なインスタンスは一つだけ」という要望は多くの場合推測に過ぎない
・理論的には独立しているはずのコード間に暗黙の依存関係を生んでしまう
・シングルトンパターンは永続化された状態を暗黙のうちに伴う
・マルチスレッド環境での使用は特に危険が大きい
・シングルトンを明示的に殺すための機能はない
・プログラム終了の際にはシングルトンも自動的にクリーンアップされることになる

→シングルトンをどうしても使う際には必要なインスタンスが絶対に一つだけと確信できる場合のみ使う。

71. パフォーマンスへの道は地雷コードで敷き詰められている

〇プロジェクトのスケジュールは地雷の炸裂などで予測は難しい

→コードが他にあり、影響を与えることがある。壊れた依存関係を修復する作業も入れて、計画を立てると〇。

ホットスポット:プログラムの実行時間の80%はコードの20%(ホットスポット)で実行される、といわれる。

ソフトウェアメトリクス:コードの依存性、複雑さを計測するための手段→様々な特性を定量的に評価した指標(ファンイン(fan-in), ファンアウト(fan-out))

→クラスのファンアウトというのはクラスが直接、または間接的に参照しているクラスの数のこと

72. シンプルさは捨てることによって得られる

〇コードはシンプルであるべき

質の悪いコードはなんの役にも立たない。。

→良い部分だけは残して、悪いところは全部消す!その意気が大事。

73. 単一責任原則(SRP:Single Responsibility Principle)

◯良いデザインの基本原則

「変更する理由が同じものは集める、変更する理由が違うものは分ける」
→一つのシステムやモジュール、クラス、関数などに変更する理由が2つ以上あってはならない

〇よいシステムデザインはコンポーネントがそれぞれ独立してデプロイできるようになっている

「依存関係逆転の原則(Dependency Inversion Principle:DIP)」を遵守する

→SRPを守り、違う理由で変更しうるコードを別要素に切り分けることは各コンポーネントを独立してデプロイできるような設計をするうえで非常に重要な条件

74. 「イエス」から始める

〇「わからない」→自分の不勉強を相手に知らせてしまう。
→そこから解決策を考える姿勢が重要

「イエス」から始めることはテクニカルリーダに不可欠な態度だ。

質問に対して、「質問の理由は何か」・要望の原因は何かを考えることは重要である

→「イエス」から始めれば、人との対立は生まれず、協力関係が生まれるのです。

75. 面倒でも自動化できることは自動化する

〇行動の頻度を意識する

〇誤解例

・自動化はテストだけのもの

→ドキュメント・デプロイ・レポート生成などもできる

・IDEを使っていれば自動化の必要はない

→設定次第で環境はみんな違う。常に同じビルドをできるように、AntやAutotoolsなどの自動化システムが役に立つ

・自動化のためには特殊なツールについて学ぶ必要がある

→bashやPowerShellで十分です。webとのやり取りなら、iMarosやSeleniumがある

・扱うファイル形式によっては自動化ができないことがある

→プレーンテストじゃダメなのか

・忙しくて自動化のことまで勉強している時間はない

→自動化を進めながら勉強するということでOK

76. コード分析ツールを利用する

静的解析ツールは昔からバグを減らすためにとても有効であった。

〇コードの品質を高める唯一の方法はテストだけではない

→解析ツールも積極的に利用するべき。自ら作ってもOK

ex. Pyhtonのdisモジュールなど

対象:スタイルガイド違反・ヌルポインタ逆参照なども検出できるものもある

77. 偶然の仕様ではなく本物の仕様のためにテストを書く

〇テストを効果的なものにするには、実装で生じた偶然の仕様を確認するのではなく、あくまで、コードがもともとの要求に合っているかを確認するべき。→ブラックボックステストが有効。テスト対象のコードの中身ではなく、外から見た動きに注目してテストを書き、もともとの要求にあっているかみる。

78. テストは夜間と週末に

〇夜間や週末にテストサーバを動かそう

夜間・週末の活用で解決できるテスト課題(時間とリソースが余っている環境)
・納期まで時間がないとテストする前に変更をコミットしがち…
・製品の安全性テストのための機会がない
・パフォーマンステストのための機会がない
・順列組み合わせテストの必要があるが煩雑

79. テストのないソフトウェア開発はありえない

建築や土木の開発とソフトウェア開発は本質的には異なる

〇ソフトウェア技術者は作りながらテストする

→テストが品質保証のための第一の手段

テストはソフトウェアの品質・再現性を保証し、品質を一定以上に保つためにすること

80. 1人より2人

〇プログラミング作業は複数人で協力するのが主流

→プログラマ同士、ビジネスアナリスト、システムアナリスト、QA担当者、ユーザなどとも関係を密にするべき。ソフトウェアの品質が向上する可能性が高い。まずは同僚のうち、誰かと組んで試してみよう

81. エラーがエラーを相殺してしまう

◯一方のエラーを治すと問題が顕在化する事が多い、

→表面上起きている問題は1つだが、関わっているコードが2つ以上ある場合、複数の修正が必要になり対処が難しくなる

ex. アポロ11号のエンジン制御ソフトウェアのバグ

→大切なのはこのような問題が存在すること、思い込みを捨ててあらゆる対処を思いつくよう冷静さを保つことが重要

82. 他者への思いやりを意識したコーディング

◯ソフトウェアを作るには技術も必要だが、他人との関わりも重要

→ときには顔を上げる。プログラマはソフトウェアに関わるすべての人の成功に寄与する責任があるが、その責任は他の全関係者と共有している

ex. ubuntuはズールー語で「他人への思いやり」という意味

◯自分のコードの質の低さは全体に悪影響をもたらす。コードの質が高いと思っても他のプログラマの存在を意識すればより良くする方法が見つかる

→思いやりを持ってコードを書けば、同僚たちにとって価値あるコードとなる。ともかく、プログラマが他の人への思いやりを持たずにコードを書くことはありえない

83. UNIXツールを友にする

◯UNIXツールは自分の発想次第で何でもできる

→IDEの場合は開発者の考えたコマンド以外使えない

もともとUNIXツールはRAMが128KBしかない時代に開発された

→現代の大容量RAMのPCであれば事実上扱えるデータに上限がない

「スモール・イズ・ビューティフル」→必要十分な機能を持ち応用範囲の広いツールを使おう

84. 正しいアルゴリズムとデータ構造を選ぶ

ex. 莫大なデータ量のテキストデータを一文字ずつ判定していた。。。

◯「まずは動かす」…とはいえ適切なアルゴリズムを選ぶようにする

→可能であれば既存ライブラリを使う+既存のアルゴリズムのスケール特性について学ぶ必要がある

85. 冗長なログは眠りを妨げる

〇「汚いログ」を残さない

ログは多くても少なすぎてもダメ

〇多すぎるログはないのと同じくらい役に立たない

→本当に重大な問題が起きた場合以外、基本的にエラーログには何も記録されないのが良い。うまくいっているときは、優先度の低いメッセージが重要なアプリケーションイベント1つにつき1つ出れば充分

86. WETなシステムはボトルネックが見つかりにくい

〇DRY原則(Don’t Repeat Yourself):同じことを繰り返すな

 ⇔ WET(Write Every Time):必要なものをその都度書く

→DRY原則が破られやすい状況に気を付けて、WETなシステムを避ける。

DRY原則を守ることで、パフォーマンスのボトルネックの発見と解消がWETなコードの場合より容易になっている。

87. プログラマとテスターが協力してできること

(お互いに敵ではない。)

〇テスタ:プログラマにテスト項目を早めに連携する

→これから書こうとするコードがどのようなものか明確にできる

ex. 返り値を受け取る際の正規表現の組み方など

〇プログラマ:テスタがテストしやすいコードを書くことは当然の責務であると考える

→回帰テストと自動化をテスターと共同で進めることなども簡単にできるようになる

88. コードは生涯サポートするつもりで書く

〇プログラマが必ず知っておくべきこと→様々な答えがくる。

〇大切なのは自分なりの「ベストプラクティス」を守り続け自分のものにする。そのためには「生涯自分がサポートし続けなくてはならない」と思ってコードを書くこと

→技術力を高め、命名法・常に良いデザインパタンを探し、使う。コメントもまめに、テストも逐一実施、リファクタリングも頻繁になるもの

〇書かれたコードで書いた人がどういう人か評価する

→コードを1行書くたびに、ユーザのこと、顧客のこと、自分のキャリアのことを考えるべき。コードは自分の人生を決めると思って書くべき

89. 関数の「サイズ」を小さくする

◯関数を作るときは必要十分な要素で。

ex. x > 2 これは2より大きい実数すべてが当てはまる→完全に正しいという証拠を得る検討の数がバカでかい

組み込み型の代わりに、問題領域固有の方を使うほうが良い。ex {1,2,3,4}

→型は関数を書く前に問題領域について知識を基に考えるべき。確認すべき数を極限まで削る

90. コードを見る人のためにテストを書く

◯誰のためのテストか→コードを見る人のため

◯良いテストの条件

・コンテキスト、出発点、満たすべき事前条件がわかる

・ソフトウェアがどのように起動されるかがわかる

・期待される結果と、確認すべき事後条件がわかる

テストメソッド名は「そのメソッドに期待される実行結果」がわかるようにすると良い

+あえてエラーを混入させ、期待通りそのエラーが検知されるかを確認するのも◯

91. 良いプログラマになるには

〇両者の最大の違いは取り組む姿勢にある

→次のことを心がける

・どんな場面でも「とりあえず動かす」ためのコードは決して書かない
・わかりやすいコード:保守しやすいコード, 正しいコードとは何かを考え続ける
・他のプログラマと協調してチーム全体の成果を最良とするように努力する
・自分が扱ったコードは少しでも良いコードにする(構造を変える、改めてテストする, わかりやすく修正する)

〇難しい問題を見事解決できるプログラム、自ら誇りに思えるプログラムを書こう。

92. 顧客の言葉はそのまま受け取らない

〇顧客とプログラマは話し方が違う。そもそも何が欲しいのかよくわかっていない人が多い

→顧客との関りを密にすること。早い段階から、頻繁に疑問を投げかけ、説明を求めるようにする

〇コツ

・言葉を換えて言い直す(2,3回繰り返す)

・複数の人々と別々の機会に話し合うべき

・ホワイトボードを利用して、図や絵を利用する

93. エラーを無視するな

◯コードからエラーを通知する方法

・戻り値を使う(関数が正しく実行されなかったときに内容を示す値が戻るようにする)
・errnoを使用する
・例外を使用する(エラー通知とハンドリングの方法は言語仕様で定められている)

◯エラーを放置すると次の事が起こる

・不安定なコードができる(修正しにくいバグが多い)

・セキュリティ上問題のあるコードができる(クラッカーが侵入する際にはエラー処理の不備を利用することが多い)

・貧弱な構造とインターフェース(利用側のエラーハンドリングが煩雑で面倒なコード)

94. リンカは魔法のプログラムでは無い

リンカ:オブジェクトファイルのコードセクション、データセクションを連結し、定義されているシンボルと参照を接続し、ライブラリから未解決シンボルを抽出し、実行ファイルを書き出す

1. ソースコードを編集する
2. ソースコードをコンパイルすると、オブジェクトファイルが作成される
3. 何やら不思議な処理が行われる
4. 実行ファイルができる

95. ペアプログラミングと「フロー」

フロー状態:なにかに完全に没頭知っているとき

◯フロー状態の維持には「ペアプログラミング」が役に立つ

パートナの経験が浅い場合:忍耐強く接すること

パートナが自分より技術ある:気後れすることなく接する

→自分や他のメンバの長所・短所がどこにあるのか注意深く見るようにすると、他のメンバから学べることは多い。

→ペアのパートナとタスクのローテーションが頻繁に変わるようにする

◯フロー持続の理由

・不慮の事態の影響を最小限に抑えることができる(チーム全体で知識や技術を共有しているから)
・問題解決が容易(誰かに相談できるからね)
・統合がスムーズ(パートナにすぐ聞ける)
・割り込みの影響を緩和できる(急な対応を調整できる)
・新人が早くプロジェクトに馴染む(担当するタスクとパートナをローテしていれば新人も色々な部分のコードとチームのメンバに馴染むことができる)

→フロー状態になれば生産性は驚くほど向上する。フロー状態を維持するためにあらゆる手段を講じる

96. テストは正確に、具体的に

〇テストは正確で厳密に

→コードの動きが本来の要求にあっているかを確認する

ex. ソート処理のコードのテスト

→「正しい順か」+「処理以前と長さは同じか」+「処理前と同じ値で構成されているか」

〇正確なだけでなく、誤解の余地のないものにしなければならない

97. ステートに注目する

〇ステート:状態

ex. webショップ

・進行中:注文の追加、削除はできない。商品の発送は可能。

・決済済み:注文の追加、削除はできない。商品の発送は可能。

・発送済み:注文処理が全て完了。変更は一切受け付けない。

→ステートは重要。何か操作をしようとすればどのステートにいるかを確認する必要がある

〇Statesパターン→Design by Contractについて学ぶ

〇ステートに注目して考えれば、コードをよりシンプルにそして堅牢にする

参考本:デザインパターンにおける、23の主要なパターン

今回は、日本語版に翻訳された際に巻末に「日本人プログラマによる知っておくべき10のこと」に追加されたエッセイ集をまとめました。

1. 命を吹き込む魔法

〇プロジェクトのコードネームを設定する

→チームをまとめるシンボルになる

ex. wikiのサイト名, ソースコードのレポジトリ名, メーリングリスト…etc

〇名前の由来が具体的で、身近なものを選ぶ

→コードネームの仕掛けで遊ぶ時もよく知っている名前の方が連想が弾む

〇素敵なコードネームをつけたら何度も口にしていく

→チームの結束する秘密の合言葉で遊び、ソフトウェアに命を吹き込んでいく

2. ロールプレイングゲーム

〇「理想のプログラマ」とは

→難しいので「演じる」(勤務中は理想のプログラマのふりをする)

〇理想像は本の中ではなく、あくまで「現場(チーム)」の理想を追求する

→チーム内の理想は各々の判断でに対して良い悪いのフィードバックを行うことで徐々にチームの価値観が醸成される(「理想」なので仕方なくフィードバックすると思うと楽…)

3. ルーチンワークをフローのきっかけに

〇単純作業を「きっかけ」にする

→フロー状態への助走

ex. 1日の終わりに翌日最初に行うことを決めてメモしておく

ex. 変更のアイデアをコードのコメントとして残しておく

〇自動化することも重要だがほんの少しだけ、その作業で手や頭を動かす余地を残しておくのも重要かも

→単純作業もプログラマがクリエイティブになる準備としては悪くない!

4. プログラマが持つべき、3つのスキル

(1)コードを読むスキル
(2)テストするスキル
(3)デバッグするスキル

→ソフトウェア開発の場で、体を動かして経験を積むしかない

〇理想的には現場に師匠を見つけて弟子になる

→難しければOSSプロジェクトで見つけて入っていく(まずはメーリングリストの購読とかで〇)次にgitのレポジトリからコードを落として、バグを直す(バグフィックス)練習をしてみる

OSSプロジェクトの場合、メールなどのやり取りがコミュニケーションのいろはを習得できる機会にもなる。

5. 快適な環境を追求する

〇身の回りの環境を改善することで毎回の作業が効率よくなる

→時間を有効に活用→快適にコーディングできるようになる

6. 見知らぬ人ともうまくやるには

〇バグには2種類

①できるはずのことができないこと

②できてはならないことができること

〇できてはならぬことを禁じるのではなく、初めからできていいことだけをできるようにする

ex. Linuxのスーパーユーザの考え方

7. 不具合にテストを書いて立ち向かう

〇TDD(Test Driven Development)

→「不具合の修正時には必ず先に不具合を再現する自動テストを書いてから修正する」

メリット

・不具合が本当に自分の考えた原因で発生しているかが明らかになる
・対象コードと対象領域に対する理解が深まる
・自分の弱点、気づきにくい点がわかる
・テストの堅牢さ、価値が上がる
→不具合を克服して立ち上がるたびにテストの網羅性は上昇、既存コードに対する自信も深まる

〇テストを友として、自信を持ちながらコードを書く

→テスト駆動開発を身に着けたプログラマ

8. 育ちのよいコード

〇巨大な関数・相互依存(凝縮・結合)を作らない

・疎結合なコードは変更があちこちにまたがらない
・高凝集なコードは変更が1か所にまとまるはず

〇先を急ぐ野心と慎重な設計を橋渡しするのがリファクタリングの役割

→リファクタリングを独立したパッチに追い出せば、優れた設計を示す「まとまりの良い」パッチが残る。

9. Noといえることの大事さ

〇機能追加を色々つける

→オプションの実装はニッチな回収になりやすい

→バグの出やすいソフトウェア(Feature Creep)と呼ばれる

10. 名前重要

〇RubyはPerlの翌月の誕生石

〇適切な命名ができた機能はうまく実装できることが多い

→機能が果たすべき役割を設計者自体がうまく理解できている状態

end

ryuichi