tags:

views:

81

answers:

3

I know that in OOP you want every object (from a class) to be a "thing", eg. user, validator etc.

I know the basics about MVC, how they different parts interact with each other.

However, i wonder if the models in MVC should be designed according to the traditional OOP design, that is to say, should every model be a database/table/row (solution 2)?

Or is the intention more like to collect methods that are affecting the same table or a bunch of related tables (solution 1).

example for an Address book module in CodeIgniter, where i want be able to "CRUD" a Contact and add/remove it to/from a CRUD-able Contact Group.

Models solution 1: bunching all related methods together (not real object, rather a "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() {}

}

Models solution 2: the OOP way (one class per file)

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() {}

}

i dont know how to think when i want to create the models. and the above examples are my real tasks for creating an Address book. Should i just bunch all functions together in one class. then the class contains different logic (contact and group), so it can not hold properties that are specific for either one of them.

the solution 2 works according to the OOP. but i dont know why i should make such a dividing. what would the benefits be to have a Contact object for example. Its surely not a User object, so why should a Contact "live" with its own state (properties and methods). Cause i tend to think like this: If something needs a state, then i create a OOP class so that the methods could affect the state or other things based on the state.

so should models be "stateful" too? if they require no state, why should i create it according to the OOP pattern. then i could just bunch it all together like the "package" solution.

you experienced guys with OOP/MVC, please shed a light on how one should think here in this very concrete task (and in general when creating a model)

EDIT: come to think about Controllers in MVC. they are created according to the "package" solution. It makes me wonder...

+2  A: 

I don't know if there's a best way, but i'll share the way i do it...

I have a table gateway e.g. ContactTableGateway that contains all the sql for dealing with contacts. I like all the sql being in one place.

class ContactTableGateway extends Model {

    function saveContact( Contact $contact )
    function getContact ( $contact_id )
    function createContact ( Contact $contact )

}

Then i have a contact class that basically just has getters and setters ( or public properties ). Objects of this class are used as arguments for the table gateway to save/create

class Contact extends Model {

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

}

Heres a simplified example

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";
    }
}
Galen
thanks for sharing! it sure looks like you are going with the OOP solution:) and it looks quite elegant. how about your controllers, are they more like packages, or also object-oriented?
never_had_a_name
im not sure what you mean. site.com/contact/create = create method on contact controller. site.com/contact/view/3/ = view method on contact controller, viewing contact with id: 3
Galen
oh never mind with the controllers:) you got the public properties in Contact class? cause else, the ContactTableGateway CANT access them. but i never wants my properties to be directly accessible but private so they could be only accessed through setters/getters. complication.
never_had_a_name
make them all private and add getters/setters =)
Galen
good point!! :)
never_had_a_name
+1  A: 

I think your Solution #2 is superior as it's more molecular/modular, therefore, more understandable, flexible and extensible (in the OOP domain). It's also more resource friendly as it could allow you to only have to load the Contact class when no contact group functionality is required and vice-versa. That is the benefit of division.

If models need no state, that does not mean OOP/MVC does not apply. Table models may have no state in one's design but that is why we have static methods/members, i.e., Contact::read($id).

webbiedave
+2  A: 

should every model be a database/table/row (solution 2)?

No. Don't tie the definition of a model to its method of persistence. Although for simple applications you might extend a model from a database row object, you should keep them at least mentally separated.

Models are simply representations of entities in your domain, so by necessity they have state. Where you talk about a Contact model, you are really talking about a mapper or gateway, i.e. the object retrieving your model from the data store. It's unfortunate that so many ad hoc implementations of Active Record have muddied the waters on this.

Mappers can be implemented as a collection of static functions or as an object - however, the collection is less flexible if you want to extend or alter the behaviour for any reason (such as mocking for unit testing).

The model itself should simply be a collection of data, either stored as public properties or preferably with appropriate setters and getters (please don't just define a get/set function pair for every variable or you might as well just leave them public), along with other methods that operate on the data. It should have no concept of, or dependency on, the data store. It is the responsibility of the mapper to instantiate and initialize the model through its interface. Doing this will afford flexibility in how you can create and save your models. You can do it from the database, an XML file, in-code, from a serialized stream sent in over the network, whatever floats your boat really, all by substituting a different mapper, and the model remains completely unaware.

Duncan
i think i get your point. but is the sql code to retrieve/insert rows from/to the database in the mapper_model or the data_models? why should i retrieve data from mysql and put it in the data_model (each object representing a contact) through a mapper? what's the point? or have i misunderstood the flow? CONTROLLER calls MAPPER_MODEL which retrieves data from MYSQL and put it in DATA_MODEL? I think im wrong. could you explain the flow for me.
never_had_a_name
You've got it right. The controller calls the mapper (usually indirectly through a service or invoking another model depending how far you want to take things) and asks for a model. The mapper creates the model, populates it and returns it. The purpose is abstraction; it shields the model from changes to the data store. The MySQL code belongs with the mapper, the model should know nothing about it. If you decided to store your data in a different format later, let's say XML, then you write a mapper which parses XML files and returns the model. That way all persistence logic is encapsulated.
Duncan
it makes so much sense to me now! so basically i should name my mappers to whatever data layer they are using, eg. "xml_mapper_model", "mysql_mapper_model". in this particular way, i could use whatever data storage i prefer. and the data models are the "contact_model" and "contact_group_model". its like the matrix..every program is a "human beeing" responsible for one task only. we got the "gatekeeper", the "key maker", the "security guards" and so on. so a whole application is just a bunch of these objects communicating with/delegating to tasks each other. also like a military government=)
never_had_a_name
but i've heard people say that often a way to code is to make one model for each table. and then have one controller with the same name. so users_controller -> users_model -> users_table. that is the RoR way of doing it they state. what is your opinions regarding this? and how does this impact with the "mapper_models" and the "data_models". would be great if you could use my example for this too.
never_had_a_name