コンパイルログとかに何かしら色をつけたい

最近はHaskellの本を読んでいて写経したり色々試したりするのだけど、コンパイルログの見辛さによって、静的型付け言語の強みであるコンパイル時エラー検出の力が出せていないような気がした(ghcに--colorオプションとかある?)。

社内LTもあることだし、自動で色付けするマシーンを作ろうと思いたって作り始めた。テキストに自動で色をつけるというと、テキストをルールでパースして色をつけるというやり方になるかと思う。しかしいちいちパースルールを書くのもだるいし、テキストを適当に標準入力から突っ込むと適当に色付けしてくれるものが欲しい。

自分が知っている自動色付け方法はCoding in colorという、シンタックスハイライトされない部分にも色を付けて見やすくしてやろうというもの。

Coding in color — Hacking Programs : Code, Programming Idea, Tutorial, Showcase, Experience — Medium

function等のキーワード以外の単語を名前順にソートして、予め用意しておいた色のリストに割り当てていくというやり方になっている。例えばtypoしたときに色が違っていたりするので気付きやすいという利点がある。

他にどうやってログに色付けするかも考えつかなかったのでパクろうと思いHaskellで書いてみようとしたが、自分は想像以上にHaskellに精通しておらず、色々調べながら進めていたら就業時間後の2日かけても出来上がらなかった。余談だけど、System.Console.Rainbow (https://github.com/massysett/rainbow) のコードを読むのはMonoidとかを実際に使っていて、初心者には勉強になった。例えば "text" <> blue <> bold で太い青色文字列 "text" を表わすとして、この組み合わせは "text" <> bold <> blue でもいいみたいな。

今すぐHaskell力を上げるのは厳しいことがわかったので、色付けプログラムをRubyで書いてみたらプロトタイプがLT発表日のお昼休みで出来上がった。

https://gist.github.com/jewel12/b33f73635bbbed2b9e97

入力を空白でsplitしていったものを単語として扱っていて、Coding in colorと同じように着色していった結果。

f:id:jewel12:20140520011450p:plain

自分のコンソールではカビが生えたような彩色になってしまった。

元のログはこんな感じ。

f:id:jewel12:20140520014208p:plain

他にも色付けする方法ないかと無い知恵を絞ったところ、語の頻度によって、高頻度になるに連れて色を強調していくという方法をとってみた(逆にどうでも良い語だともとれるので強調しないというのもあり)。

f:id:jewel12:20140520011602p:plain

カビよりも落ち着いた感じになったが、たいして読みやすくなったようには思えない。"Not in Scope"の塊で色がついてるのはいい感じがする。頻度で色付けする方法の辛いところは、テキストファイルを全部読み込まないといけない点で、コンソールに流れるログに色付けはできない。

個人的には色をつけるだけでもなんとなく読みやすくはなったと思う。カッコ内は1語だったり複合語を考慮したりと適切な粒度の塊に色付けすればもっと見やすくなる予感はある。なんか適当に色付け方法を考えて試してみて、偶然いい感じになってくれたらと期待してたけど、まずここに色をつけて欲しいというふうに自分で色付けしてみてから、それに合わせて色付け作戦を練っていくアプローチが真っ当だったっぽい。

ご意見ご感想お待ちしております。

タスク切り替えにはコストがかかる

ゴールデンウィークに親と待ち合わせしていて、早めに着いたからジョエルオンソフトウェアを買って読んでいた。暇つぶしだから面白そうなところだけかいつまんで読むつもりだったけど、基本的に全部面白い。PART 2まで読み終わって一番面白かったのは23章の「人のタスク切り替えは有害であるとかんがえられる」。

Human Task Switches Considered Harmful - Joel on Software

よくタスクを平行してやるよりも直列で進めたほうが早く終わると感じる。フロー状態をぶつ切らないとかマジカルナンバーのように人間が同時に物事を把握できる量はそんなにないとか色々理由付けられると思うけど、この章のCPUのマルチタスキングを例にして解説しているところがわかりやすくて面白かった。

タスクの切り替えにはコストがかかる。ゴールデンウィーク前にしていた仕事の細部が思い出せない。昼休み前に自分はどんな構成のコードを書こうと思って途中まで書き進めていたんだっけ。という具合に人はすぐに物を忘れるので、思い出すのに時間がかかる。残念ながらパイプライン処理のようにタスクをこなす超人にはなかなかなれない。他のことが気になっても、できるだけ今のタスクが終わってからにできないかというのを意識するようになった。

ただ、期日が決まっている中で直列にタスクをこなすのは止めた方が良いときもある。タスクAとBがあって、序盤ではAもBも2日で終わるという(たいして根拠の無い)予測をしていて、2つ合わせて4日かかると思っていた。予定通りAを2日でこなし、Bにとりかかって1日目の夕方に、どうもBは4日必要なタスクだったと気付く。この時点で明日には終わらないから締め切りを3日伸ばしてくれとお願いすることになる。一方、最初にAを2日かけて終わらすのではなく、Aに1日、Bに1日というやり方だったら2日目で締め切りが伸びるということを伝えることができる。AとBが終了する日数は同じとしても、土下座するタイミングは速いほうが迷惑はかからない。すごい極端な話ではあるけど。

数日かかる大きいタスクは数時間単位に分割して、細かいタスクを直列に実行する。大きいタスクは直列に実行するのではなく、進めてない方のタスクをたまに様子見したりすると良いかなと思う。

最近遊んだiOSゲーム

面白かったのを一言ずつ。iTunesオススメゲームが基本的に面白いから、面白いゲームを探したりする行為をしなくなったように思う。パズルゲームとかも遊んだけど、ハズレが多かった。ミニマルを目指しましたみたいなデザインのゲームは面白そうに見えるがハズレを連続で踏んだから食傷気味。

Smash Hit

iTunes Storeのオススメコーナーにあったから遊んでみた。ボールを投げてガラスを破壊していくゲーム。ガラス破壊さえなければゴミ箱シュート系のゲームと変わらないけど、ガラス破壊の爽快感だけで全然別物になる。


Smash Hit Trailer - YouTube

Geometry Dash

強制横スクロールアクションゲームで、横からくるブロックをジャンプで避けたりする。操作はタップのみ。極端な難易度と1ステージの適度な長さのバランスがSuper Hexagonを思い出す。


Official Geometry Dash Trailer - YouTube

Duet

赤と青のボールを円に沿って右回転・左回転させて障害物を避けていくシンプルなゲーム。難易度は高い。これもオススメコーナーにあったし、もうオススメコーナーにあるゲームだけ遊んでおけばおkなんじゃないかと思う。


Duet Game - Universal - HD Gameplay Trailer - YouTube

Deemo

音ゲー。ステージをクリアしていくとストーリーが進む珍しい音ゲー。現在、中間エンディング(?)みたいなのがあるだけで、話は終わっておらず、次の追加パックで話が進むらしい。


Deemo Android GamePlay Trailer (HD) - YouTube

Kero Blaster

開発室Pixelの新作アクションゲーム。攻撃は左右と上にスワイプすると方向が固定されるという操作方法で、スマホでも遊びやすいUIだと思う。サクッとクリアできる内容で、色々盛り沢山だった洞窟物語とくらべてしまうけど、そのサクサク感もスマホ向けに調整されているのかな。まあ、当たり前に面白いよねという感想だった。


Kero Blaster - Launch Trailer - YouTube

Markdown => Textile

メモはMarkdownで書いてるのに、やむを得ない事情でそれをTextileにしないといけないこともある。 仕方がないのでいろんな形式のドキュメントを相互変換できるPandocを使いだした。

Installingに書いてあるとおり、PandocはHaskellパッケージ管理システムのcabalでインストール。

brew install haskell-platform
cabal update
cabal install pandoc
export PATH="$HOME/Library/Haskell/bin/:$PATH"
pandoc -f Markdown -t Textile File

みたいにすればMarkdown形式のFileをTextileへ変換できる。 変換ついでにクリップボードに放り込めると便利なのでpbcopyを使う。

pandoc -f Markdown -t Textile File | pbcopy

記事のネタがないのでこんな感じでお茶を濁していきたい。

白と黒のとびら

魔法使いに弟子入りした少年ガレット.彼は魔法使いになるための勉強をしていくなかで,奇妙な「遺跡」や「言語」に出会います.最後の謎を解いたとき,主人公におとずれたのは……

http://www.utp.or.jp/bd/978-4-13-063357-4.html

こんなふうにオートマトン形式言語に関連するテーマで1つのストーリーになっている。ある程度わかってる人たちは読んでると先が読める部分があると思うけど、それはそれで面白くて、主人公のガレットよ頑張れという気持ちになった。もちろん、オートマトンなんて単語も聞いたことない人でも読めて、最後にはチューリングマシンとはなんだとか、チューリングマシンで解けない計算問題とはどんなものかというところまで分かる。

ガレットに対する師からの言葉には身につまされる部分が多くて、辛い感じになるところもあった……身が引きしまる。

対角線言語

解説にあった対角線言語という単語を知らなかった。対角線言語はチューリングマシンに入力する文字列のうち、記述するチューリングマシンによって受理される文字列を除いた集合だと解説には書いてある。すなわち、受理されない文字列の集合。

受理されない文字列には「そもそもチューリングマシンを記述しない文字列」と「記述するチューリングマシンで受理されない文字列」がある。対角線言語を受理できるチューリングマシンがあるとその文字列は受理可能だという矛盾が生じるので、対角線言語を定義できるチューリングマシンは存在しない。

実践テスト駆動開発

実践テスト駆動開発 テストに導かれてオブジェクト指向ソフトウェアを育てる (Object Oriented SELECTION)

実践テスト駆動開発 テストに導かれてオブジェクト指向ソフトウェアを育てる (Object Oriented SELECTION)

実践テスト駆動開発を読んだ。サブタイトルは「テストに導かれてオブジェクト指向ソフトウェアを育てる」。TDDの手法そのものだけでなく「オンラインオークションの自動biddingクライアントの作成」という実践テーマを通して、オブジェクト指向ソフトウェアの柔軟性を高めるためのノウハウと、アジャイルやプロトタイピングなどの顧客に提供する価値を高める方法が書いてある。

うまくまとまらなかったのでメモしたところだけ箇条書き的に。

  • 予期せぬ変化を早くつかむためにもフィードバックループは欠かせない

    • 仕事をタイムボックスに分割し、設定された期間中に分析・設計・実装をすませてそれをデプロイする
    • デプロイ後実地からのフィードバックを得る
  • テストを書くことはどこまでやれば作業完了なのかを表すことになるので、不必要なフィーチャを盛り込んでしまうことを防げる

    • テストに書いている要件に不必要なフィーチャが入り込むことは防げないけど、テストに書いてある以上のことはしない
  • ひとつの仕組みで複数の概念を表現すると再利用が難しくなるのでコードの重複が生じる

    • オブジェクトは疎結合・高凝集であれ
  • オブジェクトが意思決定を行うとき、自身の情報かメッセージとともに渡された情報のみを使うことを心がける(デメテルの掟)

    • 例えば、引数で渡されたオブジェクトのメソッドの戻り値に対して何らかのメッセージを送るということは、2つ先のオブジェクトの構造まで知る必要があるので結合度が増してしまう
  • デプロイプロセスなどのあるプロセスを自動化するということは、そのプロセスを理解することと明文化することに繋がるのでお得

  • 先にシステム全体のテストを書くことは事前の設計を完璧にすることではない

    • 最初に決めたことはたいてい間違っているのだから、詳細についてはTDDでシステムを育てながら決めていきたい
    • システム全体のテストが動き始め、フィードバックループが実行されるということが重要(TDDサイクルに火を入れる)
  • テストはそのクラスが何をするかという説明書でもある

    • メソッドのテストをするのではなく振る舞いのテストを書く
    • メソッド名だけではそのクラスが何を実現可能なのか分からない
      • フィーチャが実現されているかの確認に集中することが大事という話だと思うがちょっと極端に聞こえる
      • そもそも実装を知らないと書けないテストの部分はコンポーネントとして切り出せそうだが、持たせるべきフィーチャ以外のものも同じ所で実装しちゃうこともある(時と場合によりという言い訳付きで)
  • 様々なコンテキストに適用できる高凝集なオブジェクトを作る

    • オブジェクトの組み合わせ方を変えるだけでシステムの変更が可能となるように
  • 値型の包括性

    • 複数のフィールドが一緒に使われている時、何らかの構造体が欠けている可能性がある
    • それらのグループに名前をつけてまとめ、値型をシンプルに保つ
  • Javaインターフェースはオブジェクト間のプロトコルとして定義する

    • インターフェースを実装したものはロールを表わす
      • クラスは実装上の詳細であり、他のオブジェクトが知ることではない
      • インターフェースを小さくすることでロールがいっそう明確になる
      • オブジェクト間の暗黙的な結合を最小限に抑え、取替え可能なものとする
  • 設計をいつ変更するのか

    • 既存のコードをコピペすることもあるとき、設計を変えるかどうか、時間との相談だというコンテキストで…

「ちょっと変えただけのコードをコピーして使おうとしている。これは馬鹿馬鹿しいし、時間のむだだ」なのか、「今はこれを修正すべきときではない。まだよくわかっていないのだ」なのか。この方針について、再現可能でシンプルなテクニックは存在しない。スキルと経験が必要なのだ。だから、開発者は自分たちの活動について深く考えるよう習慣づけなければならない。この後のコーディングのために自分たちの時間を投資するもっともよい方法は何か、と。その結果、今までとまったく同じようにやることになるかもしれない。しかし、少なくともそれについて考えてはいるのだ。

(p.179より)

  • 心変わり万歳

    • 前に考えていた知識は、開発プロセスを何度も繰り返して得た今の知識と比較すると間違っていたり明確ではない
    • 知識が不明確な状態で考えた構造は脆いので、既にある構造に合わせるのではなくどんどん変えていく
  • 複雑なテストデータの構築

    • テスト対処のオブジェクトを生成するために必要なオブジェクトがあるとき、オブジェクト生成部分が長くなったりしてテストする振る舞いに関係ない情報でうめつくされる
    • テスト対象のオブジェクトが変わった時にテストも大きく変更する必要があるため、テストが脆くなる
    • オブジェクト生成をテストデータビルダーに任せればオブジェクト生成に関するノイズがなくなり、テストに必要なパラメータの明示が可能となる
  • 4段階のTDDサイクル

    • レッド・レポート・グリーン・リファクタリング
      • レポートは診断メッセージを分かりやすくすること
      • レポートがないとコードをグリーンにすることばかりに気を取られてしまいレッド時のメッセージが分かりにくいと、次にレッドになった時に失敗の意味が分からなくなる