Press → key to advance.
Slides controls, press:
簡潔性、利便性、直交性、透明性、開示性などについて、 書籍を読んで学んだこと、コードを読んで学んだこと、 設計時に考えたこと、使う/使われることによって学んだことなどを話したいと思います。
@m_seki さんに煽られた とはいえ、とんでもないことを書いてしまったものだ……
$ cat ilities | wc -l 70 $ head ilities Usability Security Portability Interoperability Testability Reliability Maintainability Availability Stability Scalability $
これらの話はしません。
簡潔性、利便性、直交性、透明性、開示性などについて、 書籍を読んで学んだこと 、コードを読んで学んだこと、 設計時に考えたこと、 使う/使われることによって学んだこと などを話したいと思います。
"Simplicity is prerequisite for reliability"
"シンプルさは信頼性の前提条件である"
– Edsger W. Dijkstra
シンプルさと簡単さの主な違いは、シンプルさは客観的、簡単さは主観的であるということ
template = TwoWaySQL::Template.parse(<<-EOS SELECT * FROM emp /*BEGIN*/WHERE /*IF ctx[:job]*/ job = /*ctx[:job]*/'CLERK' /*END*/ /*IF ctx[:deptno_list]*/ AND deptno IN /*ctx[:deptno_list]*/(20, 30) /*END*/ /*IF ctx[:age]*/ AND age > /*ctx[:age]*/30 /*END*/ /*END*/ EOS ) merged = template.merge(age: 35, deptno_list: [10,20,30]) merged.sql #=> "SELECT * FROM emp WHERE deptno IN (?, ?, ?) AND age > ?" merged.bound_variables #=> [10,20,30,35]
<script type="text/javascript" src="path/to/qunit.js"></script> <script type="text/javascript" src="path/to/qunit-tap.js"></script> <script> qunitTap(QUnit, function() { console.log.apply(console, arguments); }); </script>
# module: math module # test: add not ok 1 - expected: 7, got: 1, test: add, module: math module not ok 2 - with message, expected: 7, got: 1, test: add, module: math module ok 3 ok 4 - with message 1..4
var assert = require('power-assert'); describe('Array#indexOf()', function(){ it('should return index when the value is present', function(){ var ary = [1,2,3], zero = 0, two = 2; assert(this.ary.indexOf(zero) === two); }); });
1) Array#indexOf() should return index when the value is present: AssertionError: # /path/to/examples/mocha_node.js:10 assert(ary.indexOf(zero) === two); | | | | 2 | -1 0 false [1,2,3]
→ シンプルで直交性のある層と、簡単さを提供する層とを分けたくなる
"ぶざまな姿をさらさずに複雑なソフトウェアを書く唯一の方法は、 全体としての複雑さの度合いを下げること だ"
"つまり、 適切に定義されたインターフェイスで結び付けられた単純な部品からシステムを作り上げる のだ。 こうすれば、ほとんどの問題は局所化されるし、全体を壊さずに部品だけを改良することも不可能ではなくなる。"
"簡潔性とは、 設計が人間の頭のなかに入る程度のものかどうか ということだ"
"簡潔だということは「簡単に学べる」ということとも 違う。 簡潔な設計のなかには、基礎にある難解な概念モデルを習得するまでは理解することかきわめて難しいものがある。 しかし、その 慨念モデルを習得したときには、世界の見方ががらりと変わり、簡潔が単純に変わる のだ。 多くの人々にとってそのように感じられるものの古典的な例としては、Lisp言語が挙げられる。"
ある種の 独立性、分離性 と言い換えても良い。
"副作用を起こしたり、他のコードからの副作用に依存したりしていないコードは 簡単に動作を確かめられるので、テストと開発のために必要な時間が短縮される。 テストすべき組み合わせが減るのだ。 直交的なコードは、エラーを起こしたとしても、システムの他の部分に影響を与えずに簡単に置き換えられる。 そして、直交的なコードはドキュメントを書きやすく、再利用しやすい"
"ソフトウェアシステムは、よくわからない部分や隠されている部分がなければ透明である。 つまり、透明性は 受動的な性質 である。 プログラムは、実際に行われていることを外から見通すことができ、 すべての、あるいはほとんどの条件のもとで動作が予測でき、頭のなかで動作かイメージできるなら、透明だといえる。"
"プログラムが何をどのようにするのかについて人が正しいイメージを持てるようにする機能を組み込んでいるソフトウェアシステムは、 開示性を持っている。
たとえば、優れたドキュメントは、ユーザーに対する開示性を上げる。 適切に選ばれた変数、関数名はプログラマに対する開示性を上げる。開示性は、 能動的な性質 だ。
開示性のあるソフトウェアを実現するためには、単にわかりにくい部分を作りそびれるだけではなく、 プログラムを理解しやすくするために積極的な努力を払わなければならない。"
Linuxカーネルのソースは、(していることの本質的な複雑さを考えるなら)驚くほど透明だが、開示性はない。 コードのなかを自由に動き回り、開発者のイディオムを理解するために必要な最小限の知識を獲得するのは難しいことだが、 それができれば、すべてがはっきりとわかる。
それに対し、Emacs Lispライブラリには、開示性はあるが、透明ではない。 1つのことを変えるために必要な知識を獲得するのは簡単なことだが、システム全体を理解するのはとても難しい。
Elegance is a combination of power and simplicity.
エレガントは、力と単純性が結合して生まれる。
Elegant code is not only correct but visibly, transparently correct.
エレガントなコードは、ただ正しいだけではなく目に見える透明な形で正しい。
power-assert の場合