日々常々

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

量に量で対抗しない方法を身につける

ビッグデータとかそういう話ではないです。

チキンカウント

……って言葉があるはずなんだけど、検索しても出てこない。誰に聞いたんだっけ。 「鶏は三歩歩くと忘れる」ってことわざに由来するのだけど、これ自体日本のことわざっぽいし、何かの勘違い……?

とりあえず3を超えると数えられないので、個々として扱う上限を2とする。みたいな。

他に似た言葉だと「三振制」とか使います。共通化を検討するのは三度出てきてからって言う、どちらかと言うと早すぎる共通化を押し留める言葉だけど、三度出てきたらアウトなんで共通化しないとねーと。 ツーストライクまでは強振していい。と言う局面もある。ツーストライクに追い込まれる前にってのもあるので、どれも状況次第で使い分けなんだけど。

同程度の数を扱うものでDRYとかもあります。DRYは二度出てきた時点で繰り返しですが、Yourselfかどうかの識別が結構難しいので、コードの上っ面だけで語るものではないと思ったり。

量との取っ組み合い

システム開発は量と取っ組み合いです。

多くの処理対象に同様の処理を行って期待する結果を出すものを開発するのがシステム開発だと言っていいと思う。 同じ条件だったら同じ結果を出すのがシステムは得意なわけだし、よく使われる文脈昔から今もこの辺のはず。 違う文脈のシステムもあるけど、それは一旦横に置いておいて。

量に対して仕組みで対抗するのがシステム開発である。これは前提。 前提なんですが、こと自身の仕事になった時に、なぜか量のまま対抗しようとするのをよく見ます。

なんで最初にチキンカウントに触れたかと言うと、「量が多い」の基準です。 なんか10とか20くらいまで我慢して「まだ(手作業で)なんとかなる」って言うの。 そう言う世界もあるんだけど、システム開発の文脈ではそうではないと思うのです。 量が多いってのは二桁とか三桁とかでなく、マジカルナンバー(7±2)でもなく、チキンカウントで数えられなくなったくらい。つまり3以上を指すわけです。 量が多いもので溢れてますね。

量に量で対抗するのを避ける

量のまま対抗するって表現は、量が多いのを作業量に結びつけてしまうことです。 何かタスクをやる時に「数が多いので時間がかかる」と言うのが典型的。いやいや、「数が多い」と「時間がかかる」は直接は結びつかないよ?って思うんだけど、数が多いことと時間がかかることを結びつけることに当人も周囲も違和感が無いようで。

簡単な例だと、コードの出現箇所をgrepして書き直すようなもの。それも何箇所も。やったことあると思います。1箇所ずつ丁寧にやるのが量を量のまま扱ってるもので、量で対抗するには仕組みで対抗する。

例えば二度と同じ作業をせずに済むようにする。構造化と言ってもいいし、単一責任原則だとか言ってもいい、リファクタリングでの重複の排除だと言ってもいい。呼び方はここではなんでもいい。

例えば機械的に置換する。使うツールはなんでもいい。単にエディタの置換でも、何かしらのコマンドでも、ちょっとしたスクリプトを書くでも。

前者は処理対象自体を減らすアプローチ、後者は作業を減らすアプローチかな。何かしらの抽象概念を持ち込んで量を減らすわけです。

こう言うのは「あたりまえ」と思うのだけれど、案外そうでもないと言うのが私の観測範囲。類友かもしれないけど。 先に挙げたような置換はやってたとしても、少しでも外れたるととたんに量(作業量、労働時間)で対抗しがちに見えるんですよね。

処理対象の量が多いものに、時間をかける作業量で対抗する方法は基本的に精度が低く、その検証も量でやってしまいがちで、往々にして漏れるものです。 どこかのタイミングで量のまま扱うのをやめないと大変なことになります。大変になって、納期などの時間制約に押しつぶされて、後工程を省略したりする。量のまま扱ってたら当然ですよね……

システム開発をやってるんだから、自分たちの日常業務も対象にしていいと思うんです。 医者の不養生、紺屋の白袴に並ぶことわざができる前に(もうあったりして……)なんとかしたい。どうしたらいいんだろう。

自分たちの業務の効率化を考えるのはいい練習になります。費用対効果とかも測りやすいですし、何より実践ですから何かしらのお題が与えられる例題をやるよりよっぽど身になる。 例題とかだと「こうなったら正解」みたいなのがあってわかりやすいかもですが、誰も正解なんて与えてくれないことを生業にしてるんだから例題はほどほどでいいと思うんです。全くいらないとは言わない。

てことで、もしやってないなら、今すぐ自分が量に挑んでるものを別の方法で対処してみよう。きっとうまくいかない。 うまくいくはずがないけれど、Fail CheapやFail Oftenを経験できるし、失敗を糧にする練習にもなるはず。 仕事でも自身の裁量(時間制約など)をそれなりに見ておけば別に難しいことじゃない。

あ、仕組み化したら怒られるとかは別の話です。マクロ使ったらダメとか、そう言うのは別のアプローチが必要です。ここに記すには余白が狭すぎる。

参考文献

この辺にフォーカスした本として挙げるなら、プロダクティブ・プログラマかな。

プロダクティブ・プログラマ -プログラマのための生産性向上術 (THEORY/IN/PRACTICE)

プロダクティブ・プログラマ -プログラマのための生産性向上術 (THEORY/IN/PRACTICE)

Amazonだと中古しかないですが、新品は O'Reillyのストア なら買えるっぽい。

仕組みで量をさばくのに重要なのがソフトウェアの梃子を有効に活用する。UNIXという考え方からです。

UNIXという考え方―その設計思想と哲学

UNIXという考え方―その設計思想と哲学

2020年になろうと言うのに10年前と20年前の本を紹介するのをなんと言うべきか……今時だと別の本あったりするんですかね?でも別に書いてることってそれほど陳腐化してないと思うんですよね。さすがに具体的なツールとかはあれだけど。

言いたいこと

  • 「数が多い」と「時間がかかる」は直接結びつかない
  • 2を超えたら「多い」と言える
  • 数が多いものに時間をかける人間の作業は精度が見込めない
  • 仕組みで対抗しようとする癖をつける
  • やっていないとできるようにならない
  • きっと思ってる以上に仕組みで対抗できるものは多い

私のカウント

チキンカウントとか言っときながら、私のカウントは「ぜろ、いち、いっぱい」だったりします。 二つ以上は集合として扱う。どうも鶏より脳内メモリは少ないようです。

Gradleのタスクは順番ちゃんとしよう

私が雰囲気でGradleを使ってる感がよくわかる。

  • Gradle 6.0.1 と 5.6.4

前置き

とあるタスクを実行するときに clean してコンパイルしてから実行したくて、こんなこと書いてました。

myTask.dependsOn(clean, compileJava, processResources)

opengl-8080さんのQiitaに書いてあるし、たぶんGradle徹底入門にもあったかとおもうけど、dependsOnの引数は実行順を制御しません。 Gradleで実行順を制御したかったら mustRunAftershouldRunAfter を併用するものです。

でもこれで今まで特に問題になったことなかったんですよね……。

起こした問題と原因

なんでこんなことを今更書いてるのかと言うと、以下のように書き直したら一部の環境で動かなくなりました。正確に言うとMacのターミナル上でコマンド叩いた時だけ動きました。

classes.dependsOn(clean)
myTask.dependsOn(classes)

ここでGradleのThe Java Pluginの図を引用。

f:id:irof:20191213161855p:plain

compileJavaprocessResourcesclasses が依存してるからこれで良いかーって。

f:id:irof:20191213163141p:plain

まあダメなんですけどね。clean がいつ実行されるか運に任せ……実際は何かで決まるんだろけど詳細は追っていません。ログ眺めてると個々のタスクの依存関係みながら何度も並び替えしてるっぽくて、結果をみると環境依存でした。

でこれが、CIでコンパイルが落ちる。 ./gradlew build を手元で叩いたら問題なくコンパイルできる。 そしてIntellJのビルド( ./gradlew classes testClasses 相当が実行される )は動かない……クラスあるのにクラスがないって怒られる。よくわからないから放置して寝た(せめて戻せ)。

で翌朝ログを眺めてたら「なんか clean 動くタイミングがおかしいな?」と気づきました。 やっぱ深夜の脳はなんかダメだし、寝起きの脳はとても役立ちますね。

CircleCIでは compileJava -> clean -> processResources -> classes -...-> compileTestJava の順で動いてました。Appveyorはまた別の順番。 IntelliJのビルドは compileJava -> processResources -> clean -> classes -...-> compileTestJava となっており、そりゃクラス(*.javaファイル)あってもクラス(*.class)がコンパイル後に消されてるんだからビルドできないよね。

なお手元の ./gradlew buildclean が一番最初に動いてました。そりゃ動く。

潜在してた問題

ていうか、元のもこうだったわけで。

f:id:irof:20191213165441p:plain

clean がいつ動くかは誰にもわからない。 よく動いてたな?

結局どうしたか

[compileJava, processResources]*.mustRunAfter(clean)
myTask.dependsOn(clean, classes)

f:id:irof:20191213165052p:plain

clean が途中で動いて欲しいことってないし。 classes から mustRunAfter しても意味ないし、並べるしかない気がしたからこんな感じ。

compileJava.dependsOn(clean) とかにしないのは、いつも clean したいかってとそうでもないから避けました。

あと、GradleのIssueに gradle clean build can run clean after tasks that produce output by depending on other tasks #2488 とかありました。問題になるのはmulti-projectの時だけなのかな。

モデリングのきほん

関西Javaエンジニアの会10周年イベント、 KanJava 10th Anniversary Partyモデリングの話をしました。

話したこと

モデリングモデリングしたモデルでモデリングを説明してみました。図の書き方とか言葉の抽出とかそう言う話ではありません。「なんちゃらモデリングをうまくやる方法」みたいなのを期待された方はすみません。でも延長線上にはあると思います。

私の中のモデリングは、対象から使わない情報を削ぎ落とし、対象の特定部分を強調することです。 モデルのモデルを 26ページ で描いてみました。 この図単体では伝わり難いと思いますが、図単独で成立するモデルではなくセッションも含めてのモデルなので雰囲気で見てください。

モデリングのポイントとして 54ページ で「同じことは同じように表現する」と挙げています。「同じことは同じように表現する」は手段で、原則は「情報を維持して表現を減らす」です。 例えば楕円を使うなら、そのモデル内での楕円は同じ意味で使う。同じものを楕円にしたり長方形にしたりしない。違うもの、つまり違いをそのモデルで表現しようとしたこと同士を楕円にしない。これは言葉の揺れも同じです。

モデリングの目的は使えるモデルを作ること( 34ページ )。わざわざモデルを作る以上、何かに使うはずです。なのでモデリングを行う際は使い方に焦点を当てます。

モデルを他人に伝えるために使うとしましょう。モデルを使えば伝わりやすいというのは経験があるかと思いますが、モデルは43ページのようにそのモデルで使わない情報を削ぎ落としたものなので、削ぎ落とした部分が気になってしまうと理解しづらいかったりもします。「あのことを考えなくていいのはなんでだろう」とか。この場合はモデルを使って伝える前に、会話などで目的を説明します。このような場の整えもモデリングなんのですが、メタメタして意味がわからなくなってくるので、それっぽいところで折り合いをつけます。それっぽいところは伝える相手との関係を含めていい感じにモデリングしてください。

あと、21ページ に挙げてますが、モデルは決して図ではありません。私の中ではスライドもモデルですし、このブログの文章もモデルです( 61ページ )。 22ページ に目に見えないモデルもある、みたいなことを描いてみましたが、正直これはうまく描けていません。脳内モデルとかをプロットしたら良かったかなーと思いつつ、うまく描けなかったんだから仕方ありません。

ともかく、「モデリングができない」なんてことはないと思っています。 「使いやすいモデルが作れない」はあるかもしれませんが、「なんでもモデリングだ」と思えばいくらでも実践機会はあります。 練習ではなく実践なので、やってるうちに使いやすいモデルを作る力も付いてきますし、モデルを使う力も付いてきます。

モデリングは難しいからできない」が「モデリングやってるけど難しい」になったら、本セッションの目的は達成です。難しいものは難しい。

イベントについて

今回は Mix Leap Studyさんとの共催と言う形でさせていただきました。ありがとうございます。

orange_cloverさんが togetter まとめてくれてます。シングルトラックかつセッションごとに見出し入れてくれてるので追いやすい。ありがとうございます。

関ジャバ10周年ということで、関ジャバ運営 + 設立メンバー全員がセッションしました。特にテーマも設けず、各々が話たいことを話したらこんな感じになりました。 関ジャバっぽかったと思います。半分以上Java関係ないセッションでしたが、関ジャバはJavaエンジニアのためのコミュニティなのでJavaの話をする必要はないのです。

思い返せば関ジャバでの私の初セッションは多分 関西Javaエンジニアの会(関ジャバ) '11 9月度 で、この時もJavaに関係のない夜行バスの話とかしてました。同年7月の関ジャバカンファレンス2011でLTとかもしてたりするんですが、そっちはLTなのでノーカン。カウントしたとしてもGroovyの話だけど。

これからもぼちぼち活動すると思うので、よろしくお願いします。