レガシーコード改善ガイドを読了したので、読書メモです。

20130811215651.jpg

分厚い本だけれども、とても良書だった。挫けそうだった時に読んだので、心に染み入るように文章が心に響いた。

もっとも、自分は仕事ではC言語のレガシーコードと戦っているのて、オブジェクト思考的な手法は使えない。そういう部分は読み飛ばした。

いろいろと心に残ったことはあるけれども、抜粋して書き出します。

整合部・形容点

以下、書籍から定義を引用します。

接合部

接合部(seam)とは、その場所を直接参照しなくても、プログラムの振る舞いを変えることのできる場所である。

許容点

どの接合部も許容点(enabling point)を持つ。許容点では、どの振る舞いを使うかを決定できる。

この2つの概念は大事。どんなコードも、依存関係を排除できる可能性があるということ。諦めてはいけいなということ。鋭い感性で、ズバッと許容点を探しだすスキルを磨くことが大事だ。

スプラウトメソッド

スプラウトメソッドとは、新規追加する機能は関数として抜き出して(スプラウトして)実装する方法。関数の呼び出しもとは、ドロドロの依存関係でテストがかけないれども、できたてホヤホヤの関数ならばテストがかけるはず。

if文のリファクタリングによく使う。こんなの。

if( (hogehoe && uhauha) ||
    (iyaiya) ||
    ((mouiya) && (dameda)) )

場合によっては、ファイル自体をテストハネースに組み入れることができない。そんなときは、新しいファイルを新規作成して、機能を独立させて実装する(これをしたら怒られたけどれも)

ラップメソッド

ラップメソッドはスプラウトメソッドの逆。既存の処理は、関数として独立させて追い出す。汚い部分は追い出す。SmelllCodeをラップする。臭いものには、クレラップ。

if(smell){
    /* 500 Step*/
}

ここに機能を追加しないといけないときは、ラップ関数を作成して、追い出す。

void lap(void) {
    if(smell){
        /* 500 Step*/
    }
    return 0;
}

あとは、きれいな関数たちでコードを書く。

seiketu();
lap();

プリプロセッサ接合部

このテクニックを知ったことは、一番の収穫かもしれない。プリプロセッサ接合部、便利すぎる!というか、すごいぞ!

例えば、コードの中にあるunko()が邪魔でしょうがない時は、プリプロセッサで消してしまえば良い。

#define unko{retrn 0}

スパイしたり、フェイクしたいときだって、置き換えは簡単。インクルードファイルを冒頭に書いてその先で後方置換してしまう。こんな風に、スパイだって自由自在だ。

hogehoge.c

#ifdef DEBUG
#include "Mock_unko.h"
#endif

Mock_unko.h

static int last_un;
static int last_ko;

void unko_Spy(int un, int ko)
{
    last_un = un;
    last ko = ko;
}
...

#define unko unko_Spy

多用し過ぎるとプロダクトコードがごっちゃになるとかで推奨されていないようだが、便利すぎるのでついつい使ってしまう。

仕様化テスト

振る舞いを維持するためには、テストが必要。しかし、その振る舞いすらよくわからないことがある。よく

いわれるのが

「仕様書を信じるナ!実機に聞け!」

実際の動作のみが唯一正しい真実なのだ。

この振る舞いを壊さないために、テストして明文化することでで、振る舞いを維持する。そのテストが仕様化テスト。

正直、今目の前にあるコードをテストで覆うのは無理!なので、既存処理に対する単体テストは諦めてる。とてもそんな工数はないし、コストパフォーマンスもない。そうではなくて、機能テストで覆うことに心の重点がシフトし始めている。それが、Fitnesseだったりする。