Les objets en POO doivent-ils représenter une entité?


82

Un objet doit-il représenter une entité?

Par une entité que je veux dire quelque chose comme un Product, Motorun ParkingLotetc, un physique, ou même un objet conceptuel non physique claire - ce qui est bien défini, avec quelques données de base appartenant clairement à l'objet, et certaines fonctions / méthodes qui fonctionnent clairement sur les données de base.

Par exemple, je peux avoir un objet d'un Demon, une entité en soi, un imaginaire peut-être et non physique mais une entité néanmoins

Un objet peut -il être simplement un ensemble de méthodes , un ensemble commun de procédures qui se rapportent à un objectif commun?

Exemple: une classe peut-elle être appelée MotorOperationsou MotorActions, s’il n’ya pas d’entité, mais les méthodes de la classe font des choses comme

  • getMotorDataFromHTMLForm ()
  • getMotorManufacturers ()
  • selectMotorFromUserRequirements (exigences en dollars)
  • canMotorCanHandleOperatingConditions ($ conditions)
  • computePowerConsumptionForMotor ($ id)

Une classe est généralement définie comme une donnée centrale pour l'objet + les opérations sur les données. Donc, pour un Motoril peut y avoir certaines variables de moteur relatives aux spécifications du moteur, et il peut y avoir des opérations qui combinent ces données pour produire quelque chose.

Dans mon cas, c'est plus comme si j'avais une classe avec des opérations sur les données + données qui sont transmises à travers la classe, il n'y a pas de données centrées sur "Opérations sur les moteurs", autres que des données temporaires de passage à travers la classe.

Question

Les classes peuvent-elles représenter des objets sans entité? Sinon, pourquoi sont-ils mauvais / incomplets / non centrés sur la POO? Existe-t-il des moyens de les modifier / améliorer conceptuellement pour les rendre conformes à la POO?


2
+1 Mais "oui" voudrait-il dire qu'il doit représenter une entité ou pourrait-il signifier qu'ils peuvent représenter des objets sans entité?
Panzercrisis

1
La première chose qui me vient à l'esprit: java.awt et ses classes "Op" (par exemple, docs.oracle.com/javase/7/docs/api/java/awt/image/… ), si c'est ce que vous voulez dire. Cela représente une opération. Maintenant, je ne suis pas sûr que ce soit une bonne pratique (cela a l'air bizarre et moche), mais cela est inclus dans la bibliothèque standard Java, et Java est OOP. Pour la plupart.
Luke

1
Non , ce ne est pas, mais cela ne signifie pas MotorActionsou MotorOperationssont de bonnes idées ou non.
user253751

1
Cette question pourrait bénéficier d'une spécification supplémentaire de can .
reinierpost

3
@ Dennis, j'ai vraiment l'impression que vous posez toutes les mauvaises questions. D'abord parce qu'il n'y a pas une définition définitive de la POO, ensuite parce que les paradigmes ne sont qu'un moyen d'atteindre un but. Les seules questions qui comptent sont les suivantes: "Écrire du code de cette manière facilite-t-il la raison de son exactitude?" et "écrire du code de cette manière facilite-t-il la réutilisation?"
Doval

Réponses:


109

Non , un objet ne doit pas nécessairement représenter une entité.

En fait, je dirais que lorsque vous cessez de considérer les objets comme des entités physiques, vous obtenez enfin les avantages promis par la programmation orientée objet.

Ce n'est pas le meilleur exemple, mais la conception de la cafetière est probablement celle où la lumière a commencé à s'allumer pour moi.

Les objets concernent les messages. Ils concernent les responsabilités. Ils ne concernent pas les voitures, les utilisateurs ou les commandes.

Je sais que nous enseignons à OO de cette façon, mais après quelques essais, nous réalisons à quel point il est fondamentalement frustrant de savoir où vont les choses lorsque vous essayez de faire MVC, MVVM ou MVWther. Vos modèles sont ridiculement gonflés ou vos contrôleurs le sont. Pour la navigabilité, il est bon de savoir que tout ce qui touche les véhicules se trouve dans le fichier Vehicle.ext, mais lorsque votre application concerne les véhicules, vous vous retrouvez inévitablement avec 3 000 lignes de spaghettis dans ce fichier.

Lorsque vous avez un nouveau message à envoyer, vous avez au moins un nouvel objet, et peut-être une paire d’eux. Donc, dans votre question sur un ensemble de méthodes, je dirais que vous parlez éventuellement d'un ensemble de messages. Et chacun pourrait être son propre objet, avec son propre travail à faire. Et ça va. Cela deviendra évident lorsque vous séparerez les éléments qui doivent vraiment être ensemble. Et vous les mettez ensemble. Mais vous ne perdez pas immédiatement toutes les méthodes dans un tiroir vaguement approprié pour des raisons de commodité si vous souhaitez profiter de OO.

Parlons de sacs de fonctions

Un objet peut être juste une collection de méthodes et être toujours OO, mais mes "règles" sont assez strictes.

  1. La collection devrait avoir une responsabilité unique, et cette responsabilité ne peut pas être aussi générique que "Fait des choses aux moteurs". Je pourrais faire une telle chose comme une façade de couche de service, mais je suis parfaitement conscient que je suis paresseux pour des raisons de navigabilité / découverte, pas parce que j'essaye d'écrire du code OO.

  2. Toutes les méthodes doivent être au même niveau d'abstraction. Si une méthode récupère des objets Motor et qu'une autre renvoie Horsepower, la différence est probablement trop grande.

  3. L'objet doit fonctionner sur le même "type" de données. Cet objet manipule les moteurs (start / stop), celui-ci fait des manivelles, celui-ci gère le séquencement de l'allumage, celui-ci prend une forme html. Ces données pourraient éventuellement être des champs sur l'objet et cela semblerait cohérent.

Je construis généralement des objets de ce type lorsque je fais des transformations, de la composition ou que je ne veux tout simplement pas m'inquiéter de la mutabilité.

Je trouve que me concentrer sur les responsabilités des objets me conduit à la cohésion. Il doit y avoir une certaine cohésion pour être un objet, mais il n’est pas nécessaire qu’il y ait des champs ou beaucoup de comportement pour que ce soit un objet. Si je construisais un système qui nécessitait ces 5 méthodes de moteur, je commencerais avec 5 objets différents qui font ces choses. Au fur et à mesure que je trouvais des points communs, je pouvais soit commencer à fusionner les choses, soit utiliser des objets "auxiliaires" communs. Cela me fait basculer dans les préoccupations ouvertes / fermées. Comment puis-je extraire cette fonctionnalité afin de ne plus jamais avoir à modifier ce fichier, mais à l'utiliser quand c'est nécessaire?

Les objets sont des messages

Les champs importent peu à un objet - obtenir et définir des registres ne change pas le monde en dehors du programme. Collaborer avec d'autres objets permet de faire le travail. Cependant, la force de OO réside dans le fait que nous pouvons créer des abstractions afin de ne pas avoir à penser à tous les détails en même temps. Les abstractions qui fuient ou qui n’ont pas de sens sont problématiques. Nous réfléchissons donc profondément (peut-être trop) à la création d’objets correspondant à nos modèles mentaux.

Question clé: Pourquoi ces deux objets doivent-ils se parler?

Pensez à l'objet en tant qu'organe d'une personne: il a un objectif par défaut et ne modifie le comportement que lorsqu'il reçoit un message spécifique dont il se soucie.

Imaginez un scénario où vous êtes sur le passage piéton et où une voiture arrive rapidement. En tant qu'objet du cerveau, je détecte un facteur de stress. Je dis à l'hypothalamus d'envoyer de la corticotrophine. La glande pituitaire reçoit ce message et libère l'hormone corticotrophe surrénalienne. Les glandes surrénales reçoivent ce message et créent de l'adrénaline. Lorsque l'objet musculaire reçoit ce message d'adrénaline, il se contracte. Quand le coeur reçoit le même message, il bat plus vite. Toute une chaîne d'acteurs est impliquée dans le démarrage du comportement complexe du sprint dans la rue et ce sont les messages qui importent. L'objet cérébral sait comment amener l'hypothalamus à envoyer l'alerte, mais il ne connaît pas la chaîne d'objets qui finira par provoquer le comportement. De même, le cœur n'a aucune idée de l'origine de l'adrénaline,

Ainsi, dans cet exemple ( simplifié ), l’objet de la glande surrénale doit seulement savoir comment prendre de l’ACTH et produire de l’adrénaline. Cela n'a pas besoin de champs pour le faire, pourtant cela me semble toujours un objet.

Maintenant, si notre application est conçue uniquement pour courir dans la rue, je n’ai peut-être pas besoin de l’hypophyse et des objets de la glande surrénale. Ou j'ai seulement besoin d'un objet de l'hypophyse qui ne représente qu'une petite partie de ce que nous pourrions conceptuellement considérer comme le "modèle de l'hypophyse". Ces concepts existent tous en tant qu’entités conceptuelles, mais c’est un logiciel et nous pouvons créer AdrenalineSender ou MuscleContractor ou autre, et ne pas trop nous soucier de l’incomplétude de notre modèle.


4
Je suis d’accord avec le contenu réel de cette réponse, mais j’ai l’impression que cela comprenne mal la question. Plus précisément, la question inclut dans l'entité "ou un concept, quelque chose de bien défini". Les contre-exemples à ceci sont " MotorOperationsou MotorActions". De là, je suis assez confiant sur le fait que les conceptions de classe initiale et finale de l'exemple CoffeeMaker correspondent à la définition de "représenter une entité" donnée par le PO
Ben Aaronson

1
L'architecture système postmoderne DCI résout ce problème sans les abstractions extrêmes créées par des ingénieurs passionnés par la structure. L'ordinateur doit penser ce que pense l'utilisateur, et non l'inverse. fulloo.info/doku.php?id=what_is_dci
ciscoheat

@ BenAaronson Je pense que vous pouvez évoluer vers cet objet en tant que concept cohérent avec suffisamment d'efforts concertés, mais j'ai trouvé une tendance pour une entité-focus à forcer les éléments qui doivent être séparés. Les entités encouragent les frontières dans nos noms, ce qui est bien, mais elles apportent également cette notion de correction / complétude, qui a tendance à faire mal. En termes les plus ridicules, je suis pour un objet FirstNameValidator et contre un objet Name qui effectue également la validation des noms et prénoms.
Steve Jackson


2
Les objets traitent de messages - la réponse de Steve Jackson - c'est tout à fait correct. MOP n'est pas ce que l'on entend par "message" tel que conçu par le père de OO, Alan Kay, qui a déclaré que la grande idée était la messagerie . Et de plus, je suis désolé d’avoir forgé il ya bien longtemps le terme «objets» pour ce sujet car beaucoup de gens se focalisent sur la moindre idée.
radarbob

21

Les classes peuvent-elles représenter des objets sans entité? Sinon, pourquoi sont-ils mauvais / incomplets / non centrés sur la POO? Existe-t-il des moyens de les modifier / améliorer?

En bref, vous pouvez faire n'importe quoi, mais ce scénario spécifique serait contraire aux principes de la programmation orientée objet :)

Ce que vous décrivez est parfois appelé une classe "utilitaire" - généralement un signe d’odeur de code. Vous voulez éviter de créer des classes afin de garder certaines méthodes ensemble.

Tous les objets de votre application ne doivent pas nécessairement être liés à une entité réelle, comme un moteur ou une voiture. ce sont des objets métier. Dans votre application, vous utiliserez probablement un grand nombre de vos objets métier, mais vous aurez également besoin d'une plus grande séparation des autres opérations qui ne font pas partie d'entités commerciales, telles que celles que vous avez répertoriées.

Vous devriez jeter un coup d'œil aux modèles architecturaux courants, dont MVC (Model-View-Controller) .

Si je devais distribuer les méthodes que vous avez énumérées à l'aide de MVC, voici ce que je ferais:

Classe de vue:

  • GetMotorDataFromHTMLForm ()

Classe de modèle (moteur essentiellement):

  • GetMotorManufacturer ()
  • CanMotorHandleOperationConditions ()
  • CalculatePowerConsumption ()

Classe de contrôleur (MotorsController):

  • GetAllMotors ()
  • GetMotorById ()
  • GetMotorByUserRequirements ()

Il semble que vous utilisiez PHP. Laravel est un bon framework MVC à regarder . Dans leurs exemples, ils illustrent bien où appartiennent les méthodes.

Les principes GRASP et SOLID sont une autre source d’informations plus générique pour décider où les méthodes appartiennent .


Merci. En gros, il me semble que ce que j’ai est une classe de contrôleurs avec quelques impuretés mélangées (modèle, vue, etc.). Est -ce que cela veut dire que si je renomme MotorOperationspour MotorsControlleret le nettoyer un peu, ma collection de fonctions sera conforme à la POO?
Dennis

@ Dennis, pas nécessairement, jetez un coup d'œil à ma collection de méthodes dans chaque classe. Controller n'est pas une classe qui contient tout cela :) C'est la classe qui opère sur vos modèles, et rien de plus. Les seules dépendances d'un contrôleur seraient généralement directement DAL (Data Access Layer) ou des services qui vous donnent accès à DAL. Vous ne voulez jamais accéder à View à partir du contrôleur (exemple: getMotorDataFromHTMLForm). Au lieu de cela, votre vue doit être celle qui dépend du contrôleur.
Alexus

2
Pourriez-vous expliquer pourquoi une Utilsclasse serait un exemple d'odeur de code? Je suis simplement curieux, car j’ai moi-même aimé avoir des fonctions aléatoires dans une Utilsclasse plutôt que des fonctions autonomes. Selon mon expérience, le code est un peu plus lisible, mais mon expérience est limitée.
HC_

3
@HC_ Avoir une classe Utils revient à avoir un dossier "Divers" dans votre collection d'images. Cela indique que vous étiez paresseux pour attribuer des responsabilités à vos objets correctement / potentiellement des objets manquants et utiliser Utils pour compenser cela. Il existe un espace pour les classes Util, en particulier pour les fonctions statiques, et les extensions d’autres classes, mais avant de créer une collection de ce type, vérifiez si vous pouvez les incorporer dans vos classes POO appropriées :) Une autre raison est parfois qu’une classe ne peut avoir que une méthode. Mais pour aller de l'avant, vous devez en ajouter et la classe Utils devient un plus gros désordre.
Alexus

Je me retrouve souvent avec une bibliothèque Utils, mais j'essaie généralement de grouper et de nommer mes classes utils de manière plus descriptive. De nos jours, il existe de nombreuses bibliothèques "utilitaires communs" open source qui ont déjà des utilitaires à usage général dont la plupart des gens ont besoin, aussi je regarderais un peu avant d'écrire les vôtres.
Guy Schalnat

15

Les classes peuvent-elles représenter des objets sans entité?

Pouvez? Oui. Devrait? Probablement pas - ou du moins, pas comment vous formulez les choses.

Les objets sont réellement les meilleurs quand ils ne représentent pas directement un objet physique, car la réalité correspond rarement au code. Mais ils doivent représenter un concept cohérent ou un objet code. Ils doivent représenter une seule responsabilité cohérente.

Le simple regroupement d'un ensemble de fonctions liées de manière tangentielle constitue un espace de noms ou un module, et non un objet au sens de la programmation orientée objet. Celles-ci peuvent être utiles, mais elles ne sont pas identiques et nécessitent un type d'utilisation / de pensée différent pour une utilisation efficace.


3
bundling a bunch of tangentially related functions together is a namespace: cela ressemble plus à un paradigme procédural qu'à un objet.
Dennis

@dennis - exactement (ou fonctionnel si vous appelez cela un module). Les paradigmes de mélange peuvent être puissants. Ou cela peut être terriblement désordonné.
Telastyn

Ou les deux :) - - - - -
Alexus

@Dennis: Ni l'un ni l'autre - regrouper uniquement des fonctions liées de manière tangentielle est une pratique douteuse dans n'importe quel paradigme.
Sdenham

Je traite avec du code qui a commencé comme une base de code procédurale. À un moment donné, un effort de conversion en OOD a été fait, mais la plupart des classes ont été créées pour "contenir des fonctions et des méthodes", sans conception OO réelle. J'ai découvert pas mal de choses comme celle-ci qui tentent de combler le fossé entre les paradigmes mais ne sont ni dans l'un ni dans l'autre
Dennis

11

Une classe devrait modeler quelque chose - sinon c'est inutile. Cependant, ce qui est modélisé peut ne pas être une "chose" physique; au lieu de cela, il peut s'agir d'une représentation de quelque chose qui n'est pas «réel», mais qui est nécessaire pour contrôler le système modélisé. Par exemple, dans un système de contrôle des feux de signalisation, vous pourriez très bien avoir une sorte de classe ControlSignal, représentant un signal envoyé d’une partie du système à une autre pour indiquer qu’une action doit être effectuée. Dans "le monde réel", ces signaux pourraient consister en des impulsions électriques transmises par des fils d'un boîtier à un autre. Le processus de modélisation de quelque chose qui n'est pas "réel" en tant qu'objet concret est appelé "réification".

Bonne chance.


Oui, c'est presque exactement ce que j'aurais dit. Une classe n'est rien de plus qu'un modèle pour un nom . C'est ça. Ni plus ni moins. Une classe est un nom et les méthodes sont des verbes (ou des messages si vous préférez). Un ingénieur débutant qui pense en ces termes simples peut faire beaucoup de chemin avant que ces analogies ne disparaissent (contrairement à essayer de prétendre que les classes sont des descriptions d'objets physiques - une analogie qui commence à s'effondrer dans presque votre premier projet).
Calphool

7

Non (titre édité pour poser la question opposée!)

par exemple:

Public class MyRepository
{
    public MyObject GetObject(string id)
    {
        //get data from the DB and build an object
    }
}

ou

Public class MyService
{
    public MyObject3 ProcessData(MyObject1 obj1, MyObject2 obj2)
    {
         //perform a process which is not a sole responsiblity of obj1 or obj2
    }
}

Cependant, en général, l’idéal derrière la POO est de s’éloigner de la

public struct Car
{
    public Wheel[] Wheels;
}

public int CountWheelsOnCar(MyCarStruct car)
{
   return car.Wheels.Length;
}

à

public class Car
{
    private Wheel[] wheels;
    Public int CountWheels()
    {
        return this.wheels.Length;
    }
}

Voulez-vous dire qu'ils peuvent représenter des objets sans entité? (Voir le commentaire que j'ai laissé sur la question.)
Panzercrisis

3
Cela fait trop longtemps que je programme OO, je suppose - quand j'ai regardé MyRepository, j'ai immédiatement imaginé un bol en verre sur ma commode avec un tas de pièces et de la merde dedans. Attrapez-vous et prenez un penny ou un bouton ....
Bill K

@pan oui, comme le service et le repo dans mon exemple
Ewan le

@ bill vous fou vieux fou! C'est la classe MyButtonAndOrPennyBowl! nettoyer le code ftw
Ewan

1
Votre deuxième exemple me semble être une fonction déguisée en objet, ce qui n’est pas (à mon avis) justifié en soi, bien qu’il puisse exister une autre justification (par exemple, si les fonctions ne sont pas des entités de premier ordre dans le langage. )
sdenham

5

Je pense que visualiser quelque chose dans le monde réel est utile lors du codage des classes, mais pas nécessaire.

En fait, selon votre niveau de littéralité, de nombreux objets avec lesquels nous travaillons n'ont aucune représentation physique. Par exemple, considérons l'architecture MVC. Dans le monde réel, il n'y a pas de modèle ou de contrôleur, même s'ils sont généralement représentés par des classes. Les trois ensemble représentent souvent quelque chose, mais pas toujours - mais comme je l'ai dit, vous pourriez probablement forcer un ajustement dans quelque chose si vous le voulez vraiment (et être capable d'imaginer quelque chose aide! Je visualise la plupart des objets d'une manière ou d'une autre - mais pas n'importe quoi vous verriez jamais dans le monde réel).

La plupart de ces "règles" que vous apprendrez sur OO ne sont que des instructions destinées à vous aider à penser en OO et pas nécessairement aux choses qui vous inquiètent une fois que vous l'utilisez pour coder quotidiennement.

En passant, OO en soi n'est pas une panacée et cela ne vous aide pas beaucoup lors de votre première tentative de codage d'une solution, mais je pense que si c'est bien fait, c'est un moyen vraiment fantastique d'organiser le code pour qu'il puisse être plus facilement compris plus tard. L'écriture de code maintenable est probablement l'une des tâches les plus difficiles du développement logiciel et, dans de nombreux cas (tout ce qui nécessite un débogage / une maintenance continus), elle est de loin la plus importante.


5

Un objet doit-il représenter une entité?

Question: Quelle entité a Loggerreprésente?

Pas métaphoriquement - littéralement.

Lors de l'explication de la programmation orientée objet aux étudiants, il est utile d'expliquer les objets avec des analogies avec le monde physique.

Alan Kay - l'un des pères de la POO - a écrit ce qui suit:

[...]

La conception originale de celui-ci avait les parties suivantes.

  • Je pensais à des objets ressemblant à des cellules biologiques et / ou à des ordinateurs individuels sur un réseau, capables uniquement de communiquer avec des messages
  • Je voulais me débarrasser des données.

[...]

La POO signifie uniquement la messagerie, la rétention et la protection locales et

dissimulation du processus de l'État et liaison tardive extrême de toutes choses.

architecture HW presque incroyable. J'ai réalisé que le

une métaphore cellule / ordinateur complet se débarrasserait des données

la source

De là, les objets sont mieux compris comme

  • objets autarciques encapsulant / cachant des données

  • communiquer avec d'autres objets via des messages

Les classes peuvent-elles représenter des objets sans entité?

Certainement: penser à Math


Concernant votre exemple:

Exemple: une classe peut-elle s'appeler MotorOperations ou MotorActions, où il n'y a pas d'entité, mais les méthodes à l'intérieur de la classe font des choses comme

  • getMotorDataFromHTMLForm ()

  • getMotorManufacturers ()

  • selectMotorFromUserRequirements (exigences en dollars)

  • canMotorCanHandleOperatingConditions ($ conditions)

  • computePowerConsumptionForMotor ($ id)

Pour décider où mettre ces méthodes, vous devez regarder responsibilities: qui est responsable de quoi .

getMotorDataFromHTMLForm ()

Le contexte d'une telle méthode serait la construction d'un objet-moteur . Il n’est pas de la responsabilité du moteur de se créer à partir de données récupérées via un formulaire . Il y a au moins deux objets impliqués; l'un est le moteur et l'autre est le créateur du moteur .

getMotorManufacturers ()

Le contexte typique dans lequel on écrirait une telle méthode est un service.

selectMotorFromUserRequirements (exigences en dollars)

Ceci serait aussi utilisé dans un servicecontexte

canMotorCanHandleOperatingConditions ($ conditions)

Ceci est une question à un motorobjet

computePowerConsumptionForMotor ($ id)

C’est aussi une question qu'il vaut mieux poser à un moteur lui-même.


tl; dr

La métaphore objectscomme des objets physiquement est plus irritant qu'utile.


wow votre réponse donne un peu de vie à la POO! Je dois dire que je ne voulais pas dire physique comme une fin à tout. L’intention de ma question était davantage la suivante: "un objet doit-il être thingassocié à des données dans lesquelles les données appartiennent clairement à la chose et dont les fonctions agissent clairement sur les données qui appartiennent à la chose"? Ainsi, Logger dans ce cas, bien qu’il ne s’agisse pas d’une chose physique, c’est un concept qui ressemble à celui de "journal de bord physique". Si des données essentielles à son état, et non seulement transitoires, dépendent de la mise en œuvre et de l'interprétation ... et plus
Dennis

mais oui, les réponses devaient tenir compte de mes préjugés physiques
Dennis

3

Oui, tu peux faire ça. Mais vous créez essentiellement une classe fournissant les mêmes fonctionnalités qu'une bibliothèque procédurale. La seule raison de le faire est que votre langage manque de modules procéduraux (par exemple, Java ou Ruby).

Dans un langage avec des modules procéduraux (je pense que PHP a des modules procéduraux), vous pouvez envisager d'utiliser simplement un module procédural.

Vous pouvez également envisager de redéfinir votre classe afin qu'une instance de la classe représente un objet cohérent.

Mais n'utilisez la notation OO que lorsque cela vous donne une puissance supplémentaire, pas seulement pour le plaisir d'être OO!


3

En termes simples

  • Ce que vous décrivez s'appelle une classe utilitaire.
  • Il n'a pas d'état, ce qui signifie que vous n'en aurez jamais vraiment besoin plusieurs fois.
  • Toutes les méthodes sont statiques, ce qui signifie que vous devez tout passer comme paramètres.

De telles classes existent. Par exemple, le kit SDK Java contient la classe Collections, composée exclusivement de méthodes statiques qui fonctionnent sur les collections ou les renvoient.

Donc, la réponse serait non, il n'est pas nécessaire que toutes les classes soient modélisées à partir d'une entité de domaine.

D'autre part, ces classes ne sont que peu nombreuses ou devraient l'être dans un programme créé dans un langage POO, car le pouvoir réel de la POO réside dans le polymorphisme et l'encapsulation.

Ce serait comme utiliser un avion pour aller d'un endroit à un autre, pas en volant mais en le conduisant sur des autoroutes. Les avions ont des roues comme les voitures, mais elles sont destinées à voler.


2

Non, une classe représente simplement quelque chose qui peut être instancié, a des membres et dont on peut hériter.

En fait, votre langue peut avoir des classes statiques, qui ne sont même pas instanciées plus d'une fois.

.NETMath est un excellent exemple de classe "professionnelle" qui ne représente aucune entité (à moins que vous ne souhaitiez avoir une idée philosophique de ce que sont les mathématiques ...), et illustre également un cas d'utilisation légitime d'une telle classe. Il ne comporte que des méthodes et 2 champs (les deux représentant des constantes individuelles).

La hiérarchie de classes d'une bibliothèque similaire Math.Netregroupe les méthodes mathématiques / numériques en classes par type. Ici, les classes ne représentent pas une entité, mais une catégorie logique.

Moi-même, je finis souvent par créer des classes (statiques) qui ne sont rien d'autre qu'un sachet de fonctions connexes (statiques) ou un ensemble de constantes regroupées de manière pratique dans un emplacement central. Je ne dirais pas que c'est un bon design, mais c'est parfois la solution la plus simple.


1
Le fait que les méthodes liées aux mathématiques soient placées dans .NET / BCL dans une classe distincte en tant que méthodes statiques n'est pas une considération de nécessité ou de conception, mais une conséquence du fait qu'il n'y a pas de méthodes autonomes en C #. En C ++, de telles fonctions pourraient simplement être regroupées dans un espace de noms.
Vlad

1

Les réponses à vos questions dépendent en définitive de la précision avec laquelle on définit des termes tels que "classe" et "entité". Vous avez bien défini ce dernier en permettant des entités physiques et conceptuelles. Mais le terme "classe" sera toujours pour les puristes "une fabrique pour instancier des objets avec une représentation interne particulière" et pour les pragmatiques, le terme englobera les éléments Java ou C ++ méprisés par les puristes. Idem pour le terme "OOP", ce que les pragmatiques pourraient dire, Java et C ++, mais que les puristes prendraient pour signifier ce que Alan Kay voulait dire quand il a remarqué ["J'ai inventé le terme orienté objet, et je peux vous dire que je ne l'ai pas C ++ à l'esprit "] ( Qu'est-ce que * Alan * a réellement voulu dire par" orienté objet "? ).

Si vous adoptez une vue pragmatique, vous pouvez accepter vos classes d’utilitaires sans instance. Mais le point de vue puriste est plus intéressant. OOP, selon Kay, était toujours plus sur les messages que les classes. Donc à vos questions:

Les classes peuvent-elles représenter des objets sans entité?

Les classes classifient les objets. Les classes sont par définition les entités auxquelles vous envoyez un message, par exemple newpour produire un objet. Un objet est une entité constituée d'une classe. Les classes existent pour fabriquer et même classifier des objets. C'est ce que font les classes. Les classes font des objets. Nous utilisons des classes pour classifier les objets. Donc, si C est juste un ensemble de méthodes qui ne permet pas l'instanciation ou le sous-classement, il ne peut y avoir aucun objet classé par C, donc C n'est pas une classe.

Sinon, pourquoi sont-ils mauvais / incomplets / non centrés sur la POO?

Ils ne sont pas mauvais. Il suffit de ne pas les appeler des cours. Un ensemble de méthodes est OOPable: vous pouvez envoyer un message pour invoquer une méthode, mais ce n'est pas une classe sauf si elle peut instancier un objet. Connais-tu Ruby? En Ruby, un module est un ensemble de méthodes. Une classe est un module qui peut instancier des objets. Il n'y a rien de mal à propos d'un module . Mais ce qui distingue une classe d’un module (en termes purement POO), c’est qu’une classe peut avoir des instances. Un module est juste quelques méthodes. La confusion est que C ++ et Java et d'autres langages utilisent le terme "classe" pour la classe et le module .

Maintenant, pour examiner l'un de vos exemples spécifiques, vous posez des questions sur une MotorOperationsclasse à laquelle vous pouvez envoyer le message computePowerConsumptionForMotoravec argument id. Est-ce mauvais? Au moins, cela ne viole pas le principe Dire, ne pas demander . Est - ce que nous devons faire une classe de moteur et l' envoyer le powerConsumptionmessage? Peut-être pas dans 100% des cas, mais peut-être qu'essayer de faire de telles choses mènera à de bonnes idées sur votre code. Ou bien, cela peut conduire à une explosion de petites classes qui seraient mauvaises.

Existe-t-il des moyens de les modifier / améliorer conceptuellement pour les rendre conformes à la POO?

Si "faire de la programmation orientée objet" est important pour vous, vous devez rechercher des moyens d'architecter un système en composants qui communiquent en s'envoyant des messages. C’est justement ce que la programmation cible est , ou du moins ce que le coiner du terme avait en tête. Les classes d’utilité ne sont pas une POO dans cette vue. Mais pour certaines personnes, ils peuvent être.

Essayer de créer un grand système à partir de millions de vies, de respirations, d’objets, tous instanciés à partir de classes, peut convenir à certains projets. Mais si vous créez des classes artificielles et erronées, des modules doivent être introduits. Essayez de mettre l'accent sur les classes et d'utiliser des modules lorsque les classes instanciables seraient ridicules.

TL; DR - Les ensembles de méthodes ne sont pas toujours mauvais. Essayez d’utiliser d’abord des classes instanciables. Retourner aux "modules" uniquement lorsque cela est nécessaire.


0

Prenant les exemples donnés:

getMotorDataFromHTMLForm()
selectMotorFromUserRequirements($requirements)

Celles-ci ressemblent à des méthodes "d'usine", qui renverraient un Motorobjet. La seconde implique soit que vous créez un nouvel objet pour répondre aux exigences, soit que vous examinez une base de données ou une collection de moteurs en mémoire. Dans ce cas, cela devrait être une méthode. Ou cela pourrait être une méthode sur l'objet des exigences.

getMotorManufacturers()

D'où les obtenez-vous? C'est ce que cela devrait être une méthode de.

canMotorCanHandleOperatingConditions($conditions)
computePowerConsumptionForMotor($id)

Celles-ci semblent être des méthodes Motor.


Oui. c'est un "ensemble de méthodes éventuellement non liées" (BOPUM en abrégé). Je suis d'accord avec les commentaires de l'usine et du moteur. getMotorManufacturersest de renvoyer tous les fabricants de moteurs de la base de données. Je ne sais pas où cela va. Il me faudra un certain temps pour démêler ce BOPUM afin de mettre les choses là où elles doivent aller.
Dennis

Je reçois getMotorManufacturersde la base de données. La base de données ne peut pas avoir de méthode ... Actuellement, j'ai un modèle DataMapper qui interroge la base de données, initialise un tableau et le remplit avec des objets de moteur (contenant également des informations sur le fabricant), puis renvoie ce tableau à l'appelant. L'appelant est ma MotorOperationsclasse, qui à son tour est appelée à partir d'une ProductSelectionclasse (qui contient un algorithme utilisé pour sélectionner les moteurs, et les informations de moteur chargées correspondent aux données de cet algorithme)
Dennis

0

Un objet est un ensemble de méthodes et de données à forte cohésion. Ils appartiennent à une classe parce qu'ils sont fortement interdépendants et que leur état est conservé.

Cela est vrai que vous utilisiez une conception très sophistiquée et que vous tentiez de tout modéliser, ou une conception émergente dans laquelle vous effectuez une itération et faites évoluer l'objet en ce qui correspond aux besoins du système à ce moment-là.

Si vous n'avez aucune raison de conserver l'état, vous n'avez probablement aucune raison d'instancier un objet, ce qui signifie qu'il n'y a probablement aucune raison d'avoir une classe. Sauf si la langue que vous utilisez n'a pas la capacité de définir un espace de nom autre que class. Dans quelle classe utiliser devrait être bon parce que ce serait idiomatique.

Je ne peux penser à aucun aspect négatif à utiliser des classes de cette manière autre que le type. Votre coût et votre complexité inutiles en invitant à instancier un "espace de noms". Toute personne prenant en charge ce code se demandera où les données coûtent une charge cognitive supplémentaire (très probablement un coût ponctuel par personne). C'est un usage inhabituel sans aucune valeur supplémentaire.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.