Refactoring your legacy code - Part Three: View me!

And there we are again - today we will take a deeper look into the views.

It is important to decide which classes are critical to test and which classes only deal with retrieving information. The MVC pattern is the answer. It separates logic from presentation. View classes only “reroute” the information and Controller classes host all the logic.

Decoupling Models from the Views is vital for your tests. For the model you need to have nice unit tests. The Views should be tested by acceptance tests. Some people do also run unit tests on the Views - it is possible - but my personal opinion on this issue is that you really should try to avoid logic in the view and then it’s sufficient to test them via selenium tests.

This is why we created a new rule in effect – no logics in view classes, just getters and setters for controllers and super global wrappers.

Let me give you a good hint: do never ever use the accessor methods for the super globals from the model classes. Let it be $REQUEST, $COOKIES or even $SESSION. All these parameter should be collected in the view and passed on to the model. Doing so gives you the chance to have small, clear and decoupled functions and also your tests can be done very easy.

Let’s see how this could look like before:

class displayUserDetails()
{
    /**
     *  Processes input and sends user first name, last name to display;
     */
    function show() {
        global $dbLink;
        global $templateEngine;
        $itemId = (int) $_REQUEST['user_id'];
 
        $firstName = $dbLink->getOne("select first_name from users where id = $itemId");
        $lastName = $dbLink->getOne("select last_name from users where id = $itemId");
 
        $templateEngine->addTemplateVar('firstName', $firstName);
        $templateEngine->addTemplateVar('lastName', $lastName);
        $templateEngine->display();
    }
}

and after refactoring you should get something similar:

/**
 * A view class responsible for displaying user details. 
 */
class userView()
{
    /**
     * Loads user object and sends first name, last name to display
     */
    public function show()
    {
        $userId = $this->_inputProcessor->getParameter("user_id");
 
        $this->templateEngine->addTemplateVar('user', $this->model->loadUser(userId));
        $this->templateEngine->display();
    }
}
 
/**
 * And the corresponding model
 */
class userModel()
{
	public function loadUser($userId) 
	{
		$user = new User( $userId );
 
        return array( 'firstName' => $user->getFirstName(),
        			  'lastName' => $user->getLastName());	
	}
}

And - as usual thanks to Tomas who provided this time the examples.

Comments

Leave a Reply