B-Teck!

お仕事からゲームまで幅広く

【本】リーダブルコードを読んだ

リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック (Theory in practice)

リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック (Theory in practice)

ずっと積んでいたんだけどようやく読み終えた。
書いて有ることは普段意識していることや、心がけていることも多かったけれど、
改めて考える・意識するきっかけとして良い本だった。
忘れた頃に読み返して、都度気持ちを引き締める用途にいいかも。

以下各章の自分用メモ。

1 理解しやすいコード

  • 理解しやすいコードは優れたコード
  • 短いことは理解の助けになるが、難解になる場合は冗長になっても理解しやすさを取る

2 名前に情報を詰め込む/3 誤解されない名前

  • 汎用的な名前ではなく、具体的で誤解を生むことのない明確な単語を利用して名前を付ける
    GetではなくFetchやDownload、tmpやretValではなく、何を表した値か等
    小さいスコープなら短い名前で良い
    命名の方法、長さなどのフォーマットを決め、メンバ変数や引数、定数などに差をつけると見やすい

4 美しさ

  • コードの見た目が揃っていることで間違いや違和感に気付きやすくなる
  • 重複を削除することで見る範囲が減る
  • 宣言や実装をブロックごとにまとめて分割する
  • 複数の箇所で同一の流れの処理がある場合、統一されていることで実装・確認がしやすくなる

5 コメントすべきことを知る/6 コメントは正確で簡潔に

  • コードを読んで自明の内容は書く必要がない
    コードを読むよりも理解が早くなるようなコメントのみ残すべきである
    なぜこの実装を選んだのか、改善するべき方針や、使用時に注意するべき点など
  • 定数に数値を設定する場合、コメントを残しておくと実装の意図がわかりやすい
  • ファイルやクラス、関数自体にざっくりとしたコメントを付けることで理解を早くできる
  • コメントを書く場合はなるべく小さく具体的に
  • コメントだけでわかりづらい場合は具体例を書いておく

7 制御フローを読みやすくする

  • 分岐は否定より肯定形を使う
  • 単純な条件や目立つ条件や重要な条件を先に書く
  • 三項演算子は場合によっては理解の助けになるが、過度な使用は読みづらくなる
  • 結果が早く取得できる場合は途中でもreturnする
  • gotoは必要な場合もあるが基本的には使わない
  • ネストはなるべく浅くする

8 巨大な式を分割する

  • 式自体を表す変数を用意する
  • 論理式を読みやすく置き換える(ドモルガンの法則などを用いる)
  • 短絡評価は便利だけど読みづらくなる場合もあるので注意する

9 変数と読みやすさ

  • 不要な変数を削除する
    一度しか使われていない、式を単純化していない、返り値を保持しているだけ...
    処理上で意味をなさない変数は、処理を分割するなどして削除できないか検討するべき
  • 同時に考える変数を少なくする
    変数が参照される範囲を狭めることで、一度に意識しなければならない問題を減らす
    定数にできる変数は定数にして意識する必要をなくす

10 無関係の下位問題を抽出する

  • 大きなコードの中で、単体で完結している処理を分割し別関数として切り出す等
    単体で完結した処理は再利用が行いやすい
    問題を分割して小さくなったコードは目的がわかりやすい
  • 汎用的なコードはプロジェクトに依らない共通部品として切り出す
    次に必要になる場面があった時、実績のある部品を利用することで別の重要な問題に注力できる
  • 複雑な処理を簡易に利用できるインターフェースを作る

11 一度に1つのことを

  • 処理をブロックごとにまとめて、同時に複数のことを行わないようにする
  • 複数の処理を同時に行おうとせず、小さなタスクに分割する

12 コードに思いを込める

  • 人に説明するように変数や処理の流れを置き換えることで、自然でわかりやすいコードになる
    明確で、人の理解しやすい流れを意識する

13 短いコードを書く

  • 実装時点で必要の無いコードは書かない
  • 前提条件と求めることを明確にすることで問題が単純になることがある
  • ソースコードを小さく保つことで、全体を俯瞰できる状態を維持する
  • ライブラリを知っておくことで、車輪の再発明や無駄な処理の実装を避けることができる

14 テストと読みやすさ

  • テストコードを小さく、読みやすい状態に保ち、変更に耐えられるようにする
  • エラーメッセージをわかりやすく書くことで、必要になった時に役に立つ
  • 入力値を単純化し、適切な値でテストできるよう意識する
    テストする機能が複雑な場合など、必要があれば複数のケースでテストコードを記述する
  • テストメソッドはテストの内容がわかるような名前にする
  • テストを見据えた開発を行うことで、テストがしやすいコードになり、品質が上がる
    依存や副作用が多い関数、必ず同じ状態にならないような実装を避ける
    テスト駆動開発なども考慮にいれる
    テストのために実装を犠牲にする必要はない

15 「分/時間カウンタ」を設計・実装する

  • 問題が発生した時、素朴な解決策から試す
  • 素朴な解決策から改善策を考案し、試す

リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック (Theory in practice)

リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック (Theory in practice)

【Javascript】連想配列の値やキーに特定の値が存在するか調べる

var Country= {
  "Japan": "日本",
  "China": "中国",
  "Korea": "韓国",
  "Vietnam": "越南"
};

function getHashProperties(a){
  let r = [];
  for(let v in a){
    if(a.hasOwnProperty(v))
      r.push(a[v]);
  }
  return r;
}

// 入力したオブジェクトのプロパティの値を配列に展開する
// -> Array [ "日本", "中国", "韓国", "越南" ]
console.log(getHashProperties(Country));

// includesで戻り値配列の中に値が存在するかを確認できる
// -> true
// -> false
console.log(getHashProperties(Country).includes('日本'));
console.log(getHashProperties(Country).includes('Japan'));

// indexOfでも当然判定できる
// -> 3
// -> -1
console.log(getHashProperties(Country).indexOf('越南'));
console.log(getHashProperties(Country).indexOf('Vietnam'));

// 特定の名前のプロパティが存在するかは下記で判断できる
console.log(('China' in Country));
console.log(('韓国' in Country));

【デザインパターン】デザインパターンの勉強中メモ 生成に関するパターン

AbstractFactory

Factory Methodの概念の進化系という感じ。
Factory MethodがスーパークラスのメソッドとしてFactoryを定義するのに対して、
AbstractFactoryではFactoryを束ねたクラスを作成する。

1つの処理に関連するクラス群のFactoryを束ね、抽象化することで、
処理の単位でクラスを置き換える事ができる。

Builder

オブジェクトの生成に準備と特定の手順が必要な場合、
コンストラクタのみで記述するには責任範囲が広くなってしまうので、
準備するクラスをBuilderクラス、手順を定義するクラスをDirectorクラスとして分割して定義する。
Builder・Directorそれぞれに利用するためのインターフェースを用意することで、
様々な組み合わせを同じ手順で実行することができる。

FactoryMethod

オブジェクトの生成をサブクラスに任せることで、
生成するインスタンスを選択できるようにするパターン。

スーパークラスで定義された処理をサブクラスで生成したオブジェクトで行う場合や、
特定のスーパークラスを持ったオブジェクトを生成する手順を複数提供したい場合に利用する。

Prototype

あるオブジェクトを生成するために必要な手順がある時、
すでに手順を実行して生成されたインスタンスを用意し、
そのインスタンスを複製可能な実装にする。

次に同じオブジェクトを利用したい場合は複製して使うことで、
生成の手順をスキップできる。

Singleton

あるオブジェクトについて、インスタンスが1つのみであることを保証するパターン。

複数のインスタンスを生成したくないオブジェクトが存在した時、
インスタンスの生成/呼び出しを行う共通のメソッドを作成し、
インスタンスが既に存在すれば生成済みのインスタンスを利用し、
存在しなければ新しいインスタンスを生成することで、
常に単一のインスタンスのみが存在する状態を保つ。