クラスに変更が起こる理由は、一つであるべき。Principle)クライアントは自分が使わないメソッドに依存することを強制されない。クライアントから見えるべきで、他のメソッドには依存したくない。最小にして、変更の伝播を最小限に食い止めたい。ISPは「インターフェイスをクライアント毎に分離しよう」という原則なのです。氏も同じような話をしています。リファクタリングのコストが高くなるので、早い段階で分割を進めてしまうという理由があるからではないかと指摘しています。対しては、強力な型システムがあることによって、これらの懸念を払拭できるため、先走りのモジュール分割を避けることが出来るというわけです。実際に、Elmでは一つのファイルやモジュールが大きくなることについて、他の言語(特にオブジェクト指向言語)よりも寛容であるということがよく言われています。そもそも適切な抽象化が難しいのに、その抽象化が有用であるという証拠が揃わない内に分割を進めてしまうと、より不適切な分割をしてしまう可能性が高くなってしまいます。先走って分割したモジュールが、後々の状況変化に対応できなくなって、例外条件に対応するコードが増えて行き、そしてスパゲッティ化していく過程というのはシステム開発の現場で働く多くの人が目撃しているのではないでしょうか。abstraction「間違った抽象化よりも、コードの重複の方を好む」ということで、長らく信奉されてきたDRY原則への挑戦がここでは行われています。abstractionそして、偶然なのか何なのか、これも同じ8月に、オブジェクト指向における抽象化がなぜ難しいかというのを良く表している大変興味深い記事を見つけることになります。~何のために、「データとロジックを一体に」するのか?~カプセル化することが自己目的化していて、何のためにカプセル化するのかという視点が極めて希薄なことです。その結果、「うまいカプセル化」「まずいカプセル化」の区別がない、という状況に陥っています。...本来は、値引き判定のロジックをどのオブジェクトに配するかを決めるにあたって、どのような知識を隠蔽すべきか、あるいは裏返して言えば、どのような知識は開示して構わないかという点に思いをめぐらすべきでした。...解決策は、「データとロジックを一体に」という、どちらかというとゲームのルールのような具体的で単純なルールから視点を引き上げ、「情報隠蔽(=知識隠蔽)」のような、より本質的な、目的志向的な設計原則に立ち帰って考えることです。この記事の要旨は、増田亨氏の「現場で役立つシステム設計の原則」という書籍で紹介されているオブジェクト指向のコード例について、「データとロジックを一体に」というオブジェクト指向の表面的なルールに囚われ過ぎて「何を隠蔽して何を表に出すのかという設計判断」を蔑ろにしているという指摘です。この記事を読んで個人的に思ったことは、設計判断の根拠となる「スコープが適切でない」ということを、後から文脈をズラすことでいくらでも言えてしまうというのが問題の本質じゃないか、そこに「データ・ロジック一体型設計」の限界があるということなのではないか、ということでした。Abstractions」という、2002年に書かれた記事に出てきます。なった時にかかるコストというのは、抽象化がなかった時よりも高くついてしまう可能性があります。隠蔽された部分の知識も結局のところは必要なのだとなれば、抽象化された部分と隠蔽された部分の両方の知識が必要になるからです。togetherオブジェクト指向の問題点を指摘する場合、一番厄介なのは、オブジェクト指向に定まった定義がないという事実です。このブログでは以前、オブジェクト指向の歴史を遡って、あれってそもそも何だったのかということについて検討したことがあります。ゆびてく歴史的な経緯から言えば、オブジェクト指向を発案したアラン・ケイ氏が言うところの「メッセージング」が、オブジェクト指向の本質だということなりそうですが、一般に普及した「オブジェクト指向言語」と呼ばれるもので、メッセージングをサポートしているものはほとんどありません。きっかけに流行した「抽象データ型」を起源とする流れが、一般的に認識されているオブジェクト指向だと考えて差し支えなさそうです。氏によれば、一般的にオブジェクト指向の強みだと思われているほとんどの要素はオブジェクト指向固有ではなく、オブジェクト指向固有の強みなど、実際には一つもないそうです。Companyすんごく長いけど一読の価値あり。オブジェクト指向固有でないものを除外していくと、最後に残るのが「データとロジックを一体に」という先ほどのルールです。このルールがオワコンになりつつあるのではないかというのが、この約1年間、Elmでプログラミングをしていて実感するようになったことです。関数型プログラミングをしていると、データとロジックが分かれていることのメリットを実感する機会が度々あります。アプリケーションにはアプリケーション固有の複雑さというものがあって、それらは多くの場合、必要な複雑さである場合が多いような気がしています。オブジェクト指向では、データとロジックを一緒にしなければならないという制約のために、それらの例外的だと思われるケースを捨象して、現実に即さないモデルに(強引にでも)落とし込むことになります。オブジェクトに関数が結びついているからこそ「このメソッドはこのオブジェクト構造を処理するためのものだ(他の用途には使えない)」という風に専門化できていたんであって、データと関数を個別のものと扱う以上は、「この関数はこのオブジェクトだけを扱う」という前提を置けないのです(当たり前です)。あるオブジェクトと別のオブジェクトが、型であったりクラスであったりが異なったとしても、関数は、そのオブジェクトが、関数の処理できる構造であれば、処理できるべきなんです。関数とオブジェクトが独立しているというのはそういう意味であるべきです。あれば、すべての関数にまたがるような、共通の汎用データ構造があって、すべてのデータはその汎用性を担保してたほうがいい。氏が、彼のオブジェクト指向批判の中で、「オブジェクト指向とは、つまりモデリングなのだ」と喝破していますが、複雑な事象を分かりやすい用語(ターム)の集合に落とし込めるという先入観が、アプリケーションレベルの複雑性を扱う時に明らかな障害となって現れるケースが多くなっているような気がします。メッセージングが今のオブジェクト指向と関係ないのだとすれば、「データとロジックを一体に」がオブジェクト指向の核心になりますが、そうだとすれば、オブジェクト指向自体がオワコンだという結論になってしまいます。それはどうもそうっぽいという感じがしているのです。makingここからは少し余談になりますが、以上のような気づきを得た上で、過去のオブジェクト指向批判の文章を読むといちいち首肯できることが多くて困ってしまいます。オブジェクト指向というのは、オブジェクト指向にしかない問題を作り上げて、それを解決するためのツールを作るというマッチポンプ的なことをしてお金を稼いでいるという話があります。Armstrong(さっきのバナナの人)あるいは、オブジェクト指向ではそもそも過剰な複雑性を作り込んでしまう傾向があるという批判があります。いえば、オブジェクト指向には、インターフェースに対してプログラミングするという考え方があるので、プログラムは自然にレイヤー構造になっていくからです。「コンピュータサイエンスは、間接層(indirection)を設けることであらゆる問題が解決できるという信念に基づいた学問である。DeBruler」とあったりしますが、しかし、間接層はもろ刃の剣であることに注意しなければなりません。1つのものを2つに分割するということは、それだけ管理しなければならない部分が増えるということなのです。オブジェクトが、他のオブジェクトに委譲を行って、その先もさらに委譲を繰り返すような場合、プログラムが読みにくくなるのも事実です。間接層は、最小限に絞り込むべきなのです。言え、実際には過剰なレイヤー構造になっていることが多いような気がします。enough」や「YAGNI」なんてことが言われるようになりましたが、今を思えば、これはオブジェクト指向の側にそもそも過剰な複雑性を生む性質があったために、わざわざ言わなければならなくなったことのようにも思えてきます。Companyこれはまさにオブジェクト指向にしか存在し得ない問題を、比較的大掛かりに解決しようとした例の代表だと言えそうです。氏に批判されています。流れで、いよいよオブジェクト指向に対する懐疑心が無視できないレベルに達した2017年冬。2件のコメントオブジェクト指向と関数型プログラミングは両立するのか?オブジェクト指向と関数型プログラミングは両立すると言われる。実際に両方のパラダイムを持つプログラミング言語も存在し普及もしている。関数型プログラミングに入門してから一年余り、どうもこの二つの考え方は両立しないのではないかという思いが強くなってきた。これらが両立するという前提が混乱の元になっているのではないかと思うようになった。関数型プログラミングの何が嬉しいのか?」では、オブジェクト指向と関数型での、状態に対するアプローチの違いについて触れた。オブジェクト指向では状態とその遷移を隠蔽することによってシステムを単純化する一方、関数型では(多少冗長になっても)状態遷移を明確にすることによってシステムの動作を予測しやすくするという対比だ。両者は、状態に関しては真逆のアプローチを取っている。オブジェクト指向でも、不可変なデータを扱うことによって意図しない状態遷移を防ぐことができるし、それによってオブジェクト指向でなくなってしまうわけではないと考えることもできる。副作用を避ける(不可変なデータを扱う)場所と、副作用を扱う場所を分けることによって、両者の考え方をうまく共存させることができるのではないかと。アーカイブ動画を見ていたら、オブジェクト指向と関数型はそもそも根本的に異なる思想なのだという思いを新たにした。フロントエンド開発に特化した、純粋関数型のプログラミング言語である。この発表では、プログラムデザインの流れをもう一度基礎から再考すべきであるということが語られている。Refactor」というサイクルを回しながら、構造化すること自体を目的化せず、今行おうとしているそのリファクタリングによって「そもそも何を保障したいのか?」を問う。ここでの狙いは、過去の経験によって培われた「構造化の先走り」を防ぐことにある。有名な問題に「コンポーネント・アンチパターン」というものがある。コンポーネントの集まりとして表現する、というそれまで当たり前に考えられてきた文脈に沿って、状態とその変更ロジック、そしてその状態を表示するためのビューをひとまとめにしたコンポーネントというものを定義し、それらを組み合わせることによってアプリケーションを構築するという手法を紹介していた。このデザインでは、アプリケーションが大きくなるにつれてコンポーネント同士を連携させるためのボイラープレートが膨大になったり、柔軟性に欠けるケースや無駄な重複が現れるとして、その後、コンポーネント化はできるだけ避けるべきだと明言されるようになった。動画では、コンポーネントとは結局のところ、状態と操作をひとまとめにする、オブジェクト指向の構造化手法であることが指摘されている。同様の手法を適用した結果、思ったような柔軟性を得られなかったという流れだ。このブログでは過去に「オブジェクト指向とは何だったのか?」という記事で、オブジェクト指向をその起源に遡って解釈しようと試みたことがある。ゆびてくケイ氏は、オブジェクトを、ネットワークを形成してメッセージを送り合うコンピュータのメタファーとして捉えており、インターネット上のサーバーのように、リクエストをメッセージとして受け取り、そのメッセージをサーバー側で解釈して何らかの処理を行うというモデルを想定していた。...この全てがオブジェクトであるという原則と、大きなシステム(オブジェクト)は小さなシステム(オブジェクト)の組み合わせで作られるという「再帰的デザイン」によって、どんな複雑なシステムをデザインするときでも、覚えなくてはならない原則は少なくて済むようになる。オブジェクト指向では上のような再帰的構造を持つものとしてシステムを捉える。これがアプリケーションに応用されると「アプリケーションはより小さなアプリケーションの集合によって表現される」ことになる。凝集性の観点から言えば、これはとても魅力的なアプローチに思える。アプリケーションを構成する、より小さなサブアプリケーションは各々が独立していて、変更の影響も局所化される。世界)では、このモデルに疑いの目が向けられることになった。件の動画では、アプリケーションはアプリケーション固有の(そもそも必要とされる)複雑さを持つのだから、その複雑さに対応するために、データから操作を切り離し、両者をより柔軟に組み合わせることによってその複雑性に対応すべきだということが示唆されている。グローバルな状態やロジックを集めたコードが長くなることについて、他の言語よりも寛容である、ということが説明される。持つ強力な型システムの支えもあるかもしれないが。アプリケーションの再帰的構造というオブジェクト指向のモデルは、昨今のフロントエンドのような複雑なシステムを表現するには単純に過ぎるという問題は、オブジェクトとリレーショナルモデルをマッピングするときに問題視されたインピーダンスミスマッチの問題に似ているかもしれない。最近、この問題に関係していると思われる大変興味深い記事に遭遇した。氏による「小さな関数は有害だと考えられる」というタイトルの記事だ。Mediumhttps://medium.com/@copyconstruct/small-functions-considered-harmful-91035d316c29タイトルが若干ミスリーディングであることは本人も認めているが、彼女が言わんとしていることはこういうことである。Code」などに書かれていたり、あるいはソフトウェア開発における著名人が喧伝するような、今では当たり前とされる、オブジェクト指向時代に生まれた設計指針が果たして今も本当に有効なのかどうか今一度確認してみるべきではないのか、と。彼女の問題意識は、適切な抽象化というものがそもそも難しいのだというところから出発して、DRY原則などによって無条件に構造化を推し進めようとする既存の設計手法は、多くの場合に失敗に終わる抽象化によって、可読性や柔軟性を欠いたコードになることが多いという発見に辿り着く。オブジェクト指向時代の多くのプラクティスは抽象化が適切に行われることを前提にしているため、物事が複雑に揺れ動く現実の世界では、そもそもそのメリットを享受することが難しい。abstractionそもそも完璧な抽象化というものは存在しない。抽象化された概念というのは、ある文脈を前提にした主観的なものに過ぎないからだ。その文脈はあらゆる要因によって常に揺れ動いている。氏は、既存のコードが持つ影響についても指摘している。書き上がったコードはある種の成果であるため、たとえ文脈が変わってしまっても、そもそもの文脈を廃棄することには心理的な抵抗が働くのだと。その結果、いびつな形で増改築が行われた建築物のように、構造化はされているが、全体像を捉えるのは難しいプログラムが出来上がってしまう。速くそして複雑に変化するシステムを捉えるためには、無条件な構造化については慎重にならなければならない。下手に構造化するぐらいであれば、多少関数が長くなっても実直に書かれている方が遥かに可読性が高く修正もしやすい。Principle(開放/閉鎖原則)に則るべきだと言われてきた。その原則がうまく働くのは抽象化がうまく行われた時だけである。あれば、「修正しやすい」こととは何かということを今一度考え直すべきなのかもしれない。この議論を呼びそうな記事に対しては、当然のことながら、既存の設計指針を支持する陣営から反論が行われている。以下はその一例である。Mediumhttps://medium.com/@joshsaintjacque/small-functions-considered-awesome-c95b3fd1812f反論の要旨は以下のような感じだ。従って修正されるべきである大きな関数は副作用を持つ可能性が高くなるこういう反論はいかにもありそうだという印象を個人的には受ける。「あなたはそもそも適切に抽象化できていないから」小さな関数が有害だと感じるのだという、オブジェクト指向界では比較的馴染みのあるものだ。「そもそも抽象化が難しい」というところには応答しておらず、議論はすれ違っている印象を受ける。会談」にも現れていた。ゆびてくDHH氏の想定するようなTDDは、Beck氏やFowler氏の想定するTDDとは異なり、単にやり方が悪いからうまく行かないだけで、DHH氏の発言は「わら人形論法」に過ぎないというのが、TDD肯定派の反論である。DHH氏の立場であり、ここがすれ違いの中心になっている。役割が相対的に小さくなること、あるいは「TDD再考」でも取り上げたように、ユニットテストそのものの価値の問題を考えると、それほどクリティカルな反論であるとは言えないように思える。いうシステムを開発している。いうシステムの後継に当たる。