Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I like to keep my code testable and have decided to go with the Dependency-Injection strategy for my current MVC framework, which definitely has proven to be a great way to ensure loosely coupled code, testability and modularity.

But as being far from a master at Design patterns, I have a hard time of figuring out a good way of keeping my Models as loosely coupled from the Database connector classes, as possible.

How can this done?
As I haven't provided any physical code along with this question, I would really appreciate some logic/code examples or info that could point me into a direction to understand the above described issue.

share|improve this question

migrated from stackoverflow.com Aug 9 '11 at 10:14

This question came from our site for professional and enthusiast programmers.

    
This question belongs on Programmers, as it is more about the structuring and thinking around this topic, more than it is about implementing it in code. –  Lasse V. Karlsen Aug 9 '11 at 10:14
add comment

3 Answers

up vote 6 down vote accepted

One way is to design your models before you design your database. When designing your models, the focus is on capturing the business logic and meanings within the problem domain. This should be captured in a way which makes sense to the business, including more than just entities and data fields. Some data elements are interpreted from others, some are contingent upon others, etc. Additionally you'd add to this model any basic logic you need, such as how an object internally responds when a certain element is set to a certain value.

It's entirely likely that you'll end up with something that's 90+% identical to how you end up persisting the data. That's fine. It can be completely identical without being coupled.

Note also that modeling the domain in a fog of true persistence ignorance is a bit of a holy grail for software design. If you can do it, fantastic. But if the problem domain is at all significant and has any complexity to it then it's still a good idea to step back from the domain modeling from time to time in order to do a sanity check on data persistence to make sure you haven't painted yourself into a corner.

Just remember the actual roles of the various components and keep those roles separated when you design them. For any given design decision, ask yourself if any of those roles are violated:

  1. Database - Store the data, maintain the integrity of the data, maintain the data at rest.
  2. Models - Contain the business logic, model the problem domain, maintain the data in motion, respond to business-level events, etc.
  3. Views - Present data to users, perform user-side logic (basic validation before true validation is performed in the models, etc.).
  4. Controllers - Respond to user events, pass control to models, route requests and return responses.
share|improve this answer
    
Hi David. Thanks for your extensive reply! Whilst maintaining a high level of loose couplings, how would you connect the models with a database connector? –  Industrial Aug 8 '11 at 18:33
    
@Industrial: There are a number of ways to connect models to persistence, but so far the only method I've found which truly satisfies my desire to separate concerns is to have repository interfaces in the domain which are externally implemented by a DAL. The repository methods accept and return domain models, and internally converts between those and any generated database entities. (To be honest, I haven't done this much in PHP.) So you can use a DAL framework to auto-generate all your DB CRUD, etc. and then write your repositories as an interface between that stuff and your models. –  David Aug 8 '11 at 19:23
    
@Industrial: For example, if you use an ORM, then that ORM would be referenced by your DAL (which is isolated from the domain models) and would transform your models into data access accordingly. Or if you do direct database access with manual SQL, you'd do that in your DAL's repository methods and translate the results of the SQL queries into domain models before returning them. –  David Aug 8 '11 at 19:25
    
@Industrial: Keep in mind also that the repository methods don't have to just be CRUD. Lots of intelligence can be baked into that code. A lot of the more complex ones can have a lot of internal code which transforms data from the database. Or, if the complex ones involve many trips to the database, then for performance gains you can put the logic in a stored procedure and the DAL method just passes through to that procedure and translates the results into models. –  David Aug 8 '11 at 19:26
    
Hi David! Just wanted to thank you again for this answer. Definitely one of the best I've received on StackExchange! –  Industrial Aug 24 '11 at 8:02
add comment

Remember, MVC arose in smalltalk, which has automatic persistence for all objects. So the MVC pattern doesn't prescribe any solution for model/persistence separation.

My preference is to provide a "Repository" object that knows how to create Model objects from the database and store Model objects to the database. Then the Model knows nothing about persistence. Some user action will have to trigger a save though, so it's likely the Controller will know about the Repository. I usually use some form of Dependency Injection to keep the Controller from being coupled to the Repository.

share|improve this answer
add comment

You want to have two things.

  1. Your Models (accessors to the DBAL and doing most of the app logic).
  2. Your "Domain Models" aka Data Entities, these represent the entities of your system such as users, posts, products etc.

    class PPI_Model_User {
    
        protected $_conn = null;
    
        function __construct(array $options = array()) {
            if(isset($options['dsnData'])) {
                $this->_conn = new PPI_DataSource_PDO($options['dsnData']);
            }
        }
    
        function getAll() {
            $rows = $this->_connect->query("SELECT .....")->fetchAll();
            $users = array();
            foreach($rows as $row) {
                $users[] = new PPI_Entity_User($row);
            }
            return $users;
        }
    
    }
    

Usage Code

    $model = new PPI_Model_User(array('dsnData' => $dsnData));
    $users = $model->getAll();
    foreach($users as $user) {
        echo $user->getFirstName();
    }

There you have it, thats how you create domain models (Entities) and have MVC models doing the DB connectivity and data manipulation.

If you're wondering what PPI is, google for "PPI Framework".

Good luck with your search.

Regards, Paul Dragoonis.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.