web-dev-qa-db-fra.com

Exemple de code pour expliquer le problème de Banana Monkey Jungle par Joe Armstrong

Dans le livre ( Codeurs au travail Joe Armstrong a déclaré que:

Je pense que le manque de réutilisabilité vient dans les langages orientés objet, pas dans les langages fonctionnels. Parce que le problème avec les langages orientés objet, c'est qu'ils ont tout cet environnement implicite qu'ils emportent avec eux. Vous vouliez une banane mais ce que vous avez obtenu était un gorille tenant la banane et toute la jungle

Je ne comprends pas tout à fait ici. Si le problème est d'obtenir une banane, nous pouvons encapsuler toute la logique derrière la fonction 'getBanana'. Comment le singe et la jungle sont-ils impliqués dans ce contexte? Quelqu'un pourrait-il écrire un extrait de code qui explique le problème d'une manière plus facile à comprendre, par exemple, démontrer le fait que l'objet Banana nécessite le lancement des objets Monkey et Jungle , S'il vous plaît?

14
Kha Nguyễn

Il fait allusion à un fait, que la majorité des vrais programmes OOP ne respectent pas la séparation des préoccupations. Par exemple, vous pourriez avoir des cours:

public class Banana
{
    public Monkey Owner {get;}
}

public class Monkey
{
    public Jungle Habitat {get;}
}

public class Jungle
{
}

Si vous utilisez Banana, il est transitoirement nécessaire de dépendre également de Monkey et Jungle.

Mais je ne serais pas du tout d'accord pour dire que c'est un problème avec OOP et que le style fonctionnel ne l'a pas. Cela peut facilement être corrigé dans OOP avec l'introduction de abstraction droite.

Le problème concerne davantage les développeurs qui ne se soucient pas de la séparation des préoccupations. Et je n'aurais pas peur d'affirmer que la majorité des programmeurs OOP sont des novices, alors que les programmeurs fonctionnels ont une certaine expérience, ce qui les motive à séparer correctement leur code.

L'abstraction possible pourrait être:

public class Banana
{
    public IBananaOwner Owner {get;}
}

public interface IBananaOwner
{
}

public class Monkey : IBananaOwner
{
    public Jungle Habitat {get;}
}

public class Jungle
{
}

De cette façon, vous savez que Banana a le propriétaire, mais il ne doit pas nécessairement être Monkey. Ça peut être n'importe quoi. Et il limite ce que Banana peut faire avec le propriétaire aux seules opérations définies par IBananaOwner, ce qui simplifie le raisonnement.

16
Euphoric

Les gorilles ne sont pas des singes!

En laissant cela de côté, vous répondez à votre propre question par " nous pouvons encapsuler toute la logique derrière la fonction 'getBanana' ". Tout ce que je veux, c'est une banane, mais pour l'obtenir, j'ai besoin d'appeler getBanana sur un objet, par exemple une instance de la classe Gorilla. Cet objet banane contient alors probablement une référence au gorille auquel il appartient et cet objet gorille aura à son tour une référence à la forêt à laquelle il appartient. Je demande donc une banane, mais derrière, c'est toute la jungle.

C'est un exemple extrême et ne sera pas toujours aussi mauvais. Mais il n'est pas rare de se retrouver avec un système OO comme celui-ci. Et donc, pour tester cette méthode getBanana, j'ai besoin d'instancier ou de simuler une forêt entière.

13
David Arno