Upgrade to Pro — share decks privately, control downloads, hide ads and more …

2022年度新卒技術研修「良いコードの書き方」講義

 2022年度新卒技術研修「良いコードの書き方」講義

良いコードの定義を「読みやすいこと、拡張しやすいこと、安全なこと」の3つにしぼって解説したコーディングに関する講義です。

excitejp

June 17, 2022
Tweet

More Decks by excitejp

Other Decks in Technology

Transcript

  1. 原則 Keep It Simple! Stupid. (KISS) コードを書くとき最優先の価値を「単純性」「簡潔性」に置きます。 - 新しく覚えた技術を使いたい -

    将来の必要に備えたい(YAGNI) - 勝手に用件を加えてしまう といったことを避けましょう。 機能が同じであれば, 余計なコードを含まないコードの方が優れています。 7
  2. 原則 Don’t Repeat Yourself. (DRY) 同じ知識(コード)を重複して書いてはいけません。 重複はコード量を増やし, 理解を妨げ, 変更の難易度をあげます。 知識(コード)を抽象化しましょう。

    単にコードをそのまま説明しているコメントも重複です。 オブジェクト指向や設計, デザインパターンといった技術はコードの重複の排除を目的の 1つにしています。 8
  3. 原則 You Aren’t Going to Need It. (YAGNI) コードは「多分必要になるだろう」で書いてはいけません。 色々な事態に備えてコードを盛り込んでおいても使われないことがほとんどです。逆に

    時間が経つとなぜ使われないコードがあるのかわからなくなります。 汎用性よりも単純性を考え, コードは「今」必要なものに留めましょう。 仮に要件が増えて拡張することになっても, 単純なコードを変更する方が, 汎用的で複雑 なコードを変更するよりも簡単です。 9
  4. 原則 Open Closed Principle (OCP) コードの振る舞いを拡張してもその他のコード(クラスやモジュール)には全く影響を受け ないようにしましょう。 ソフトウェアの寿命は想定よりも長くなる傾向にあります。柔らかい設計を意識しましょ う。 そのためにはポリモーフィズムが重要です。

    オブジェクト指向と手続き型の違いはここへの対処と言い切ってる書籍もあるくらいで す。(Robert C. Martin著, 角 征典・高木 正弘訳, Clean Archetecture 達人に学ぶソフトウェアの構造と設計, 株式会社ドワンゴ, 2018) 10
  5. まとめ 今回紹介したプリンシプルを簡単に意訳すると - シンプルにする - 重複させない - 将来の予測をしない - 他へ追加変更の影響を及ぼさないようインターフェースを使う

    - 処理を分岐させない - テストしやすいように書く - クラスは機能単位でまとめて各機能は他機能を参照しない - どのタイミングで何度実行しても同じ状態となるようにする 16
  6. 命名 意識すべきこと 変数, 関数, クラス名は次の大命題に応える必要があります。 - なぜそれをするのか - 何をするのか -

    どのように使用するのか もし名前に解説が必要なら, その名前は意図が明確とは言えません。 20
  7. コメント Docコメントの無くし方 29 /** * idのユーザーを DBから取得する * * @access

    public * @params int $id 検索用のユニークな ID * @return User $user ユーザーオブジェクト **/ public function get($id) { } public function findById(UserId $user_id) : User { }
  8. コメント インラインコメントの無くし方 30 // 名前は20文字以内であるべき if (length($name) <= 20) {

    return false; } // 生年月日の月は 1~12のうちのいずれかであるべき if ($month >= 1 && $month < 12) { return false; } if (isInvalidNameLenght($name)) { return false; } if (isInvalidMonth($month)) { return false; }
  9. コメント 許されるコメント 以下のようなコメントは許されます。 - 意図を示す - なぜそう書かなければならなかったのかを示す - 警告する というのは英語圏の書籍の主張です。

    基本的には賛成ですが, 英語のコードを読むのは基本的に辛いです。 コメントすることで理解の負担や時間を減らせるのであればヨシです。 31
  10. 条件分岐 条件の関数化 if ($user.type === 'child') { } if ($user.isChild())

    { } 33 まずは条件を関数化してみましょう。 例として大人と子供という区分を作って関数化してみます。 これはuser.typeをprivateにすることで防げるという見方もできます。 カプセル化を緩めるとこのように外部にロジックが漏れる危険性があります。 ※とは言え, getterを全く持たないことも不可能です。
  11. 条件分岐 早期リターン else句はコードを複雑にします。早期リターンを使って無くしましょう。 大人と子供の料金を返す関数を例としてみます。 private function fee(User $user) : int

    { if ($user.isChild()) { return 100; } else { return 200; } } private function fee(User $user) : int { if ($user.isChild()) { return 100; } return 200; } 34
  12. 条件分岐 ポリモーフィズム interfaceを使ってif文を無くします。 これで線形原理が実現できました。 interface User { public function fee()

    : int; } class Child implements User { public function fee() : int { return 100; } } class Adult implements User { public function fee() : int { return 200; } } 35 private function fee(User $user) : int { if ($user.isChild()) { return 100; } return 200; } $user.fee();
  13. 条件分岐 ポリモーフィズム ポリモーフィズムを使えば新しい区分の追加もクラスの追加のみです。 ちなみに, 生成はFactoryクラスで分岐させるようにします。 これはOCPも満たしています。 36 class Baby implements

    User { public function fee(): int { return 0; } } public static function factory(string $type) : User { $types = [ 'baby' => new Baby(), 'child' => new Child(), 'adult' => new Adult(), ]; return $types[$type]; } 生成してもらう
  14. 参考文献 [1] Dustin Boswell Trevor Foucher著 角 征典訳, リーダブルコード より良いコードを書くためのシンプルで実践的なテクニック

    , O’REILLY, 2012 [2] Robert C. Martin著 花井 志生訳, Clean Code アジャイルソフトウェア達人の技 , ASCII DWANGO, 2017 [3] 上田 勲, The Principles Of Programming 3年目までに身につけたい一生役立つ 101原理原則, 秀和システム, 2016 [4] 増田 亨, 現場で役立つシステム設計の原則 変更を楽で安全にするオブジェクト指向の原則技法 , 技術評論社, 2017 48