Une grande partie du temps, je ne peux pas penser à une raison d'avoir un objet au lieu d'une classe statique. Les objets ont-ils plus d'avantages que je ne le pense? [fermé]

9

Je comprends le concept d'un objet, et en tant que programmeur Java, je pense que le paradigme OO me vient assez naturellement dans la pratique.

Mais récemment, je me suis retrouvé à penser:

Attendez une seconde, quels sont réellement les avantages pratiques de l'utilisation d'un objet par rapport à l'utilisation d'une classe statique (avec des pratiques d'encapsulation et OO appropriées)?

Je pourrais penser à deux avantages de l'utilisation d'un objet (les deux sont significatifs et puissants):

  1. Polymorphisme: permet d'échanger les fonctionnalités de manière dynamique et flexible pendant l'exécution. Permet également d'ajouter facilement de nouvelles «fonctionnalités» et alternatives au système. Par exemple, s'il existe une Carclasse conçue pour fonctionner avec des Engineobjets et que vous souhaitez ajouter un nouveau moteur au système que la voiture peut utiliser, vous pouvez créer une nouvelle Enginesous-classe et simplement passer un objet de cette classe dans l' Carobjet, sans avoir à changer quoi que ce soit Car. Et vous pouvez décider de le faire pendant l'exécution.

  2. Pouvoir «transmettre des fonctionnalités»: vous pouvez passer un objet autour du système de manière dynamique.

Mais y a-t-il d'autres avantages aux objets par rapport aux classes statiques?

Souvent, lorsque j'ajoute de nouvelles «pièces» à un système, je le fais en créant une nouvelle classe et en instanciant des objets à partir de celui-ci.

Mais récemment, lorsque je me suis arrêté et y ai réfléchi, j'ai réalisé qu'une classe statique ferait exactement la même chose qu'un objet, dans de nombreux endroits où j'utilise normalement un objet.

Par exemple, je travaille sur l'ajout d'un mécanisme d'enregistrement / chargement de fichier à mon application.

Avec un objet, la ligne de code appelante ressemblera à ceci: Thing thing = fileLoader.load(file);

Avec une classe statique, cela ressemblerait à ceci: Thing thing = FileLoader.load(file);

Quelle est la différence?

Assez souvent, je n'arrive pas à penser à une raison pour instancier un objet alors qu'une classe statique ordinaire agirait de la même manière. Mais dans les systèmes OO, les classes statiques sont assez rares. Je dois donc manquer quelque chose.

Y a-t-il d'autres avantages pour les objets autres que les deux que j'ai énumérés? S'il vous plaît, expliquez.

EDIT: Pour clarifier. Je trouve les objets très utiles pour échanger des fonctionnalités ou pour transmettre des données. Par exemple, j'ai écrit une application qui compose des mélodies. MelodyGeneratoravait plusieurs sous-classes qui créent des mélodies différemment, et les objets de ces classes étaient interchangeables (modèle de stratégie).

Les mélodies étaient aussi des objets, car il est utile de les faire circuler. Les accords et les gammes aussi.

Mais qu'en est-il des parties «statiques» du système - qui ne seront pas transmises? Par exemple - un mécanisme de «sauvegarde de fichier». Pourquoi devrais-je l'implémenter dans un objet et non dans une classe statique?

Aviv Cohn
la source
Donc, au lieu d'un objet avec des champs et peut-être des méthodes, pas d'objets, pas d'enregistrements, juste un tas de valeurs scalaires passées et retournées par des méthodes statiques? Edit: Votre nouvel exemple suggère le contraire: des objets, juste sans méthodes d'instance? Sinon, quoi Thing?
Que se passe-t-il lorsque vous devez échanger votre appareil FileLoadercontre celui qui lit à partir d'une prise? Ou une maquette pour les tests? Ou celui qui ouvre un fichier zip?
Benjamin Hodgson
1
@delnan Okay, j'ai trouvé une question que la réponse m'aidera à comprendre: pourquoi implémenteriez-vous une partie «statique» du système en tant qu'objet? Comme l'exemple de la question: un mécanisme de sauvegarde de fichier. Que puis-je gagner à l'implémenter dans un objet?
Aviv Cohn
1
La valeur par défaut devrait être d'utiliser un objet non statique. N'utilisez des classes statiques que si vous pensez qu'elles expriment mieux votre intention. System.Mathdans .NET est un exemple de quelque chose qui a beaucoup plus de sens en tant que classe statique: vous n'aurez jamais besoin de l'échanger ou de vous en moquer et aucune des opérations ne pourrait logiquement faire partie d'une instance. Je ne pense vraiment pas que votre exemple "d'économie" corresponde à ce projet de loi.
Benjamin Hodgson

Réponses:

14

lol tu parles comme une équipe sur laquelle je travaillais;)

Java (et probablement C #) supporte certainement ce style de programmation. Et je travaille avec des gens dont le premier instinct est: "Je peux en faire une méthode statique!" Mais il y a des coûts subtils qui vous rattrapent au fil du temps.

1) Java est un langage orienté objet. Et cela rend les gars fonctionnels dingues, mais vraiment ça tient assez bien. L'idée derrière OO est de regrouper les fonctionnalités avec l'état pour avoir de petites unités de données et des fonctionnalités qui préservent leur sémantique en masquant l'état et en exposant uniquement les fonctions qui ont du sens dans ce contexte.

En passant à une classe avec uniquement des méthodes statiques, vous cassez la partie "état" de l'équation. Mais l'État doit encore vivre quelque part. Donc, ce que j'ai vu au fil du temps, c'est qu'une classe avec toutes les méthodes statiques commence à avoir des listes de paramètres de plus en plus compliquées, car l'état se déplace de la classe vers les appels de fonction.

Après avoir créé une classe avec toutes les méthodes statiques, parcourez et examinez simplement combien de ces méthodes ont un seul paramètre commun. C'est un indice que ce paramètre doit être soit la classe conteneur pour ces fonctions, soit que ce paramètre doit être un attribut d'une instance.

2) Les règles d'OO sont assez bien comprises. Après un certain temps, vous pouvez regarder une conception de classe et voir si elle répond à des critères tels que SOLID. Et après de nombreux tests unitaires pratiques, vous développez une bonne idée de ce qui rend une classe «de bonne taille» et «cohérente». Mais il n'y a pas de bonnes règles pour une classe avec toutes les méthodes statiques, et il n'y a aucune vraie raison pour laquelle vous ne devriez pas tout regrouper. La classe est ouverte dans votre éditeur, alors que diable? Ajoutez-y simplement votre nouvelle méthode. Après un certain temps, votre application se transforme en un certain nombre "d'objets divins" concurrents, chacun essayant de dominer le monde. Encore une fois, les refactoriser en unités plus petites est très subjectif et difficile à dire si vous avez bien compris.

3) Les interfaces sont l'une des fonctionnalités les plus puissantes de Java. L'héritage de classe s'est avéré problématique, mais la programmation avec des interfaces reste l'une des astuces les plus puissantes du langage. (idem C #) Les classes entièrement statiques ne peuvent pas se placer dans ce modèle.

4) Il claque la porte sur des techniques OO importantes dont vous ne pouvez pas profiter. Vous pouvez donc travailler pendant des années avec seulement un marteau dans votre boîte à outils, sans réaliser à quel point les choses auraient été plus faciles si vous aviez eu un tournevis également.

4.5) Il crée les dépendances de compilation les plus dures et les plus incassables possibles. Ainsi, par exemple, si vous l'avez, FileSystem.saveFile()il n'y a aucun moyen de changer cela, à moins de simuler votre JVM au moment de l'exécution. Ce qui signifie que chaque classe qui fait référence à votre classe de fonction statique a une forte dépendance au moment de la compilation sur cette implémentation spécifique, ce qui rend l'extension presque impossible et complique énormément les tests. Vous pouvez tester la classe statique de manière isolée, mais il devient très difficile de tester les classes qui se réfèrent à cette classe de manière isolée.

5) Vous rendrez fou vos collègues. La plupart des professionnels avec lesquels je travaille prennent leur code au sérieux et font attention à au moins un certain niveau de principes de conception. Mettre de côté l'intention de base d'un langage les amènera à se coiffer car ils vont constamment refactoriser le code.

Quand je suis dans une langue, j'essaie toujours de bien utiliser une langue. Ainsi, par exemple, lorsque je suis en Java, j'utilise une bonne conception OO, car je tire vraiment parti du langage pour ce qu'il fait. Quand je suis en Python, je mélange des fonctions de niveau module avec des classes occasionnelles - je ne pouvais écrire que des classes en Python, mais je pense que je n'utiliserais pas le langage pour ce qu'il est bon.

Une autre tactique consiste à mal utiliser une langue, et ils se plaignent de tous les problèmes qu'elle cause. Mais cela s'applique à peu près à toutes les technologies.

La principale caractéristique de Java est la gestion de la complexité dans de petites unités testables qui se tiennent ensemble afin qu'elles soient faciles à comprendre. Java met l'accent sur des définitions d'interface claires indépendamment de l'implémentation - ce qui est un énorme avantage. C'est pourquoi il (et d'autres langages OO similaires) restent si largement utilisés. Malgré toute la verbosité et le ritualisme, quand j'en ai fini avec une grosse application Java, j'ai toujours l'impression que les idées sont plus nettement séparées dans le code que mes projets dans un langage plus dynamique.

C'est difficile, cependant. J'ai vu des gens avoir le bug "tout statique", et c'est un peu difficile de les en dissuader. Mais je les ai vus ressentir un grand soulagement lorsqu'ils s'en remettent.

Rob
la source
Vous parlez principalement de garder les choses petites et modulaires, et de maintenir l'état et la fonctionnalité ensemble. Rien ne m'empêche de faire cela avec des classes statiques. Ils peuvent avoir un état. Et vous pouvez les encapsuler avec des getters-setters. Et vous pouvez diviser le système en petites classes qui encapsulent la fonctionnalité et l'état. Tout cela s'applique à la fois aux classes et aux objets. Et c'est exactement mon dilemme: disons que j'ajoute de nouvelles fonctionnalités à mon application. Évidemment, cela va aller dans une classe séparée pour obéir à SRP. Mais pourquoi devrais-je instancier exactement cette classe? Voilà ce que je ne comprends pas.
Aviv Cohn
Je veux dire: parfois, il est clair pourquoi je veux des objets. Je vais utiliser l'exemple de l'édition pour ma question: j'avais une application qui compose des mélodies. Il y avait différentes gammes que je pouvais brancher sur les MelodyGenerators pour générer différentes mélodies. Et les mélodies étaient des objets, donc je pouvais les mettre dans une pile et recommencer à jouer les anciennes, etc. Dans des cas comme ceux-ci, il est clair pour moi pourquoi je devrais utiliser des objets. Ce que je ne comprends pas, c'est pourquoi je devrais utiliser des objets pour représenter des parties «statiques» du système: par exemple un mécanisme de sauvegarde de fichier. Pourquoi ne devrait-il pas s'agir simplement d'une classe statique?
Aviv Cohn
Une classe avec des méthodes statiques doit externaliser son état. Ce qui, parfois, est une technique d'affacturage très importante. Mais la plupart du temps, vous voulez encapsuler l'état. Un exemple concret: il y a des années, un collègue a écrit un "sélecteur de date" en Javascript. Et ce fut un cauchemar. Les clients s'en sont constamment plaints. Je l'ai donc refactorisé en objets "calendrier", et soudain j'en ai instancié plusieurs, les mettant côte à côte, sautant entre mois et années, etc. C'était tellement riche que nous avons dû désactiver les fonctionnalités. L'instanciation vous donne cette échelle.
Rob
3
"L'idée derrière OO est de regrouper les fonctionnalités avec l'état pour avoir de petites unités de données et des fonctionnalités qui préservent leur sémantique en masquant l'état et en exposant uniquement les fonctions qui ont du sens dans ce contexte." C'est fondamentalement faux. OO n'implique pas d'état mutable et l'abstraction n'est pas exclusive à OO. Il existe deux façons de réaliser l'abstraction et les objets ne sont que l'un d'entre eux (l'autre étant des types de données abstraits).
Doval
1
@Doval Je ne comprends pas pourquoi chaque discussion sur OO doit nécessairement se transformer en discussion sur la programmation fonctionnelle.
Rob
6

Tu as demandé:

Mais y a-t-il d'autres avantages aux objets par rapport aux classes statiques?

Avant cette question, vous avez répertorié le polymorphisme et le fait d' être transmis comme deux avantages de l'utilisation d'objets. Je tiens à dire que ce sont les caractéristiques du paradigme OO. L'encapsulation est une autre caractéristique du paradigme OO.

Cependant, ce ne sont pas les avantages. Les avantages sont les suivants:

  1. De meilleures abstractions
  2. Meilleure maintenabilité
  3. Meilleure testabilité

Tu as dit:

Mais récemment, lorsque je me suis arrêté et y ai réfléchi, j'ai réalisé qu'une classe statique ferait exactement la même chose qu'un objet, dans de nombreux endroits où j'utilise normalement un objet.

Je pense que vous avez là un argument valable. À la base, la programmation n'est rien d'autre que la transformation des données et la création d'effets secondaires basés sur les données. Parfois, la transformation de données nécessite des données auxiliaires. D'autres fois, ce n'est pas le cas.

Lorsque vous traitez avec la première catégorie de transformations, les données auxiliaires doivent être transmises en entrée ou stockées quelque part. Un objet est la meilleure approche que les classes statiques pour de telles transformations. Un objet peut stocker les données auxiliaires et les utiliser au bon moment.

Pour la deuxième catégorie de transformations, une classe statique est aussi bonne qu'un objet, sinon mieux. Les fonctions mathématiques sont des exemples classiques de cette catégorie. La plupart des fonctions de bibliothèque C standard entrent également dans cette catégorie.

Tu as demandé:

Avec un objet, la ligne de code appelante ressemblera à ceci: Thing thing = fileLoader.load(file);

Avec une classe statique, cela ressemblerait à ceci: Thing thing = FileLoader.load(file);

Quelle est la différence?

Si FileLoaderne pas, jamais , besoin de stocker des données, j'irais avec la deuxième approche. S'il y a une petite chance qu'il aura besoin de données auxiliaires pour effectuer l'opération, la première approche est un pari plus sûr.

Tu as demandé:

Y a-t-il d'autres avantages pour les objets autres que les deux que j'ai énumérés? S'il vous plaît, expliquez.

J'ai énuméré les avantages (avantages) de l'utilisation du paradigme OO. J'espère qu'ils s'expliquent d'eux-mêmes. Sinon, je serai heureux de développer.

Tu as demandé:

Mais qu'en est-il des parties «statiques» du système - qui ne seront pas transmises? Par exemple - un mécanisme de «sauvegarde de fichier». Pourquoi devrais-je l'implémenter dans un objet et non dans une classe statique?

Ceci est un exemple où une classe statique ne fera tout simplement pas l'affaire. Il existe plusieurs façons de sauvegarder vos données d'application dans un fichier:

  1. Enregistrez-le dans un fichier CSV.
  2. Enregistrez-le dans un fichier XML.
  3. Enregistrez-le dans un fichier json.
  4. Enregistrez-le sous forme de fichier binaire, avec vidage direct des données.
  5. Enregistrez-le directement dans une table d'une base de données.

La seule façon de fournir de telles options est de créer une interface et de créer des objets qui implémentent l'interface.

En conclusion

Utilisez la bonne approche pour le problème à résoudre. Il vaut mieux ne pas être religieux au sujet d'une approche contre l'autre.

R Sahu
la source
En outre, si de nombreux types d'objets différents (classes) doivent être enregistrées (par exemple Melody, Chord, Improvisations, SoundSampleet d' autres), alors il sera économique de simplifier la mise en œuvre par des abstractions.
rwong
5

Cela dépend parfois de la langue et du contexte. Par exemple, les PHPscripts utilisés pour traiter les demandes ont toujours une demande à traiter et une réponse à générer pendant toute la durée de vie du script, des méthodes statiques pour agir sur la demande et générer une réponse peuvent donc être appropriées. Mais dans un serveur écrit Node.js, il peut y avoir de nombreuses demandes et réponses différentes en même temps. La première question est donc - êtes-vous sûr que la classe statique correspond vraiment à un objet singleton?

Deuxièmement, même si vous avez des singletons, l'utilisation d'objets vous permet de profiter du polymorphisme en utilisant des techniques telles que Dependency_injection et Factory_method_pattern . Ceci est souvent utilisé dans divers modèles Inversion_of_control et utile pour créer des objets fictifs pour les tests, la journalisation, etc.

Vous avez mentionné les avantages ci-dessus, alors voici celui que vous n'avez pas: l'héritage. De nombreux langages n'ont pas la possibilité de remplacer les méthodes statiques de la même manière que les méthodes d'instance peuvent être remplacées. En général, il est beaucoup plus difficile d'hériter et de remplacer les méthodes statiques.

Gregory Magarshak
la source
Merci de répondre. À votre avis: lors de la création d'une partie `` statique '' du système, quelque chose qui ne sera pas `` transmis '' - par exemple la partie du système qui lit les sons ou la partie du système qui enregistre les données dans un fichier: dois-je l'implémenter dans un objet ou dans une classe statique?
Aviv Cohn
3

En plus du poste de Rob Y


Tant que la fonctionnalité de votre load(File file)peut être clairement séparée de toutes les autres fonctions que vous utilisez, il est correct d'utiliser une méthode / classe statique. Vous extériorisez l'état (ce qui n'est pas une mauvaise chose) et vous n'obtenez pas non plus de redondance car vous pouvez par exemple appliquer partiellement ou curry votre fonction afin de ne pas avoir à vous répéter. (qui est en fait identique ou similaire à l'utilisation d'un factorymodèle)

Cependant, dès que deux de ces fonctions commencent à avoir une utilisation commune, vous voulez pouvoir les regrouper d'une manière ou d'une autre. Imaginez que vous ayez non seulement une loadfonction mais aussi une hasValidSyntaxfonction. Que vas-tu faire?

     if (FileLoader.hasValidSyntax(myfile))
          Thing thing = FileLoader.load(myfile);
     else
          println "oh noes!"

Voir les deux références myfileici? Vous commencez à vous répéter car votre état externalisé doit être transmis pour chaque appel. Rob Y a décrit comment vous intériorisez l'état (ici le file) afin que vous puissiez le faire comme ceci:

     FileLoader myfileLoader = new FileLoader(myfile)
     if (myfileLoader.hasValidSyntax())
          Thing thing = myfileLoader.load();
     else
          println "oh noes!"
valenterry
la source
Devoir passer deux fois dans le même objet est un symptôme superficiel; le problème réel , il pourrait indiquer que certains travaux sont exécutés de manière redondante - le fichier peut être ouvert deux fois, analysé deux fois, et deux fois fermé, si hasValidSyntax()et load()ne sont pas autorisés à l' état de réutilisation (le résultat d'un fichier partiellement analysé).
rwong
2

Un problème majeur lors de l'utilisation de classes statiques est qu'elles vous obligent à masquer vos dépendances et vous obligent à dépendre des implémentations. Dans la signature de constructeur suivante, quelles sont vos dépendances:

public Person(String name)

Eh bien, à en juger par la signature, une personne a juste besoin d'un nom, non? Eh bien, pas si la mise en œuvre est:

public Person(String name) {
    ResultSet rs = DBConnection.getPersonFilePathByName(name);
    File f = FileLoader.load(rs.getPath());
    PersonData.setDataFile(f);
    this.name = name;
    this.age = PersonData.getAge();
}

Donc, une personne n'est pas seulement instanciée. Nous tirons en fait des données d'une base de données, ce qui nous donne un chemin vers un fichier, qui doit ensuite être analysé, puis les vraies données que nous voulons doivent être révélées. Cet exemple est clairement au-dessus, mais il prouve le point. Mais attendez, il peut y en avoir bien plus! J'écris le test suivant:

public void testPersonConstructor() {
    Person p = new Person("Milhouse van Houten");
    assertEqual(10, p.age);
}

Cela devrait cependant passer, non? Je veux dire, nous avons encapsulé toutes ces autres choses, non? Eh bien, en fait, il explose avec une exception. Pourquoi? Oh, oui, les dépendances cachées que nous ne connaissions pas ont un état global. Les DBConnectionbesoins initialisés et connectés. Les FileLoaderbesoins initialisés avec un FileFormatobjet (comme XMLFileFormatou CSVFileFormat). Vous n'en avez jamais entendu parler? Eh bien, c'est le point. Votre code (et votre compilateur) ne peut pas vous dire que vous avez besoin de ces choses car les appels statiques masquent ces dépendances. Ai-je dit test? Je voulais dire que le nouveau développeur junior vient de livrer quelque chose comme ça dans votre dernière version. Après tout, compilé = fonctionne, non?

En outre, supposons que vous utilisez un système sur lequel aucune instance MySQL n'est en cours d'exécution. Ou, disons que vous êtes sur un système Windows mais que votre DBConnectionclasse ne sort sur votre serveur MySQL que sur une box Linux (avec des chemins Linux). Ou, disons que vous êtes sur un système où le chemin renvoyé par le DBConnectionn'est pas en lecture / écriture pour vous. Cela signifie qu'essayer d'exécuter ou de tester ce système dans l'une de ces conditions échouera, non pas à cause d'une erreur de code, mais à cause d'une erreur de conception qui limite la flexibilité du code et vous lie à une implémentation.

Maintenant, disons, nous voulons enregistrer chaque appel à la base de données pour une Personinstance spécifique , une qui passe par un certain chemin problématique. Nous pourrions mettre la connexion DBConnection, mais cela enregistrera tout , mettant beaucoup d'encombrement et rendant difficile de distinguer le chemin de code particulier que nous voulons tracer. Si, cependant, nous utilisons l'injection de dépendances avec une DBConnectioninstance, nous pourrions simplement implémenter l'interface dans un décorateur (ou étendre la classe, car nous avons les deux options disponibles avec un objet). Avec une classe statique, nous ne pouvons pas injecter la dépendance, nous ne pouvons pas implémenter une interface, nous ne pouvons pas l'envelopper dans un décorateur et nous ne pouvons pas étendre la classe. Nous ne pouvons l'appeler directement, quelque part caché au fond de notre code. Ainsi nous sommes forcés d'avoir une dépendance cachée sur une implémentation.

Est-ce toujours mauvais? Pas nécessairement, mais il serait peut-être préférable de renverser votre point de vue et de dire "Y a-t-il une bonne raison pour laquelle cela ne devrait pas être un cas?" plutôt que « Y at - il une bonne raison pour laquelle ce devrait être une instance? » Si vous pouvez vraiment dire que votre code sera aussi inébranlable (et sans état) que Math.abs()dans son implémentation et la manière dont il sera utilisé, alors vous pouvez envisager de le rendre statique. Cependant, avoir des instances sur des classes statiques vous donne un monde de flexibilité qui n'est pas toujours facile à récupérer après coup. Il peut également vous donner plus de clarté sur la véritable nature des dépendances de votre code.

cbojar
la source
Les dépendances cachées sont un très bon point. J'ai presque oublié mon idiome selon lequel "la qualité du code doit être jugée d'après la façon dont il est utilisé, pas sur la façon dont il est mis en œuvre".
Euphoric
Mais les dépendances cachées peuvent aussi exister dans une classe non statique? Je ne vois donc pas pourquoi ce serait un inconvénient des classes statiques mais pas des classes non statiques.
valenterry
@valenterry Oui, nous pouvons également masquer les dépendances non statiques, mais le point clé est que masquer les dépendances non statiques est un choix . Je pourrais newmonter un tas d'objets dans le constructeur (ce qui n'est généralement pas conseillé), mais je peux aussi les injecter. Avec les classes statiques, il n'y a aucun moyen de les injecter (pas facilement en Java de toute façon, et ce serait une toute autre discussion pour les langages qui le permettent), donc il n'y a pas de choix. C'est pourquoi je souligne l'idée d'être obligé de cacher des dépendances si lourdement dans ma réponse.
cbojar
Mais vous pouvez les injecter chaque fois que vous appelez la méthode en les fournissant comme arguments. Donc, vous n'êtes pas obligé de les masquer mais obligés de les rendre explicites pour que tout le monde voit "aha, cette méthode dépend de ces arguments" plutôt que "aha, cette méthode dépend de ces (une partie de) arguments et de certains états internes cachés que je ne connais pas savoir".
valenterry
En Java, à ma connaissance, vous ne pouvez pas fournir une classe statique comme paramètre sans passer par tout un rigmarole de réflexion. (J'ai essayé de toutes les manières possibles. Si vous avez un moyen, j'aimerais le voir.) Et si vous choisissez de le faire, vous êtes essentiellement en train de renverser le système de type intégré (le paramètre est un Class, alors nous nous assurons que c'est la bonne classe) ou vous écrivez du canard (nous nous assurons qu'il répond à la bonne méthode). Si vous voulez faire ce dernier, alors vous devriez réévaluer votre choix de langue. Si vous voulez faire le premier, les instances fonctionnent très bien et sont intégrées.
cbojar
1

Juste mes deux cents.

Pour votre question:

Mais qu'en est-il des parties «statiques» du système - qui ne seront pas transmises? Par exemple - un mécanisme de «sauvegarde de fichier». Pourquoi devrais-je l'implémenter dans un objet et non dans une classe statique?

Vous pouvez vous demander si le mécanisme de la partie du système qui lit les sons, ou la partie du système qui enregistre les données dans un fichier CHANGERA . Si votre réponse est oui, cela indique que vous devez les résumer en utilisant abstract class/ interface. Vous pouvez demander, comment puis-je savoir les choses futures? Certainement, nous ne pouvons pas. Donc, si la chose est sans état, vous pouvez utiliser une «classe statique» telle que java.lang.Math, sinon, utiliser une approche orientée objet.

user3663635
la source
Il y a un conseil ironique: trois coups et vous refactorisez , ce qui suggère que l'on peut attendre jusqu'à ce que le changement soit réellement nécessaire. Ce que je veux dire par «changement», c'est: plus d'un type d'objet doit être enregistré; ou besoin d'enregistrer dans plus d'un format de fichier (type de stockage); ou une augmentation drastique de la complexité des données enregistrées. Bien sûr, si l'on est assez certain que le changement se produira bientôt, on peut incorporer une conception plus flexible à l'avance.
rwong