$30 off During Our Annual Pro Sale. View Details »

良いコードとは 研修

techtekt
August 25, 2023

 良いコードとは 研修

パーソルキャリア株式会社 テクノロジー本部 エンジニアリング統括部 サービス開発部
※本資料は2023年3月時点の情報であり、当該部門における2023年新卒の研修教材です。

techtekt

August 25, 2023
Tweet

More Decks by techtekt

Other Decks in Programming

Transcript

  1. 良いコードとは
    パーソルキャリア株式会社 テクノロジー本部 エンジニアリング統括部 サービス開発部
    ※本資料は2023年3月時点の情報であり、2023年新卒の研修教材です。

    View Slide

  2. この研修では手を動かす内容はありません。
    良いコードの初歩的な部分の説明なので気楽に聞いてください。
    この研修について

    View Slide

  3. 目次
    ● 良いコードとは
    ● コードを読みやすくする
    ● おまけ

    View Slide

  4. 良いコードとは?
    ● 保守性が高い
    ● 正確に動作する
    ● 無駄な部分がない
    ● 効率的に動作する
    などなど
    縣 俊貴.『良いコードを書く技術── 読みやすく保守しやすいプログラミング作法』. 技術評論社.2021年,24p

    View Slide

  5. 将来的な修正や保守作業を容易にするために設計された、読みやすく理解しやすく、
    変更が容易で堅牢なコードのこと
    実際は複数人で開発するため、他人が読んでも理解できるようなコードを書く
    数ヶ月後の自分が読んでも理解できるコードを書こう
    保守性が高い

    View Slide

  6. ”確実に動作し、信頼性が高いことは良いコードの条件です。”
    ”良いコードは防御的で、不測のバグを生み出しにくい作りになっています。”
    正確に動作する
    防御的プログラミング
    「正常な値が来るはず」という決め付けをせずに、不正な値が来ても被害を受けないように防御
    的にプログラミングを行うこと
    防御的コードが過剰に存在するのも問題で、型による制限など不正な値がそもそも存在し得ないような制約
    を設けることも検討する。言語やフレームワークの機能も適切に利用する。
    縣 俊貴.『良いコードを書く技術── 読みやすく保守しやすいプログラミング作法』. 技術評論社.2021年,24p

    View Slide

  7. ”無駄がないコードは理解するのも修正するのも簡単で時間がかからないため、
    良いコードと言えます。”
    無駄な部分がない
    ● ロジックがシンプル
    ● 無駄な重複コードがない
    縣 俊貴.『良いコードを書く技術── 読みやすく保守しやすいプログラミング作法』. 技術評論社.2021年,24p

    View Slide

  8. ”良いコードは適切なパフォーマンスで動作する。
    似たような実装がいくつか考えられるとき、あきらかに効率の悪いものを選択する
    必要はありません。良いコードは適切なパフォーマンスで動作します。”
    効率的に動作する
    賢いアルゴリズムが本当に必要なのか実証的に見極めるのが大事です。大概はシンプルさが勝る。
    必要かどうかはパフォーマンスとの相談。
    この研修ではここには触れません。
    縣 俊貴.『良いコードを書く技術── 読みやすく保守しやすいプログラミング作法』. 技術評論社.2021年,24p

    View Slide

  9. 他に良いコードと言われて浮かぶもの
    ● 誰でも簡単に理解できるようなコードであること(可読性)
    ● 新しい機能を追加することが容易であること(拡張性)
    ● セキュリティが確保されている
    ○ 潜在的な脆弱性がないこと
    簡単に言えば、
    読みやすくて、理解しやすくて、修正しやすいコード
    ● コードスタイルの一貫性を確保する
    ● コードの中に「後でやる」「要修正」などの
    コメントが存在しない
    ● 変数名やコメントのルールが一貫している

    View Slide

  10. 良いコードだと何が良いの?

    View Slide

  11. 良いコードの価値
    継続的かつ迅速にユーザーに価値を届けられる!
    ● 人が入れ替わっても理解しやすい
    ● 機能変更に強い
    ● 修正工数がかからない
    ● バグを生みづらい
    エンジニアとしては
    ● エンジニア信頼性が上がる
    ● 満足感・達成感がある

    View Slide

  12. 悪いコードだと(開発現場でよくあること)
    ● コードを読み解くのに時間がかかる
    ○ 簡単だと思っていた仕様変更やバグ修正に何日も費やす
    ● バグを埋め込みやすくなる
    ○ どこかのコードを変更したら別の箇所でバグが発生
    ● 変更の影響がありそうな箇所を探し回る

    View Slide

  13. なぜ良いコードを書くべきか
    ● 現場ではチーム開発することが基本
    ○ コードを読まれることの方が圧倒的に多い
    ● リリースが遅れて機会を逃す
    ● バグが多いサービスはユーザーが離れる

    View Slide

  14. コードを読みやすくする

    View Slide

  15. 意味不明なネーミング
    ● 意図が全く読み取れない
    ● 読み解くのに時間がかかっ
    て、中途半端に変更してバ
    グに繋がる
    連番命名
    意図がわかる名前を使う

    View Slide

  16. 意図がわかる名前を使う
    縣 俊貴.『良いコードを書く技術』. 技術評論社.2021年,58p

    View Slide

  17. 良い名前の条件
    短すぎず、長すぎず、説明的で意味・意図を表現している変数名、メソッド名、
    クラス名は、名前がその中身を正しく表現していて、名前を見るだけでその役割
    を理解できる。
    良い名前はコードの理解がしやすいが、悪い名前は読む人を混乱させて、勘違い
    を生み、バグの発生につながる。

    View Slide

  18. 意図がわかる名前を使う
    何の計算なのかわからない

    View Slide

  19. コメントで対応するのは不適切
    コメントやドキュメントを追加するのも改善方法の一つだが、かなり乱雑な
    コードになるので良くない。

    View Slide

  20. 名前をわかりやすくする
    変数の意味がコードだけで分かるのでコメントも不要

    View Slide

  21. コメントは適切に使う
    書きすぎないこと。基本は書かない方が良いです。
    ● ロジックの内容を説明するだけのコメントはしない
    ● メソッド名をわかりやすくするなど、ロジックを理解しやすいようにした方が良い
    コード理解の助けになる場合に書くと良いです。
    これは良くないパターン
    (見ればわかるロジックをただ説
    明しているだけ)

    View Slide

  22. 必要なコメントは書こう
    コードだけでは意図がわからない場合はコメントしておくと良いです。
    ● なぜこの分岐を作らないのか、なぜこういう計算をしているのか
    ● ライブラリのバグなどで特殊な対応をしている場合
    ● 難しい前提知識が必要な場合
    @t_wada, https://twitter.com/t_wada/status/904916106153828352, 2017年9月5日

    View Slide

  23. ドキュメントコメント
    TypeScriptでは型情報を記載できるので、わざわざJSDocコメントに型情
    報を記述する必要はないです。(jsでは有用)

    View Slide

  24. 名前は基本的に省略しない
    昔は省略することが多かった(諸々の制約があり、そもそも言語仕様で長い変数
    名が許容されなかった)が、最近はエディタの入力補完などもちゃんとしてるの
    で、省略しない方が良いです。
    for文のi, j, kや例外のeなど、慣習的でプログラマなら理解できる場合、むしろ省
    略することもある。

    View Slide

  25. 名前に一貫性があるとよい
    ● 対称性を保つ
    ○ begin/end、write/read、on/offなど
    ● 単語の組み合わせ方を一貫させる
    ○ scoreAvg、scoreAverage、avgScoreなどを同時に使用しないなど

    View Slide

  26. 英語で命名されていること
    ● 和製英語を使わない
    ● スペルミスに注意
    ● 誤訳に注意
    VS CodeならCode Spell Checkerのようにタイポを発見してくれるツールもある
    昔見たことあるのは、記事が保存さ
    れるテーブルで、名称はkijis

    View Slide

  27. メソッド名の名前について
    良いメソッド名は、名前から機能が想像できる。
    逆に名前から想像できないことはしない。getterであれば、副作用はあってはい
    けない。
    メソッドは処理を行うので、メソッド名は「動詞」または「動詞」+「目的語」
    になっていることが多い。

    View Slide

  28. 変数の使い回しをしない
    コードの途中で変数の用途が変わってしまい、読み手が混乱してバグを埋め込ん
    でしまう可能性がある

    View Slide

  29. 変数の使い回しをしない
    それぞれの用途にあった、変数を都度定義する
    ≒変数のスコープを可能な限り狭くする

    View Slide

  30. 関数化する
    計算ロジックをダラダラと書くと、どこまでが何の処理なのか分からなくなってくるため、
    小さな関数を組み合わせることによって、表現がわかりやすくなる。

    View Slide

  31. 種類の異なる処理をそれぞれ関数として分離したことで、違う処理が紛れ込みにくくなり、
    複雑な処理も理解しやすくなりました。
    関数化の目安は画面に収まりきる程度、30行程度が目安になるのではないかと思います。
    (処理の内容によるが・・・)
    関数化する

    View Slide

  32. スコープって何?
    プログラミングにおけるスコープ(英:scope,可視範囲)とは、変数や関数などを参照できる
    範囲のこと。通常、変数や関数が定義されたスコープの外側からは、それらの名前を用いる
    だけでは参照できない。このときこれらの変数や関数は「スコープ外」である、あるいは
    「見えない」といわれる。(Wikipedia)
    スコープ=見える範囲=使える範囲=依存する範囲=保守性に影響を与える範囲
    = スコープ狭い方が良い
    スコープ_(プログラミング) . Wikipedia. https://ja.wikipedia.org/wiki/スコープ_(プログラミング)

    View Slide

  33. スコープが広い例(NG)
    グローバルスコープの例
    グローバルスコープにxを定義して、foo関数内でxを参照
    して、bar関数内でxを再定義しています。
    foo関数はその関数自身のスコープでxを定義していない
    ため、スコープチェーンを使用してグローバルスコープ
    からxを参照するので、bar関数の実行結果は10になる

    View Slide

  34. スコープが狭い例(OK)
    このコードでは、foo関数は引数xを受け取り、bar関数内
    で定義された変数xをfoo関数に渡しています。foo関数は
    bar関数で定義された20を出力します。
    ローカルスコープに変数を限定することで、予期しない
    結果を避けることができます。
    関数の中だけ、ループ処理の中だけといったように、
    できる限り変数の利用範囲は狭くしましょう。

    View Slide

  35. コードの行数にこだわらない
    一般的にコードの行数は少ないほど良いと言えます。
    ただし、分かりやすさ、誤解されづらさも大事なことなので、簡潔だが理解でき
    ないコードは避ける。

    View Slide

  36. コーディングルールに従う
    それぞれのプロジェクトでコーディング標準や命名規約を定めてチームメンバー
    全員が合わせていくことが重要。
    各プログラミング言語のコーディング標準も公開されています。
    https://qiita.com/moaible/items/134329123074337913fb

    View Slide

  37. ネストの深いコードは避ける
    if文, for文などの制御構文で入れ子構造になっているとき、ネストしていると呼ぶ。
    何重もの入れ子構造になっていることをネストが深いと言ったりします。

    View Slide

  38. コードの見通しが悪くなる
    ● どこからどこまでがif文の処理ブロック({}中
    括弧でくくられた処理範囲)なのか、読み解
    くのが難しくなる。仕様変更が辛い。
    深くネストしたコードは読みにくい

    View Slide

  39. ガード節(早期return)
    メインフローとは独立した事前条件を満たしていない場合、すぐにreturnで抜けるこ
    とで、メインフローの独立性を高めてシンプルな記述にできる。
    ネストが解消されて、ロジックの見通しも良くなる。
    ネストが深い場合多くの処理をやり過ぎていることも多いので、関数に分割したりす

    View Slide

  40. 自前で処理を作成
    配列にtokyoが含まれているか判定するコード
    以下のコードは配列にtokyoが含まれているか判定するコード
    標準ライブラリで同様の処理を行う関数があるにも関わらず、自前で処理を書いてしまって
    いる

    View Slide

  41. 自分が使う言語の標準ライブラリ、フレームワークは把握しておきましょう。
    自前で処理を作成
    someを使えば、ワンラインで実装できる

    View Slide

  42. 関数の呼び出しを読みやすくする
    関数に適切な名前がつけられていれば、何の関数なのか分かりやすいですが、
    引数の目的・機能が明確でないと理解するのが大変になります。
    ● 引数は不変にする
    ● フラグ引数は使わない
    ● 引数はできるだけ少なくする

    View Slide

  43. 引数は不変にする
    引数を変更すると値の意味が変わり、どんな意味なのか推測が困難になります。
    また、どこで変更されたのかわかりにくくなるので、引数は不変にする。

    View Slide

  44. フラグ引数は避ける 
    メソッド内部の機能を切り替えるために渡すBoolean型の引数のこと
    呼び出し側からは何をしているのかわからないので、メソッドを分割した方が良
    い。

    View Slide

  45. 引数はできるだけ少なくする
    引数は可能な限り少なくなるよう設計するのが良いです。
    多くの引数を使いたいメソッドは処理内容が増大するのでロジックが複雑化す
    る。引数の管理も重くなる。
    引数が多くなりそうな場合は、メソッドの分割、オブジェクト引数にする、別ク
    ラスへの分割する、などを検討します。
    オブジェクト引数への変更

    View Slide

  46. デッドコード
    どんな条件でも到達しないコードのこと
    ● 可読性低下
    ● なぜ残ってるのか分からず勝手に削
    除するのが怖い
    ● 仕様変更で到達可能になってバグに
    なるかもしれない

    View Slide

  47. 必要になった時だけ実装する
    ● 今現在必要性がないのに、将来必要
    になるかもしれない、などといった
    見込みや思い込みで機能を追加する
    ことはやめておきましょう。
    ● 予想や見込みで追加された機能は使
    われないまま 放 置 されることが 多
    く、そもそも正しい機 能なのかも分
    からない。

    View Slide

  48. マジックナンバー
    ロジック内に直接書き込まれる意図がわ
    からない数値。重複するなら定数化しま
    しょう。
    意図が明確な場所では、そのまま入れて
    も問題はないです。
    app.listen(3000)など

    View Slide

  49. 例外の握り潰しはしない
    安易にtry, catchを使わない。
    例外を握り潰すことになってしまうので、使う場合は再スローなどする。
    NG OK

    View Slide

  50. リファクタリング
    メンテナンスしやすくなるように、ソースコードを書き換えていく作業のこと
    リファクタリングをする時は
    ● リファクタリングと機能改変を同時には行わない。リファクタリングをしてから新しい機能を追加
    する。
    ● テストの追加をしない(テストケース漏れの追加, インターフェース変更への対象は例外)
    ● リファクタリングを始める前と後にはユニットテストを実行しコードの機能が変更ないかを確認す
    る。
    ● パフォーマンスよりもメンテナンス性を重視する。
    ● 小さなリファクタリングとテストの組み合わせを繰り返す。一度に大きなリファクタリングをしな
    い。

    View Slide

  51. Eslint, Prettierを使う
    ESlintを導入することで、単純な構文エラーやプロジェクト固有のコーディング
    ルールを定義することで、複数人で開発する場合でもシステム全体のコードの一
    貫性を維持することができる。
    コードフォーマッター(ソースコードを整形してくれるツール)のPrettierも併用
    することでより一貫性を保てるので積極的に使って良いと思います。
    Eslint導入する一択で良い

    View Slide

  52. テストコードは書こう
    テストコードを書くことで、仕様変更の影響が把握しやすくなったり、テスト
    コード自体が仕様として機能したり、メリットは多いので、書くようにしましょ
    う。
    安心してリファクタリングもできるようになります。
    詳しくはテストコード研修で実施されます。

    View Slide

  53. 参考書籍
    ● リーダブルコード
    ○ www.amazon.co.jp/dp/4873115655
    ● リファクタリング
    ○ www.amazon.co.jp/dp/4274224546
    ● Clean Architecture
    ○ www.amazon.co.jp/dp/B07FSBHS2V
    ● 良いコード/悪いコードで学ぶ設計入門
    ○ www.amazon.co.jp/dp/4297127830
    ● 良いコードを書く技術
    ○ www.amazon.co.jp/dp/4297120488
    ● Good Code, Bad Code
    ○ www.amazon.co.jp/dp/4798068160

    View Slide