本の中で Coders at work Joe Armstrongは次のように述べています:
再利用性の欠如は、関数型言語ではなく、オブジェクト指向言語にあると思います。オブジェクト指向言語の問題は、彼らが持ち歩いているこの暗黙の環境をすべて持っているからです。バナナが欲しかったのですが、得たのはバナナとジャングル全体を抱えているゴリラです
ここではあまりわかりません。問題がバナナを取得することである場合、関数「getBanana」の背後にあるすべてのロジックをカプセル化できます。サルとジャングルはこの文脈にどのように関与していますか。誰かが問題を理解しやすい方法で説明するコードスニペットを書くことができます。たとえば、Banana
オブジェクトがMonkey
およびJungle
オブジェクトを開始する必要があるという事実を実証できます、 お願いします?
実際のOOPプログラムの大部分は懸念の分離を尊重しないという事実をほのめかしています。たとえば、次のようなクラスを作成できます。
public class Banana
{
public Monkey Owner {get;}
}
public class Monkey
{
public Jungle Habitat {get;}
}
public class Jungle
{
}
Banana
を使用する場合、Monkey
およびJungle
にも依存する必要があります。
しかし、私はこれがOOPの問題であり、その機能的なスタイルにはどういうわけかそれが存在しないことに厳密に同意しません。これはOOPの導入で簡単に修正できます。正しい抽象化。
問題は、懸念の分離を気にしない開発者に関するものです。そして、OOP=プログラマーの大多数は初心者であり、関数型プログラマーはある程度の経験を持っているため、コードを適切に分離する動機付けになると私は断言することを恐れません。
可能な抽象化は次のとおりです。
public class Banana
{
public IBananaOwner Owner {get;}
}
public interface IBananaOwner
{
}
public class Monkey : IBananaOwner
{
public Jungle Habitat {get;}
}
public class Jungle
{
}
これにより、Banana
に所有者がいることがわかりますが、Monkey
である必要はありません。何でもかまいません。また、所有者に対してBanana
が実行できることをIBananaOwner
によって定義された操作のみに制限し、推論を簡素化します。
それはさておき、 "私たちは関数 'getBanana'の背後にあるすべてのロジックをカプセル化できます"であなた自身の質問に答えます。必要なのはバナナだけですが、それを取得するには、いくつかのオブジェクト(getBanana
クラスのインスタンスなど)でGorilla
を呼び出す必要があります。そのバナナオブジェクトには、所属するゴリラへの参照が含まれている可能性が高く、そのゴリラオブジェクトには、所属するフォレストへの参照が含まれます。だから私はバナナをお願いしますが、その後ろに封入されているのはジャングル全体です。
これは極端な例であり、常にそれほど悪くはありません。しかし、OOこのようなシステムになることは珍しくありません。したがって、そのgetBanana
メソッドをテストするには、フォレスト全体をインスタンス化またはモックする必要があります。