読者です 読者をやめる 読者になる 読者になる

kotlin小ネタ:coding conventions メモ

実際のコーディングで考察した内容を五月雨式にメモ。おいら自身が理解できればOKという最低限の記述。出そろってきたら整理しましょう。
kotlin とか coding conventions とか無関係なメモになってるっすね、、、(´・ω・`)

  • 演算子の優先順位を等価とみなして括弧を利用する。*1
    • 視覚的に理解しやすい。
    • 意図が明確になる。(誤修正されにくくなる)
  • 推移的な情報の使用を可能な限り避ける*2
  • 使命が果たせない状況では実行時例外をスローする。*4
  • クラスの命名はシンプルにする。
    • クラスの命名は、最も小さいかつ整合性のとれた名前空間 *5 に合わせてシンプルなものにする。
    • クラスの利用時にクラスの simpleName の衝突や分かりづらさがある場合は、import で as を使い別名表記する。
  • 関数型のような多段の呼び出しは、保守者が各段の意味を理解しづらいと思える場合は Extract Variable や呼び出し毎にコメントを付けるなどの対応をする。
  • fun/get()/set() では {} を使用する。
    • IDE 上で collapse するとシンプルに表示できる。
    • 型の記述がコンパイラレベル強制される。
    • "=" と "{}" の混在する不揃い感が美しくない。主観の問題だけでなく不揃いなものを認識する作業は脳への負荷が大きい。*6
    • "=" と "{}" のどちらを利用するべきか考える必要性がなくなり、時間の節約とリファクタリングのピンポン防止になる。
  • backing field を持つ property は this を使わない限り(closure生成を含むもなど)すべて primary constructor の arguments にする。
    • body 内部に記述した場合は property initializer もしくは initializer ブロックで初期化する必要がありクラス階層を縦断した参照を把握する必要があるが、this の参照も可能なため、fun/get()/set()内部からもの参照も含めた事実上全ソースを把握する必要がある。しかし、primary constructor の arguments にした場合は、当該クラスの constructor arguments の順番だけ把握すればよい。
    • kotlin では全ての constructor arguments を評価し終わるまで(つまり instance の生成完了まで)は this の参照ができないため、複雑な過程を経て constructor arguments を作成するような場合の一時的な配置場所が取りづらい。一次変数を constructor argument のデフォルト値として入れ、それを用いて set していくような方法とか、ThreadLocal に値を入れるとか、あまりスマートでない方法をとらざるを得ない。しかし、基本的に参照透明性が得られない状況はほとんどないはずなので、よほど性能要件が厳しい状況でない限りは、毎引数毎に全部計算すればよいと思われ。
  • 現在時刻の扱い
    • 扱う方針はアーキテクチャレベルで設定される。
    • 基本的には controller 的な役割の中で決定する。*7

*1:Extract Variable を用いたほうが保守しやすい場合はそちらを利用する。

*2:各種要件を超えない範囲で可能な限り。

*3:検証内容、実測値、考察など。

*4:使命が果たせない状況が起こり得る場合は設計不備を疑う。例えば、渡されたデータ内容の不備については null safety や validation 済みを保証するカプセル化で対応できることが多い。ユーザーの文字列入力など誤入力が織り込み済みの場合はその対応までが使命に含まれる。

*5:この名前空間の単位で module 化するのが理想。現在の開発環境では細かく module に分けるのはコストが大きい(gradleのmoduleとして細かく分けるのは現実的じゃない)ので特定のパッケージをモジュール的に扱うことも多いと思われる。

*6:表形式のほうがCSV形式より見やすいことが多いのと同じ。

*7:WebApplication の controller の場合は ThreadLocal に時刻情報が含まれる保証をしてしまえばよいし、Android の ui なら mainLooper のコールバックで値を設定するようにすればよい。その他の場合でもMVC系の設計の場合は controller で取得した時刻をバケツリレーすると決めてしまうとラクチン。