Hash λ Bye

Haskell, Clojure, MLなどの話

コードを書く時の生産性の低さに気付く

大して複雑なコードでもないのに、スクリプト書くのに3時間もかかった話。

問題

仕事で必要になりそうなスクリプトを書いてた。 公開できないけど。

以降に説明するような処理をするClojureスクリプトを書いていたが、 あらかた満足に動くようになるまで3時間もかかってしまった。

時間かかりすぎ、と思った。 ちゃんと設計や実装の戦略を仕込んでおけば半分の時間でできそうだなと、雑ながら感じている。

概要

ログの解析をおこなう。

JSON形式で出力されるログを走査して、 各種データの処理開始と処理終了のログを見つけたら、 そのログをペアリングして経過時間を計算する。

そのように各種データがそれぞれどのくらい時間かかっているのかをログから集計する。

一般的な処理ステップ

  • ログを読んでJSONデータ構造に復元
  • データの正規化
  • 処理の開始、終了にまとめる
  • 集計処理

シンプルだ

分析

どこに時間がかかっているのか?

体感

ソースにしているログのデータにばらつきがあったので、意外とコーナーケースの発見に時間がかかった。 pringデバッグしながらやっていたのでそれで時間くった気がする。

なのでログの解析(parsing)だけで2時間かかってたかもしれない。

何故時間がかかったのか?

なんでだろう。

  1. ゴミデータ、はずれデータが原因で動かない時のデバッグ
  2. API誤解したまま使って、predicateが逆に動いていたり

ふーん。

あ、あともう一個。

比較的大きめに関数を組んでから実行して、動かなくて部品に分解しなおしてデバッグ

これはかなりやり方よくなかったなと思う。 つい小さなパーツでの確認をとばして、どんどん大きい方に結合してからデバッグしちゃう。

小さいスコープ&合成

ということで、いま明確に認識しているのは、 この 小さな部品に分解したあとの小さなテストをしていなかった ところ。

リクスヘッジしてなかったなー。

(ちなみにすごい人はこういうところのリスクヘッジしなくても流れるように正しいコードを書くので基本スキルが違う気がしている)

どうするべきだったのか

実際のデータを使って入出力しつつ、 最小限の部品を入力と出力の間に挟むようにして動作確認していくべきだった。

Step 1

input ---> [ json parsing ] ---> output

Step 2

input ---> [ json parsing ] > [ normalize ] ---> output

Step 3

input ---> [ json parsing ] > [ normalize ] > [ accumlate ] ---> output

こんな感じでpipelineのpassを増やしていくようにして動きを見ていければよかったなーと。 テスト自体もプログラム本体の成長に従って修正されていくTDD的なやり方だったらよかったのかもしれない。

次のアクション

計測

時間を測ろう。

なんの機能あるいはどのステップの実装にどれくらい時間がかかっているかを知る必要がある。

gitのcommitのタイムスタンプから測れるかな。 でもsquashすると解らなくなるので、割とこまめに計測した方が良さそう。

pomodoro techniqueベースで時間管理することが多いから、 pomodoro timerの終わりでcommitするのが良いか。

練習

もっとたくさんプログラミングの練習をしたいな、と思った。

プログラムの速度よりは、振る舞いを実現できるか、というような機能要件にフォーカスしたい。 プログラムの効率・性能はそれから改善していけるので、まずはナイーブでも短い時間で実装できるスキルを磨きたい。

どんな問題を解くか?

どんな問題がいいかなー。

と考えた結果、手元にあってある程度現実的な問題を含む、『珠玉のプログラミング』でも読んで解いてみようかな。

読書

テスト駆動開発』もういちど読みつつ、 実践交えてやりたいな。