シンプル騎士団を結社する

シンプル騎士団を結社する。

シンプルであることが設計の最大の美徳ある。これを教義とした秘密結社、シンプル騎士団を結成したいと思う。活動の実体もないし、名簿とかもない。シンプルさって大切だよねと思っている人は、ただ心に思うだけで、特に手続きもなしに構成員になれる。

さて、シンプル騎士団の構成員の一人として、シンプルさについて思うところをについて書く。

シンプルな設計の重要性のついては、しばしば言及される。有名な設計指針として、KISS原則というものがある。"Keep it simple, stupid" とか "Keep it short and simple"とかの略とされる。*1

なぜ、シンプルな設計が重要かというと経済性のためである。シンプルにすればコストが削減される。そして、その効果というのは想像以上となる。複雑性というのは、設計したその時に考えているよりも、ずっと高価である。

最近よく製造業を引き合いに出している気がするが、製造業の経営側の人が言うには「技術者に好きに設計させるとすぐに部品点数を増やしたり、複雑な形にしてしまって製造原価が増える」そうだ。確かにそのとおりで、設計している人には製造するときのコストは分からないものだ。設計図面を引くときのコストと製造するときのコストというのは大きく乖離している。図面で何気なく、穴を一個開けたり、角を丸めたりするのはのは簡単だけれども、実際に金属を削ってその形にするのはコストがかかるものなのです。

機械設計ではシンプルにせよという圧力は非常に強い。一円のコストをかけて良いならもっとマシにできるのにと思いながら、単純にさせられてしまうというのはよくあることだそうだ。実際、自動車も外観とかの仕上げは綺麗だが、下から覗いたら驚くほどの安っぽい作りである。鋳造してちょっと削っただけとか、板をちょっと曲げて溶接しただけとか。

凝ったものを作れるのは軍需産業ぐらいだろう。彼らは好き勝手に高価なものを作っているわけではないが、民生品と比べると驚くようなギミックが付いていることがある。例えば、HEAT弾はたかが弾丸だけれどもびっくりするような複雑さだし、戦闘機のジェットエンジンのノズルはうにうに動く。

しかし、KISS原則はロッキード・マーチン社という軍需産業をしている会社で言われ始めたそうだ。コスト圧力が民需品ほどは高くなくて、放っといたらどんどん複雑化して凝ったものになっていきがちゆえに言われ始めたのかもしれない。

単純にすることで減るのは製造原価だけではない。だから、民需品を作っているところから比べたら原価意識が低いと思われる軍需産業でKISS原則なんて言われたのだろう。シンプルにすれば製造コスト以外のリソースの使用も削減できる。シンプルにすれば、使用性もメンテナンス性も信頼性も向上する。また、思考のコストも減る。凝ったものを作り始めたら、もともと解決したかった問題を忘れがちだ。

問題は、原価以外のコストは見えないコストであることだ。ロッキード・マーチンのスカンクワークスを仕切っていた人は有能だったから、見えないコストも勘定できたのだろうけれども、通常は見えないコストまで考慮されない。製造業の場合は、原価の圧縮がそのまま会社の利益になるので、シンプルにしようという強い動機が働くから、原価以外のコストが見えなくても困らない。

しかしながら、ソフトウェア産業は製造原価がほとんどない。ただデータをコピーするだけだから、複製のコストは限りなく小さい。いくら複雑であろうとも製造原価は変わらない。そのために、複雑性によって生じる見えないコストが見過ごされがちである。

むしろ、製造コストが変わらないのだから、多機能で複雑であるほどよいみたいな風潮さえある。私はこの風潮が非常に嫌いなのだ。この風潮に反旗を翻す人々の集まりがシンプル騎士団である。

ソフトウェアだってシンプルな方がいいに決まっている。

複雑さはすなわち技術的負債だ。デットコードやコピペは資産でもないし、それらをつくることは生産性に含むべきでもない。排除すべきものだ。それらを生み出すLOC生産性なんて殺せ。無意味な複雑さを作ることとか穴掘って埋め戻すだけの作業だ。世の中には一切貢献しないし、ただ他の人の足を引っ張るだけのものだ。

見えないコストも含めた真の経済性を求める人は、ぜひシンプル騎士団に入って欲しい。構成員がすべきことはただひとつだ。シンプルさの維持を、設計の際に大切にすることだけである。

*1:この原則に余計なものがついていたら自身を違反しているので、KISとする場合もある。しかし、その流儀でいうとシンプル騎士団も余計なものを含んでいるとなってしまうので、ここでは採用しない。遊びは必要だと思っている。遊びの余地を作るためにどうでもいいものを削り落とすべきなのだ。

コード型ログ(1) スレッドを止めるにはinterruptを使う

他の人が書いていたら読めるけれども、知らなければ書けない定型的なソースコードの型を集めているので気が向いたら書いていく。ダジャレが好きなので、コード型ログと呼ぶ。今回は1回目。


無限ループを持つスレッドはinterrupt()で止められるようにする。

package org.example.katalog;

public class InterruptSample {
  public static void main(String[] args) {
    Thread t = new Thread() {
      @Override
      public void run() {
        // interruptされるまで、"Hello world"を出力し続ける。
        // なお、isInterrupted()は呼ぶとフラグがクリアされてfalseになる。
        while (!isInterrupted()) {
          System.out.println("Hello world");
        }
      }
    };

    t.start();

    try {
      Thread.sleep(1000);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }

    // interruptするとスレッドのisInterrupted()のフラグが立つ。
    t.interrupt();

    // interruptしてもまだスレッドが止まっているわけではない。
    // スレッドが止まるまで待つ。
    try {
      t.join();
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
  }
}

悪い例は制御フラグを独自につくることである。Javaのスレッドには言語組み込みでその目的のフラグが用意されているのだからそれを使う。

package org.example.katalog;

class HelloPrinter extends Thread {
  // スレッドを止めるべきかのフラグ。
  // volatileはあるスレッドで代入した値が他のスレッドでも
  // 同じものが見えることを保証するおまじない。
  volatile boolean stop = false;

  @Override
  public void run() {
    while (!stop) {
      System.out.println("Hello world");
    }
  }
}

public class InterruptBadSample {
  public static void main(String[] args) {
    HelloPrinter t = new HelloPrinter();

    t.start();

    try {
      Thread.sleep(1000);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }

    t.stop = true;

    try {
      t.join();
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
  }
}