オブジェクト指向で hello.world. を作ることについて考えてみた。
なんというか、hello.world. に過ぎないのにこれが正解っていう答えがない。 オブジェクト指向は「どの方向に拡張性を確保しておくか」が書けるので、そこで思想的なものが回答に影響してくる。
case 1
「"hello.world."という文字を出力する」という機能全体を1つのオブジェクトに詰め込んだコード。
単なるhello.world.を実装しようとするならこれが正解である。YAGNIの法則に従え。
だが、これがオブジェクト指向で書いたhello.world.かと言われると疑問が残る。
class HelloWorldApp run: -> console.log "hello.world."
case 2
「オブジェクトとは、データと手続きをひとかたまりにしたものである」の概念に従ったコード。
この方式は「単一責務原則」に違反しているのではなかろうかと思う。
これは出力する文字列を変えたい場合と、何に出力するか(画面ではなくプリンタに出すとか)を変えたい場合に、HelloWorldStringを修正する必要が発生する。
class HelloWorldString constructor: -> @s = "hello.world." print: -> console.log @s class HelloWorldApp run: -> helloWorlString = new HelloWorlString()
helloWorlString.print() |
case 3
「オブジェクトとは、責任を実行するものである」の概念に従ったコード。
オブジェクト指向設計的に「正しい」のは、恐らくこれに抽象クラスを加えたものだが、完全に正規化されたDBテーブルが必ずしも良い設計ではないように、プログラム規模によってはそれが良いコードとは言い切れない。
# Hello.World.の文字を作ることの責務を負うクラス class HelloWorldString buildString: -> return "hello.world." # 出力の責務を負うクラス class Printer print: (s) -> console.log s # クラスを組み合わせて希望の動作を実現 class HelloWorld constructor: (@printer, @helloWorldString) -> print: -> @printer.print @helloWorldString.buildString() class HelloWorldApp run: -> helloWorld = new HelloWorld( new Printer(), new HelloWorldString()) helloWorld.print()