日々常々

ふつうのプログラマがあたりまえにしたいこと。

「あるエンジニアがプログラムを紡いでいく様を見てみる」ライブコーディング・リプレイ

あるエンジニアがプログラムを紡いでいく様を見てみるでしたライブコーディングで言ったことや言わなかったことを書いてみます。

意識してるのは「コードをどまんなかに」です。

speakerdeck.com

……あ、このスライドのブログ書き忘れてた。

スライド中の「えらぶ」はだいたいIDEの機能を指します。なのでライブコーディング中に使用したIDEの機能も挙げようと思います。基本的にデフォルトのつもりだけど、vimとの兼ね合いで変更してるのもあるので、そこはごめんなさい。あとMacです。今回はメソッド抽出とかクラス間移動とかダイナミックなのがなくて地味だけど、便利な子たちなので使ってあげてください。

リプレイ

ってことなので、コミットを追いながらいってみます。私の意図はどの程度コードに残ってるのかなー。

github.com

■最初はREADME

会場で何をするかを話して、READMEに書いてみました。思ったよりもでなくて、参加された方もどう参加したものかと手探りだったんだと思います。

■プロジェクトを作成して動作確認

Javaアプリケーションを作るときにまずやってること - 日々常々 で書いた内容ですね。 見事に 動作しませんでした 。本番あるある。

原因はオフライン時のライブラリ解決です。いつも通りと言いつつネットワークの無い状態なのでいつも通りじゃない。普段と違うことをしたら詰まるのは当たり前です。てことでネットワーク繋げて再開しました。(数時間前にネットワーク切断して素振りした時は大丈夫だったんです。ほんとですよ?)

SpringBootのApplicationクラスを作って実行、動作した、よし。ってところで最初の10分で目標にしてたところをクリア。

使用したIDEの機能

  • 前回 挙げたやつ
  • Alt + Ctrl + R Mainやテストの実行

使用するものの選択

build.gradle に何を使うかを書きます。今回はJava 8、Spring Boot 2.0とJUnit 5、Assert J。

Spring Bootを使うのは後でSpring Shellを使おうと思っていたと言うのもありますが、Isolating the Domainに準じて作るつもりだったので。

■パッケージ名変更

前段であがった「 tododototypoしている」の指摘はあえてスルーしてました。typoを直すよりも動作確認を優先したかったからです。仮にtypoを直したとしても動作しなきゃ無駄になるし、typoは動作に影響しないことは知っているので、後回しです。動作確認ができたので、ここでリネーム。もちろんリネーム後はアプリケーションを実行して確認します。

新たに使用したIDEの機能

  • Shift + F6 ファイル名のリネーム
  • Alt + R 前回実行したものの再実行

■初期モデル作成

環境ができたら「TODOリスト」に対して現在捉えてるモデルを書きます。 実装としてはYAGNIですが、ホワイトボードや紙に走り書きするのと同じ感じでラフにコーディング。

f:id:irof:20180308171121p:plain

たまにクラス図を眺めてみたり。この時点で頭の中で描けないようなのは詳細に立ち入りすぎかなーとも思います。

「先に設計しますよね?」

「先にある程度考えてたんですか?当然、普段は先に設計しますよね?」と言った質問がありましたが、冒頭に挙げた通り「コードをどまんなかに」なので、これが初期設計です。その時点でわかっていることを雑にコードで書きます。ただし、この時点はモデルの関連だけ。基本的に操作は書きません。この日は控えめだけど、基本的には認識してるものは全部書くので、もう少し多くなる。かも。

強調しておきますが、これは「初期モデル」です。絶対変わるし、間違ってる。立ち止まって落ち着いて確認する時間は後から何度でも取ります。欲しいのはコードからのフィードバック。間違っても完成と思わないくらいにラフなのを、ささっと短時間で書きます。間違ってたとしてもいいんです。と言うか、間違って捉えてたことのフィードバックを得るために書いてるところがあります。

新たに使用したIDEの機能

  • Alt + Enter (空気読め機能)コンパイルエラーのフィールド型名から新規クラス作成
  • + N コンストラクタ作成
  • Tab 補完
  • + E 最近開いたファイル

■タスクが取れる

TODOリストなんで、タスクがみれなきゃ困ります。 テストから書きたいところですが、テスト対象クラスでテストへ切り替えのキーを押せばテストクラスを作ってくれることは知っています。必ずセットで作るのはわかっているので、テスト対象クラスから作ります。無理矢理テストから作っても遅くなるだけなので。クラスを作り、テストクラスを生成し、テストを書き始める。ファイルの移動も少なくてスムーズです。メソッド名が微妙だなーと思いつつ、REDからGREENへ、とにかく通す。

テストメソッドは忠実にアサートファーストで書きます。だけど先走って型をStringにしてしまって「あれ?」と思ってたら、うらがみさんに突っ込まれました。素直に直したら「感心してたのに・・・」と残念がられました。くそう。

新たに使用したIDEの機能

  • + Shift + T 新規テスト作成
  • test + Tab (LiveTemplate)テストメソッド作成
  • Alt + Enter (空気読め機能)
    • コンパイルエラーのローカル変数名からローカル変数定義作成
    • コンパイルエラーのローカル変数型名から新規クラス作成
    • コンパイルエラーのメソッド呼び出しから対象クラスにメソッド作成
  • TodoService.new + TabPostfix)コンストラクタ呼び出しに変換

■メソッド名変更

スペルチェックで警告だされてるし、それほどこだわりのない名前なので、メソッド名を変えます。割れ窓理論信者なので、コードを健全な状態で保ちたいのです。警告が多いと気づかなくなるのが勿体無い。もしこの名前にこだわりがあるなら、スペル辞書に登録して警告を出なくします。警告が出ている状態はREDに近い扱いですね。

新たに使用したIDEの機能

  • スペルチェック(勝手に波線が出てるだけ)
  • Ctrl + Tリファクタリングメニュー)メソッド名のリネーム
    • Shift + F6 でもいいのだけど、押しにくいので Ctrl + T で選ぶ(と言っても一番上なのでEnter押すだけ)ほうが早い

■タスクが登録できる(RED)

ツッコミがあったところ。賛否両論、と言うか賛はあまりない感じでしたかね。

TODOリストの肝であるタスク登録に着手します。ベイビーステップで行くこともありますが、これくらいならいけるだろうと大きめの歩幅でいきます。ダメだったら戻ればいいんですよ。

まず検証方法を考えます。先ほどとれるようになったタスクをユーザーが見る場合、何かしらの形で文字列化されるはずです。なのでタスクを文字列化したらタスク名が入っている、としましょう。

-        assertThat(actual).isNotNull();
+        assertThat(actual.asText()).contains("yarukoto");

で、これが登録できればいい。タスクを登録する。

+        sut.add(task);

タスクはタスク名をつけて作る。タスク名はさっきアサーションで書いたやつ。

+        Task task = new Task(new TaskName("yarukoto"));

アサートファーストで下から順番。アサート書いて、それを実現するための操作(タスク登録)を書いて、必要な準備(タスク生成)をする。

新たに使用したIDEの機能

  • Alt + Enter (空気読め機能)
    • コンパイルエラーのコンストラクタ呼び出しから対象クラスにコンストラクタ作成
    • コンストラクタの仮引数名からフィールドを作成

「テスト変えちゃうの?」

元のテストを残さずに変更しています。タスク登録してない状態のアサーションがなくなりました。これで「タスク登録しないとnullかもしれない」と疑心暗鬼になれます。

変更してしまう理由はいくつかありますが、まず第一にタスク未登録でnullになるような実装はしないので変更前の検証がエラーになることはありません。基本的に初っ端に書いたクラスやメソッドを導くためのテストは、メンテに向いていません。テストリファクタリングをしてもいいのですが、落ちないテストに価値はありませんし、未登録時のふるまいなんかはそのうちモデルとテストが要求してきます。なので「未登録時はnullでない」程度のテストは維持せず変えちゃうわけです。

ドメインモデルとしては……」

asTextドメインにあるのがおかしい」と言った指摘がありましたが、ドメインは自身が文字列で表現されるときにどうするかを知っていると思います。「メソッド名 asTextドメイン感がない」と言ったところはあるかもしれませんが、妥当な名前が出てくればその時変えればいいです。この時点ではそれなりな名前で十分だと思っています。名前には閉じた世界の中での一貫性が重要で、その検討をするにはドメインの理解や登場するモデルの数が不足しています。この時点でメソッド名の検討は時期尚早。早く作ってフィードバックを得るのが良いです。材料が少ない状態で検討しても的外れになりやすいですし、何より分析麻痺になるのが怖い。よほど精通したドメインでもない限り、モデルが出揃ってない状態で検討できることではありません。

コードスメル: 知識がテストに書かれている

このコードは少し異臭がします。「TaskのコンストラクタがTaskNameを受け取る」と言う知識はテストクラスが持っているべきではないことでしょう。Taskインスタンスの生成方法を知る必要はありません。こう言うのがテストにあると、Taskを要求する全ての場所に同じコードがクローンされます。そこはかとなく臭いので、たぶん近い将来このコードはテストからは消え去ると思われます。でもまだ重複していないので、何かを考えるには時期尚早という判断をします。本当に複数箇所にクローンされるのか、生成のバリエーションが出ないか、などを少し待ってみてもいいかなー、と思ったり。もちろん油断すると大変なことになるので、臭いには気をつける。

■タスクを登録できる(GREEN)

さて、最速でテストを通しましょう。addされたタスクをリストに保持し、asText メソッドはタスクリストを文字列表現すればよい。タスクはタスク名を文字列表現できればよい。タスクの文字列表現は、とりあえず toString でいいや、と。余計な色気は出さず、とにかく最速でGREENにします。(それでもなんか詰まった気がするけど、忘れた。)

実はこの時点でリストを持ち出すのはYAGNIで、テストを通すだけならフィールドで十分だったりします。でも気にせずリストにしちゃいます。フィールドだとnullが登場しかねないから避けたいと言うのもある。リストを導くために複数登録するテストにしちゃうのはありかもだけど、面倒なのでしない。

新たに使用したIDEの機能

  • + Alt + F ローカル変数のフィールド化

「テストの検証が厳密でない」

この実装だと実際の文字列は "[yarukoto]" で、テストの検証は contains("yarukoto") になっていますす。当然 isEqualTo("[yarukoto]") と書いてもテストは通りますが、後者でないことに違和感があったようで、疑問の声がありました。

前段のテストで描いた未来は「登録したタスク名が読み取れる」です。登録した文字列が含まれてればOK。前後に何がついていようと別に困りません。困るのは "yarukoto" を登録したのに "yarukoto" って文字列が見当たらないこと。なので contains を選択しています。Taskのequalsなどで検証していないのは、同じTaskかどうかにあまり興味はないことと、文字列化はアプリケーションに必要なことと、テストのためだけのhashCode/equalsは開発を加速しないからです。

「登録したタスク名が読み取れる」は、おそらく完成したとしても変わりません。テストはピンポイントで重要なところだけ抑えないと、テスト対象をコールタールに沈めて身動き取れないものにしてしまい、開発の足を引っ張ります。例えば仮に isEqualTo("[yarukoto]") としてしまうと、テストが ArrayList の文字列表現に依存します。本来そこに依存関係はないので実装詳細に寄りすぎる検証となり、例えば「改行区切りにしたい」となったら即死です。(「改行区切り」を実現したくなったら、複数件を登録して「改行区切りになるよー」ってテストを書くとは思いますが。)

mdstoy.hatenablog.com

現地ではうまく説明できなかったと思っていたのだけど、存外伝わってたようでほっとしました。

やってみて

ってところで、ちょいちょい説明しながら、ネットワークとキーボードのトラブルもあったけど、合計20分とちょっとかな?最後はSpringShellを紹介するのに使いました。

「説明できるのがいいコード」としょっちゅう言ってる私ですが、だいたいこんな感じで自分に説明(言い訳)はしてる感じです。無意識にやってるものも多いですが、たまに確認はしてます。 でも今回のイベントで他人に説明するのは面白かったです。思った以上に言葉が出てこず、伝わってる感じもしなくて。変なこと言っちゃってるなーと内心ドキドキしながらやってました。

そういえばスライドでは「説明する機会はない」とか言ってたけど、なんかその機会貰えましたね。ありがとうございました。

テスト駆動開発

テスト駆動開発

せっかく買ったし、久々に読み直そう。

Javaアプリケーションを作るときにまずやってること

DevLOVE関西で実験的なイベントをさせてもらいました。

devlove-kansai.doorkeeper.jp

このイベントのおかげで、自分がアプリケーション作るときに最初にどうしてるかを確認できたので晒してみます。誰かの役に立つかどうかは知らない。あ、Macです。ある程度はWindowsでもいけると思うけど、ある程度だと思う。

なおSTSとかIDEのプロジェクト生成機能を使えば一発で済むことだったりする。宗教上の理由で使わないけど。

やってること

基本的にマウスを触る必要はないです。それぞれの詳細は次の通り。長く見えるかもしれませんが、(IDEAの起動とgradleのjarのダウンロード時間を除けば)全部で30秒くらいです。

作業ディレクトリを作る

% git init {作るもの}
% cd {作るもの}

mkdir {作るもの} して cd {作るもの} して git init することもあります。 たまにこの段階で README.md を作ってコミット、ライセンスファイルを作るときはGitHubで作ってからcloneします。

ビルドスクリプトを用意する

記憶かける程度ならそれで。

% vi build.gradle

だいたいこれくらい。たまに cat>build.gradle で書いたりもしますが、気分です。

apply plugin: 'java'
repositories.jcenter()
dependencies {
  testCompile 'junit:junit:4.12'
}

Javaのバージョンやエンコードの設定などが無いですが、一旦作ってから後で変えればいいと思っているのでこだわりません。

これよりも多く書く場合(作るものが決まってるとか)は次のいずれかになります。イベントでは「手元のテンプレートをコピる」をしました。

  • 手元のテンプレートをコピる
  • ググる
  • Spring Initializr

手元のテンプレートをコピる

% cp {テンプレートのあるとこ}/build.gradle ./

ググる

ググって出てきたの(主にGettingStarted)を切り貼りします。

MavenCentralRepositoryを検索

使いたいgroupIdとかがわかっている場合はこっちで検索。

https://mvnrepository.com/

Spring Initializr

https://start.spring.io/

便利ですね。

必要なディレクトリを作る

% mkdir src/main/java src/main/resources src/test/java src/test/resources

これをするエイリアスを作っています。前段のテンプレートをコピるのをあわせたのもあるので、そっちを使うことが多いです。

alias mkjavadirs='mkdir src/main/java src/main/resources src/test/java src/test/resources'
alias initSpringProject='mkjavadirs && cp {テンプレートのあるとこ}/springboot.gradle ./build.gradle'

と言う感じ。

IDEを起動して取り込む

% idea build.gradle

IntelliJコマンドラインランチャーを使います。 Tools / Create Command-Line Launcher から作れるもので、 idea コマンドで新しくプロジェクトが開けます。 コマンドラインラインチャーを作らないなら、IDEAを立ち上げてからOpenでbuild.gradleを選ぶのですが、若干面倒。

テストを書いて実行する

こんな感じのテストを作って実行します。

import org.junit.Test;

public class HogeTest {
    @Test
    public void test() throws Exception {
        
    }
}

即捨てるのでデフォルトパッケージです。確認したいのは環境です。テストが実行できる環境になっているかとか。

面倒に思えるかもしれませんが、テストの作成は以下でできます。

  • Projectの src/test/java ディレクトリを選択
    • [Command]+1 から上下キー、もしくはマウスクリックします
  • [Command]+n で新規のメニューを開いて [Enter]
    • 新規クラス作成のダイアログが出る
  • HogeTest [Enter]
    • クラスができる
  • [Esc]
    • エディタがアクティブになる
  • O
    • 新規行ができる。vimすばらしい。
  • test [Tab]
    • Live Templatesによりテストメソッドが生成される
  • test
    • テストメソッド名を入力
  • [Ctrl]+[Alt]+r [Enter]
    • テストが実行される

キーを押す回数は30回程度、今やってみたら12秒でした。( HgeTest ってtypoったけど。) これをサボると、たまに「なんかビルドできない」とかで悩んだりして馬鹿らしいので、ビルドスクリプトを切り貼りしたときや、環境の更新をした後などは必ずやります。

SpringBootアプリケーションの場合

テストではなく Application クラスで代用します。 起動すれば環境としては問題無いと判断できます。

コミットする

% git add .
% git commit -m"init"

いつでもここに戻ってこれるように。

この段階のリポジトリ

GitHub - irof/DevKan20180305 at a4ccd5d761ccb58cd66bdbec1516cfb2f41852c6

コミットとしてはこの2つ。

さらに前段のことや、周囲のことや、マルチプロジェクトの場合とか、とかとか

WEB+DB PRESS vol.98 「実践!イマドキのビルド環境」に書いてます!

WEB+DB PRESS Vol.98

WEB+DB PRESS Vol.98

Spring Boot Gradle Pluginの話(Spring Boot 1.5.x & Gradle 4.5)

Spring Boot 1.5.x とGradle 4.5 の話です。Spring Boot 2.0とGradle4.6が出たので、埋葬がてら書いておきます。 どんな感じで要らない話になったのかは最後に書いてます。

Spring Boot Gradle Pluginの機能

67. Spring Boot Gradle plugin

たいだい*1 だいたいリファレンスは先頭が重要です。なぜか読み飛ばされがち。コードがあったらそっち読んじゃうのはわかるけど。

The Spring Boot Gradle Plugin provides Spring Boot support in Gradle, allowing you to package executable jar or war archives, run Spring Boot applications and use the dependency management provided by spring-boot-dependencies.

  • allowing you to package executable jar or war archives
    • executable jarを作るための bootRepackage タスクが追加され、 jar タスクの後に自動的に実行されるようになる。
  • run Spring Boot applications
    • bootRun タスクが追加される。
  • use the dependency management provided by spring-boot-dependencies
    • dependencies のうち、Springが管理されるものはバージョンの記述が不要になる。

つまり、プラグインの機能は主に3つ*2ということ。

これからわかるのは、Spring Boot Gradle PluginはSpringBootアプリケーションプロジェクト(Mainクラスが入ってるやつ)には適切だけれど、SpringBootアプリケーションから使用されるモジュールにはdependency management以外は不要なので微妙ってことです。2/3を使ってないわけですからね。

単一モジュールで作っているなら問題にならないだろうけど、共通で使うモジュールとか作る際にうっかり使っちゃうと困ることになる。使わないもの( bootRun タスクがそれ)はまだいいのだけど、勝手に動作する( bootRepackage タスクがそれ)のが問題なのです。

起こりうる問題

たとえばこういう問題が起こります。

  • Main クラスがないのでビルドエラーになる。
  • (仮に最初のを回避したとして)依存ライブラリがjarの中に入る。

他にもあるかもしれないけど、知らない。

対処

  • (だめ) Mainクラスを作る
  • (だめ)bootRepackage.layout = 'MODULE'
  • bootRepackage をしない
  • Dependency management plugin だけ使う

それぞれ書いていきます。

Mainクラスを作る

Mainクラスがないからエラーとか言われるからってMainクラスを作るやつ。要らないもの作っちゃだめですね。

レイアウトをMODULEにする

Mainクラスがなくてもビルドできます。モジュールを作ってるんだからそれっぽく見えるかもしれませんが、jarの中に依存ライブラリがぶっこまれます。そんなjarいらない。無駄にでかくなるし。

bootRepackageしない

そもそもrepackageする必要がないので止めちゃいましょう。

bootRepackage {
    enabled = false
}

シンプルだし、プロジェクトによって使うGradle Pluginを変えなくていいというのはメリットかもしれません。技術スタックは少ない方がいいので。

でも使用しないタスクが入るところは微妙かも。

Dependecy management pluginを使う

Sprign Boot Gradle Pluginは中で Dependency management plugin を使っています。

GitHub - spring-gradle-plugins/dependency-management-plugin: A Gradle plugin that provides Maven-like dependency management functionality

コードではこんな感じでとりこんで、こんな感じspring-boot-starter-parent をインポートしてます。これをDependency management Plugin を使う形で build.gradle に書くとこうなります。

plugins {
    id "io.spring.dependency-management" version "1.0.4.RELEASE"
}

...

dependencyManagement {
    imports {
        mavenBom 'org.springframework.boot:spring-boot-starter-parent:1.5.10.RELEASE'
    }
}

これで余計なタスクも入らない。Spring Bootアプリケーションを作ってるわけではないのだから、たぶんこれでいいはず。

モジュールの独立性とか言ったら(bomとはいえ)SpringBootに依存するのはどうなのとかあるでしょうけど、バージョンの整合性を取るのは面倒だし、自分たちしか使わないモジュールならこれでよかろーです。

Spring Boot 2.0では

マイグレーションガイドに書かれている通り、Spring Boot Gradle Pluginからdependency managementは除外されています。

Spring Boot 2.0 Migration Guide · spring-projects/spring-boot Wiki · GitHub

あと変わったことといえば、Spring BootのリファレンスのSpring Boot Gradle Pluginの記述がスッキリしてます。(最初に出したのと見比べて見てください)

69. Spring Boot Gradle Plugin

リンクされてるSpring Boot Gradle Plugin Reference Guideがしっかりしたものになってる。あとAPIドキュメントもリンクされててて開きやすくなったのも嬉しい。

Gradle 4.6では

Gradle 4.6 Release Notes

BOMをインポートする機能がはいったのでDependency management pluginもいらない。 かも。まだ試してない。

リリースノートに書いてる通り、 settings.gradle に1行いります。

github.com

こんな感じ。

*1:

*2:Agent指定の何かとかエンコーディング変えたりとかもあるのだけど、これらは補助的なものなので書かれてないっぽい。

SpringBoot2.0がリリースされたのでバージョンアップしてみた

spring.io

待望のSpringBoot2.0がリリースされました。 ので早速バージョンアップだー。

やったことといえば、 build.gradle のビルドスクリプトプラグインのバージョンアップだけ。 Spring Boot Gradle Plugin Reference Guide に書いてる通りですね。

- id 'org.springframework.boot' version '1.5.10.RELEASE'
+ id 'org.springframework.boot' version '2.0.0.RELEASE'

そしたら javaio.spring.dependency-management が外れるので、追加。

+ apply plugin: 'java'
+ apply plugin: 'io.spring.dependency-management'

対象のプロジェクトは spring-boot-starter を使ってるだけのやつで、超シンプルなやつなのでこれだけで完了しました。 application.properties にSpringBootのことは書いてなかったんで、そっちがどう変わったかはみてないです。とりあえず軒並みキーは変えなきゃいけないはず。

SpringFrameworkも4から5に上がるわけだけど、コンパイルエラーとかにもなんない。流石にこう言うところは安定してるなー。

変わってたとこ

なんかあったらメモがてら実装してこーかと思って。

github.com

application.properties の空白文字の扱いが変わってた。

プロパティファイルの空白ってどう言う扱いなんだっけなと軽く探してみてみたけど、 Properties (Java Platform SE 8) くらいしか見つけられず。 そもそも Properties#load で読むのと SpringBoot1.5で application.properties を読むのとでも違うので、まあ、うん。

とりあえず application.properties で値に空白文字(スペースやタブ)を使用してたら、 String#trim されるんで消えちゃいます。 これは新しいプロパティを読むクラスで実装されてるので、 PropertyPlaceholderConfigurer. setTrimValues(false) とかしてみても意味ないです。

ちなみにapplication.properties ではなく、コマンドライン引数とか application.yml とか、他の手段で設定すれば特に関係ない話です。 どうしても application.properties でないとダメなんだーとかでもなければそちらで対応できるやつです。

もともとが正しいとも言いづらい(IDEが警告だすような記述なわけだし)ものなんで、仕様外の話かなーと。

ベタープログラマの第一部を読んだ

ベタープログラマ ―優れたプログラマになるための38の考え方とテクニック

ベタープログラマ ―優れたプログラマになるための38の考え方とテクニック

ベタープログラマを読もう - 日々常々で5,6,8,11,13章を読むと書きました。 実際2,4,5,6,8,11,13章を読みました。2つほど増えてますね。

雑感

部タイトル

you.write(code) って codeyou に書かせてる? you は渡された code をそのまま書くのだろうか。仮にそうだとしたら you の型って何なんだ・・・プログラマではなさそう。もし渡した code がそのまま書かれないとしたら write メソッドって名前はどうなのってなっちゃうし。ところで code は誰が生成するんだろう。 you かしら?だとしたら code 生成と codewrite で分かれてる? 流石に code って変数名で型がコード的な何かじゃないってことはないと思うし・・・

2章

vimが最善です。それがすべてです。

のっけからこれ。こう言うことを書いてる本ってのがわかりやすくていいと思います。客観的な正しいっぽいことが書いているのではなく、著者が好きに書いている感じがします。

グッドリフの法則

「コードのレイアウトに関するすべての議論は、白熱すればするほど、ほぼ実りのない議論になる」

そのとおりでございます。

さて2章は「見かけのよい状態」ってのがどう言うものかを書いてます。 前に書いた 見やすいコードのために出来るたった一つのこと - 日々常々 とか、 "ふつうのJavaコーディング"を話しました - 日々常々 で話したことのいくつかとか、普段話してることと被っているものも多くありました。「そーそー、そう。これが前提、このあたりは議論の対象じゃなく、話したいのはこの先なんだー。」と言う感じ。

4章

まだやりすぎてるところ多いなーと思ったり。「結論を出さなくてもいいように、どうとでもなるように実装しておく」ってのは確かにYAGNIではあるなーと。小さいものでも不要な作り込みは不要なわけだし。

実装する前に話すのがいいってのはわかるのだけど、でも机上の空論するなら実装しちゃったもので話したほうがいいよなってのもよくみるので、この辺は意図しての使い分けかなー。

5章

自分の古いコードを読んで、そこから学ぼう、といった趣旨。

思い返してみると、自分の過去書いたコードをみる機会って案外少なかったです。長期プロジェクトは多かったけれど、プロジェクトの間にコードが変わることは少なかったかもしれない。プロジェクトが変わるタイミングでコードも変わってた感じがする。なので以前携わってたプロジェクトのコードを見たときに、ここで書いているような経験になってたかな。git以降は普段のコードを見返す機会も増えた気がする。ここ最近はプロジェクトの切れ目とかは関係なく自分のコードがころころ変わるので、昔よりも実践できてるかもしれない。

そいや昔から言ってるよなーとログ漁ってみたら

それっぽいのがツイッターはじめた年にあったので、もっと前から言ってそう。

あと「過去の自分は遠慮なく叩ける」とかもしょっちゅう言ってる。コードに限らず過去のブログもいい教材になります。

6章

章タイトルが謎だから読もうと思った章ですね。プロジェクトに途中参画するときにどのようにしてコードにたどり着くかって話を「航路の航行」と名付けている。なるほど。

私は途中参画もそうだけど、新規プロジェクトでも地図を描くことが多いです。地図と呼んでいる何か、ではなくて結構それっぽい地図でプロジェクトをあらわしてみる。システムの境界を海岸線であらわしたり、港や崖を描いたり、わかんないところは雲や霧で隠してみたり。傍目は遊んでるように見えたかもしれない。最近はコンテキストマップを描こうとしてる。他の人との会話に使えそうだから。

ソフトウェア考古学

たまに耳にする、具体的にはどういうものか知らない言葉が出てきた。 Wikipediaだと Software archaeology - Wikipedia とかある。まあ考古学って言うのだから、事実から文化とか状況を読み取るって感じなのだろう。メンテナンスの時によくやってるアレのことだと思う。

8章

「エラーへの言い訳」に反論するの、表面的にはできるだろうけど、反論しきろうとすると難しいなと。章タイトルの「そのエラーを無視するな!」から想像していた内容よりも具体的で強い論調だと感じました。この章は読んでみてほしい。

11章

章はじめはテスト駆動開発から入りますが、話は一応テスト全般をスコープにしてる感じです。考える機会になることがいっぱい詰め込まれてます。やはり話題としては自動テストの比重がほとんどですが。

よくある誤りは、五つのメソッドを持つクラスを見て、(略)個別のテストを五つ必要だと考えること

これを明確に「誤り」と言ってるのは初めて見たので印象深かった。理由も添えられていますが、SUTがオブジェクトとしてあまり役に立たないスメルなのかなーというのが感想。

そういえばIDEでテストクラスを生成すると、メソッドに対するテストメソッドが生成されたりしますね。あれでメソッド作ったことないですけど、ああ言う選択肢がでるのがこの辺を助長してるのかもしれない。

てことで

次は二部。そのうち。。

「現場で役立つシステム設計の原則」の感想

目次流しは以前書きましたが、読み終わってるので改めて。

一緒に開発する人には読んでおいてほしい。可能なら手元に置きながら開発してほしい本です。手頃なサイズ、重量、厚さ、価格ですし。鈍器本系に比べれば持ち運びやすい。実際レビューやペアプロの際、「あの本に書いてるんだけど・・・」という感じで何度か参照しています。

読書会をしてみて

4つのイベントに参加しました。うち2つは輪読形式の読書会で、最初から最後まで読み上げです。有用なのと同時に危険でもある、というのが読書会での感想です。

平易な文章で理解しやすいように思えるのですが、表面だけで理解した気になっていると間違いなく実践で役立たない 、そんな感じです。現場での実践をシミュレーションするだけでも多くの問題にぶち当たるでしょう。そういうのがあっさりした言葉でさっくり片付けられています。このようなことを通じて「ただの理想論」と片付けるのは簡単ですが、残念ながら本書の内容は殆どが実践されているものです。特殊な一つのプロジェクトではなく、複数の会社の複数のプロジェクトで。

実践しないとわからないことが膨大にあり、それを乗り越えてようやくさらっと書かれている1文に届く感じです。読み流せば「ふんふん、まあそうだよなー」で片付いてしまい、簡単に誤解できるし、ややもすれば実践不可な理想論にしか映らないのでタチが悪い。これを危険と言わずなんと言うか。。。

読む際に外すと誤解するポイント

この本は徹頭徹尾「変更を楽で安全にする」ことを書いています。

変更しないものには興味がなく、「どう作るか」ではなく「変更のためにどう作るか」が書かれています。書いていること全てが変更ありきなので、変更しないものや変更できないものに適用しようとしても無理があり、解釈が歪みます。(しかも歪んだまま解釈できてしまう。)

どんな本もそうなんですが、書かれていることはたいていそのまま適用できません。現場のコンテキストに応じて調整する必要があり、実践で学べば方針も変える必要が出てきます。その際に変更できるかは重要で、少なくとも変更できるように作っていなければ変更はできません。得た学びを反映するためにも「変更を楽で安全にする」必要があるわけです。

読み終えて

実は書かれている内容をあーだこーだと議論してもあまり意味がない本なのではないかと思いました。議論すべきは、書かれていることを実践した結果の経験に対してです。なのでコンテキストの共有できない状態で会話すると全く実になりません。話すのならば実践経験を語れる場で、できるならば同じ経験を共有した人たちがいいでしょう。そう言う場で実際のコードと本を突き合わせて話すと、短い言葉の随所に詰め込まれた情報がようやく読み取れます。

噛んでたら味が変わる系の本ですね。

おまけ(半年前のLTスライド)

ddd-alliance.connpass.com

このイベントでのスライドです。新幹線の終電に乗ろうとしたら、山手線を逆方向に乗ってしまって帰れませんでした。ドンマイ。

ベタープログラマを読もう

ベタープログラマ ―優れたプログラマになるための38の考え方とテクニック

ベタープログラマ ―優れたプログラマになるための38の考え方とテクニック

読みながらブログを書いてみようと思いたちました。去年ポチって届いたまま積んでた。とりあえず今回は目次流しして、部ごとにブログ書いていこうかなーとか思ってます。思ってるだけかも。

どんな本かというと

コードを気にかける人の姿勢みたいなものかしらね。著者はCodeCraftと同じPeteGoodliffeなので、読んだことがある人は想像できるのかもしれない。

対象はたぶん「この本が気になる人」と幅広い感じ。それだけに専門的ではない(「はじめに」にもそう書いてる)、エモい方の内容なんでしょうね。では目次を読みましょか。

目次流し

5部、38章で構成されています。全章を書きだすのはだるいので、部単位でざっと書いていきます。

第I部 you.write(code)

部タイトルが you.write(code) とコードっぽく書かれてて素敵ですね。最後まで部のタイトルはこれで行って欲しい感がありましたが、残念ながら最初だけです。そういえばサインをお願いするとこのスタイルでメッセージを書いてくれる方がいて、格好いいなーと思ってます。

各章のタイトルはそれ一言で内容がわかり、「そうそう」と言いたくなるもの。4章の「取り除くことでコードを改善する」とかをドヤ顔で言うといいかもしれません。5章の「コードベースの過去の幽霊」なんかは、削除していないコードに悩まされる話*1かと思ったら、サブタイトルに「過去に書いたコードから学ぶ」なのでどうも口寄せとかそんな感じのようです。8章の「そのエラーを無視するな!」などから思うのは、エラーを主体に取り扱うのは解決策を扱う本や記事では取り扱いにくいのか、あまり見ない少ない印象なので特徴と言えるのかもしれない。ここは読もう。

内容が予想しづらいのは6章の「航路を航行する」と11章の「テストの時代」、13章の「二つのシステムの物語」あたり。ということで、5,6,8,11,13章を読もうと思います。

第II部 練習することで完璧になる

練習と言われるとアプレンティスシップパターンの「練習、練習、練習」はいい名付けだなと思い出します。

アプレンティスシップ・パターン ―徒弟制度に学ぶ熟練技術者の技と心得 (THEORY/IN/PRACTICE)

アプレンティスシップ・パターン ―徒弟制度に学ぶ熟練技術者の技と心得 (THEORY/IN/PRACTICE)

練習の方法が書かれているのかなと章タイトルを見て見ると、そうでもなさそう。どうも実戦の中で練習するスタイルのよう?「本番でなければ練習にならない」みたいなことを言ってる方もいらっしゃいますし、それはそれでわかります。隔離されたクリーンな環境での練習は、それはそれで役に立ちますが、予期しないことに極端に弱いものですので。さて、この部は14章の「ソフトウェア開発とは」から始まるので、第I部よりは少し俯瞰した感じ。16章に「単純に保つ」などもありますが、3章にあった「少ないコードを書く」や4章「取り除くことでコードを改善する」を受けて実際どうしていくかとかを書いてそう。19章の「コードを再利用するケース」、再利用はいっとき喧伝されていましたが、悪影響も大きいので取り扱いは慎重になるべきところだと考えています。共通化も同じで、前に書いたエントリ*2とかもその一端ですね。再利用について考察されているものはあまり記憶にないので、ケースが書かれていそうなのは期待。あと気になるのは22章の「凍結されたコードの数奇な人生」かな。コード凍結ってよくあるのだけど、バージョン管理システムを前提としてリリースブランチをもつブランチ戦略をとっていれば不要のはずだし、フィーチャートグルなどの抽象ブランチを活用したアクティブメインラインだと凍結したら開発止まるよなーとか思ってて、そう言う点を整理してくれてるのかなーと。あ、20章に「効果的なバージョンコントロール」があるので、バージョン管理システムの活用は前提、のはず。

17章の「頭を使いなさい」は、うん、まあそう言うことなんだろう。この手の本を読む人に改めて言う必要はあるんだろうか。あれかな、本の内容を真に受けて従えばいいみたいなところへの警鐘?ということで、16,17,19,22章を読みましょかね。

第Ⅲ部 個人的なこと

ふわっとした部タイトルが来た。さて各章は・・・あーうん、エモい。読み物として全体をさらっと読むところな気がする。25章「試験に基づく開発者」は別にテスト駆動開発者のことではなさそう。サブタイトルに自動車運転とか書いてるけど、なにを試験と言ってるのかは気になる。あとは26章「チャレンジを楽しむ」や27章「停滞を避ける」などはテーマとしてはよく言われることで、それに対してどう考えてるかって事が書いてるんだろう。プログラミング言語に対する姿勢についてかかれた29章の「言語への愛」あたりは面白そう。複数言語を学びつつ得意言語があるって人は多いと思うけど、そう言う所も書いてるのかな。得意言語とかを考えると、先にもあげたアプレンティスシップパターンの「得意領域へ撤退」が思い出されます。これもいいネーミング。

ちょっと面白いのが30章の「プログラマの姿勢」で、サブタイトルが「プログラマの健康の改善:姿勢、目の疲労、元気の維持」です。心構え的な姿勢じゃなく、物理的な姿勢のようですね。テスト駆動開発でKentBeckが「Cheap Desk, Nice Chair(いい椅子を買え)」と書いていたのを思い出します。

テスト駆動開発

テスト駆動開発

第Ⅳ部 成し遂げる

この部は31章「一生懸命ではなく、賢く」、32章「完了したときが完了」、33章「今度こそ分かった……」の3章だけです。だけどよく似たような事を人に言ってる気がする(自分できてないくせに)。そんなタイトルが並んでるので、全部読むかな。

第Ⅴ部 人々の営み

チームワークについて、この部も少なくて5章だけです。いずれも気にはなるけれど、特に挙げるなら説明責任について書かれている35章「原因は思考」と、36章の「遠慮なく話す」ですかね。遠慮はチームワークを阻害する害悪で、チームメンバーには「遠慮するのがあなたの仕事ですか?」みたいなことをうっかり言ったりしてました。そのまま言うとどう考えてもパワハラなので、いい方はもう少し考えたほうがいい。ってところで35,36章は読もう。

さー読むぞー

この手の本は前から順番に読むのもいいのだけど、つまみ食いして飛び回る(どうせ各章から他の章への言及があるんでしょ?)のも一つの読み方だと思います。ってことで気になる所をピックアップしてみたけど、どうも半分くらい挙がってますね……。これは上で挙げたのを読み終わったら結局全部読み終えてたりするよーな。まあいいか。

てことでぼちぼち読んでいきます。