2010-04-12 7 views
4

Je sais que dans OOP vous voulez que chaque objet (d'une classe) soit une "chose", par exemple. utilisateur, validateur etc.Comment concevoir les modèles de la manière correcte: Orienté objet ou "Package"-orienté?

Je connais les bases de MVC, comment les différentes parties interagissent les unes avec les autres.

Cependant, je me demande si les modèles dans MVC devraient être conçus selon la conception OOP traditionnelle, c'est-à-dire, chaque modèle devrait-il être une base de données/table/rangée (solution 2)?

Ou est l'intention plus de recueillir des méthodes qui affectent la même table ou un tas de tables connexes (solution 1).

exemple pour un module de carnet d'adresses dans CodeIgniter, où je veux pouvoir "CRUD" un contact et l'ajouter/le retirer d'un groupe de contact CRUD-able.

solution Models 1: bottelage toutes les méthodes liées ensemble (objet non réel, au lieu d'un "package")

class Contacts extends Model { 

    function create_contact() {) 
    function read_contact() {} 
    function update_contact() {} 
    function delete_contact() {} 

    function add_contact_to_group() {} 
    function delete_contact_from_group() {} 

    function create_group() {} 
    function read_group() {} 
    function update_group() {} 
    function delete_group() {} 

} 

solution Modèles 2: la voie OOP (une classe par fichier)

class Contact extends Model { 
    private $name = ''; 
    private $id = ''; 

    function create_contact() {) 
    function read_contact() {} 
    function update_contact() {} 
    function delete_contact() {} 

} 

class ContactGroup extends Model { 
    private $name = ''; 
    private $id = ''; 

    function add_contact_to_group() {} 
    function delete_contact_from_group() {} 

    function create_group() {} 
    function read_group() {} 
    function update_group() {} 
    function delete_group() {} 

} 

Je ne sais pas comment penser quand je veux créer les modèles. et les exemples ci-dessus sont mes vraies tâches pour créer un carnet d'adresses. Dois-je regrouper toutes les fonctions ensemble dans une classe. alors la classe contient une logique différente (contact et groupe), elle ne peut donc pas contenir de propriétés spécifiques à l'un ou à l'autre.

la solution 2 fonctionne selon la POO. mais je ne sais pas pourquoi je devrais faire une telle division. quels seraient les avantages d'avoir un objet Contact par exemple. Ce n'est sûrement pas un objet Utilisateur, alors pourquoi un Contact devrait-il "vivre" avec son propre état (propriétés et méthodes)? Parce que j'ai tendance à penser comme ceci: Si quelque chose a besoin d'un état, alors je crée une classe POO afin que les méthodes puissent affecter l'état ou d'autres choses basées sur l'état.

De même, les modèles doivent-ils être "en état"? Si elles ne nécessitent aucun état, pourquoi devrais-je le créer selon le modèle de POO. Ensuite, je pourrais tout regrouper comme la solution "paquet".

vous les gars expérimentés avec POO/MVC, s'il vous plaît donner un éclairage sur la façon dont on devrait penser dans cette tâche très concrète (et en général lors de la création d'un modèle)

EDIT: VENEZ penser à des contrôleurs dans MVC. ils sont créés en fonction de la solution "package". Je me demande ...

Répondre

2

base de données/table/ligne (solution 2)?

Non Ne liez pas la définition d'un modèle à sa méthode de persistance. Bien que pour des applications simples, vous puissiez étendre un modèle à partir d'un objet de ligne de base de données, vous devez les garder au moins mentalement séparés. Les modèles sont simplement des représentations d'entités dans votre domaine, donc par nécessité ils ont un état. Lorsque vous parlez d'un modèle Contact, vous parlez réellement d'un mappeur ou d'une passerelle, c'est-à-dire de l'objet qui récupère votre modèle dans le magasin de données. Il est regrettable que tant d'implémentations ad hoc d'Active Record aient brouillé les cartes. Les mappeurs peuvent être implémentés en tant que collection de fonctions statiques ou en tant qu'objet. Toutefois, la collection est moins flexible si vous souhaitez étendre ou modifier le comportement pour une raison quelconque (par exemple en vous moquant des tests unitaires). Le modèle lui-même devrait simplement être une collection de données, soit stockées comme propriétés publiques, soit de préférence avec appropriées setters et getters (ne pas simplement définir une paire de fonctions get/set pour chaque variable ou vous pourriez aussi bien laissez-les publics), ainsi que d'autres méthodes qui fonctionnent sur les données. Il ne devrait pas avoir de concept ou de dépendance sur le magasin de données. Il est de la responsabilité du mappeur d'instancier et d'initialiser le modèle via son interface. Cela vous procurera de la flexibilité dans la façon de créer et de sauvegarder vos modèles. Vous pouvez le faire depuis la base de données, un fichier XML, en code, à partir d'un flux sérialisé envoyé sur le réseau, tout ce qui flotte réellement sur votre bateau, en remplaçant un mappeur différent, et le modèle reste complètement inconscient.

+0

Je pense que je comprends votre point de vue. mais est le code sql pour récupérer/insérer des lignes de/vers la base de données dans le mapper_model ou les data_models?Pourquoi devrais-je récupérer les données de mysql et les mettre dans le data_model (chaque objet représentant un contact) via un mappeur? à quoi ça sert? ou ai-je mal compris le flux? CONTROLLER appelle MAPPER_MODEL qui récupère les données de MYSQL et les place dans DATA_MODEL? Je pense que je me trompe. pourriez-vous expliquer le flux pour moi. –

+0

Vous avez raison. Le contrôleur appelle le mappeur (généralement indirectement via un service ou en invoquant un autre modèle en fonction de la distance que vous voulez prendre) et demande un modèle. Le mappeur crée le modèle, le remplit et le renvoie. Le but est l'abstraction; il protège le modèle des modifications apportées au magasin de données. Le code MySQL appartient au mappeur, le modèle ne devrait rien savoir à ce propos. Si vous avez décidé de stocker vos données dans un format différent plus tard, disons XML, vous écrivez un mappeur qui analyse les fichiers XML et renvoie le modèle. De cette façon, toute la logique de persistance est encapsulée. – Duncan

+0

cela me semble tellement logique maintenant! donc fondamentalement je devrais nommer mes cartographes à n'importe quelle couche de données qu'ils utilisent, par exemple. "xml_mapper_model", "mysql_mapper_model". de cette façon particulière, je pourrais utiliser n'importe quel stockage de données que je préfère. et les modèles de données sont "contact_model" et "contact_group_model". c'est comme la matrice .. chaque programme est un "être humain" responsable d'une seule tâche. nous avons eu le «portier», le «fabricant de clés», les «gardes de sécurité» et ainsi de suite. donc une application entière est juste un groupe de ces objets communiquant avec/déléguant à des tâches les uns les autres. aussi comme un gouvernement militaire =) –

2

Je ne sais pas s'il y a une meilleure façon , mais je vais partager la façon dont je le fais ...

J'ai une passerelle de table par exemple ContactTableGateway qui contient tout le sql pour traiter avec des contacts. J'aime que tous les sql soient en un seul endroit. Puis j'ai une classe de contact qui a simplement des getters et des setters (ou des propriétés publiques).Les objets de cette classe sont utilisés comme arguments pour la passerelle de table pour enregistrer/créer

class Contact extends Model { 

    function getName() 
    function getAddress() 
    function getEmail() 
    .... 

} 

Heres un exemple simplifié

if (isset($_POST)) { 

    // some validation here 
    $contact = new Contact; 
    $contact->name = $_POST['name']; 
    $contact->email = $_POST['email'] 
    $contactTableGateway = new ContactTableGateway; 

    if ($contactTableGateway->createContact($contact)) { 
     echo "YAY"; 
    } 
} 
+0

merci de partager! on dirait que vous allez avec la solution OOP :) et il semble assez élégant. que diriez-vous de vos contrôleurs, sont-ils plus comme des paquets, ou aussi orientés objet? –

+0

je ne suis pas sûr de ce que vous voulez dire. site.com/contact/create = crée une méthode sur le contrôleur de contact. site.com/contact/view/3/ = voir la méthode sur le contrôleur de contact, en regardant le contact avec l'ID: 3 – Galen

+0

oh peu importe avec les contrôleurs :) vous avez les propriétés publiques dans la classe Contact? Cause else, le ContactTableGateway CANT y accède. mais je ne veux jamais que mes propriétés soient directement accessibles mais privées afin qu'elles puissent seulement être accédées par des setters/getters. complication. –

1

Je pense que votre solution # 2 est supérieur car il est plus moléculaire/modulaire, donc , plus compréhensible, flexible et extensible (dans le domaine OOP). Il est également plus convivial pour les ressources car il peut vous permettre de charger la classe Contact uniquement lorsqu'aucune fonctionnalité de groupe de contact n'est requise et vice-versa. C'est l'avantage de la division.

Si les modèles ne nécessitent aucun état, cela ne signifie pas que le POO/MVC ne s'applique pas. Les modèles de table peuvent n'avoir aucun état dans la conception, mais c'est pourquoi nous avons des méthodes/membres statiques, c'est-à-dire Contact :: read ($ id).

Questions connexes