by shigemk2

当面は技術的なことしか書かない

memo Readable Scala #ScalaMatsuri

the theme of this session

scalaのコードをリーダブルにすること

リーダブルとは

  • 定義は人によりけり
  • the art of readable codeから

  • 他の人が態短時間で理解できること

    • 未来の自分も含む
  • 2つコードがあって、読み手がより短い時間で理解できること

    • どちらも理解できることが前提
    • ただし、知らないパラダイムやイディオムが存在することは無視する
    • いろいろなパラダイムを導入することは重要とする
    • パラダイムの導入はチームビルディングによる
    • 故にチームビルディングや技術の導入は別の問題

Scalaは記号が多くて読みづらい

  • よく言われるけど本当にそうなのか
  • 公式のFAQから。全部で10-20くらい
    • 論理演算子/算術演算子も個別に定義されているJavaより少ない
  • ユーザーが自由に定義できる
  • Google検索よりもAPIドキュメントを読むほうが理解が進む
  • もしくはScapsを使う

記号を使うと読みづらくなるのか

  • どちらが読みやすいか

  • 例 読みやすいコード

    • multiply()
    • multiply
    • 記号だけ
  • 例: バトル関数

    • attack
    • ==!!!**>>>
  • 記号メソッドは中置演算子として使われる

  • 人間の目は空白を起点とする
  • 他の識別子が目立った形となる

  • 記号の意味を読み手に十分に認知している場合 − すぐ読める

  • 記号の意味を読み手に十分に認知していない場合 − 読むのに時間がかかる

読みやすさは読み手の知識に依存する

  • 読み手がエキスパートなら記号を多用しても良い
  • 前提知識がないのであれば、記号識別子の利用は控えたほうがいい

まとめ1

  • 特別な意味を持つ記号は少ない
  • 記号識別子は式を区切り、他の識別子を目立たせる
  • 多くの人が読めない識別子は多用しないほうがいい

implicit

  • もっとも誤解を受けやすい機能
  • implicit conversionをまっさきに思い浮かべるだろうけど、一旦忘れる
  • implicit parameterのはなしをする

implicit parameter

  • implicit就職し
  • メソッド呼び出しでimplicitな値をコンパイラが補う
  • スコープ中に型が一致する値が存在しない
  • 複数存在しているとエラーになる

  • 定義時にimplicit修飾子がついた値

導入の動機

  • 拡張性のあるインターフェイスの提供(日本語でも良くわからない)
  • traitはmixinをクラスの定義と同時に行う
  • 定義を変更できないクラスは自作のtraitをmixinできない
  • 自分がタッチできないクラスはmixingできない

  • メソッドの実装をクラスの定義と分離

    • comparator
  • 値を定義すればいいだけ
  • mixinと変わらない使い勝手になる

  • implicitの利用 howとwhatの分離

  • comparator

  • comparatorがimplicit parameterでないばあい

  • valuesのソートなのにcomparatorの合成をやってしまい巨大なコードの意図が埋もれる
  • sort(values)
  • やりたいことが最短で把握できる
  • howがコード上にあらわれているほうが読みやすいという人もいる
  • プログラミングの歴史はhowの隠蔽してwhatを端的に表現するようにするかの歴史
  • howとwhatの分離により、コード上の表現と目的を端的に示すことが出来る要因あるので、コードの意図を短時間で読めるように出来る
    • 不具合調査やパフォーマンスチューニングではhowが重要な関心事となる
    • howとwhatが分離していることでビジネスロジックに影響を与えずに最適化できる
  • implcitな値が直感的あるいは自明の定義になっている必要がある
  • comparatorの定義が直感と反する定義にされていた場合読み手の意図は崩壊する

自明な定義

  • 自明な定義とは
  • 抽象化を行うことで自明な定義を導出できる
  • すべての戻り値をリピートした文字列
  • 型引数を用いて抽象化する 抽象化することで型から定義が自明になった
  • 再利用性だけじゃない
  • howは自明な定義になっていること
  • 抽象化(e.g.型引数)を使うことで自明な定義を増やせる

implicit conversion

  • implicit conversionはimplicit parameterの特殊形
  • A => B 型の特殊対応
  • implicitな値を定義する際はメソッドでも構わない
  • 過剰に使われがちなのでenrich my libraryパターン以外でのimplicit conversionの積極的な利用は避けるべきであること

enrich my library pattern

  • 追加したいメンバを保持したクラスを定義し、型としてはそのクラスを使わない手法
  • 頻出するのでimplicit classという使い方が存在する
  • Javaのように拡張メソッドを持たない言語の場合、既存のクラスを拡張したいときにsingletonなutilityをつくれる
  • 拡張メソッドにすることで視覚的に分かりやすくなることがある

まとめ2

  • リーダブルコードとは他人が最短時間で内容を理解できるコード
  • scalaの書く機能はコードの意図を端的に示せる
  • リーダブルなコードを書くためにscalaの言語機構を活用しよう