Base Model View Controller (Base MVC) - Part 1

1 | 927

Model View Controller (MVC) has been around for a while and it's a good design pattern as it separates the data, user interface and business logic. MVC enables a development team to collaborate and each concern can be done discreetly with a clear way of content negotiation. Content negotiation could be handled via API or objects. In our engineering sprints, we learned that to make the software development process easier, we adapted the MVC to something we referred to "Base MVC". Basically, is means pushing CRUD functions to a base object and have light children objects. Below are three hurdles that we come across as we iterated to come up with the Base MVC. 

#Hurdle 1:  Repetition

In the course of our software development, we noted there is repetition of code that perform the same actions especially the CRUD - ie Create, Read, Update, Delete. I'll use two Objects for explanation. Student and Class. 

In MVC, for Student you have: 

  • StudentController
  • StudentModel and 
  • StudentView

Also for Class you have:

  • ClassController
  • ClassModel
  • ClassView

If we wanted to perform a CRUD action, we'll have the following functions in both StudentController and ClassController

  • postCreate
  • postUpdate
  • postDelete
  • getList
  • getDetailed

The Rule of three postulates that code that is copied more than once should be replaced by a procedure to make it easier for maintain. We noted that the above functions are declaratively the same and technically do the same action. Function postCreate in both controllers do the same thing, save data in the respective table. Why repeat? 

Using object Inheritance, we created a Base Controller that both the StudentController and ClassController will inherit from. In the BaseController, we added the five functions. So we have:

  • class StudentController extends BaseController
  • class ClassController extends BaseController

This enables us to reduce repetition which makes maintenance easier and also improvements as easy like Sunday morning.

#Hurdle 2: Uniqueness

Soon we noted that objects are unique and we needed to perform object specific actions. eg when creating a student, you might want to calculate their age before saving the data and also send an email to the parent after creating the student. To solve this we use "hooks" that are executed before or after the CRUD action. 

  • validate
  • beforeCreating
  • afterCreating
  • createRedirect

These functions are public inner functions that are executed within the postCreate function but also the individual objects can override. The ability to override is very powerful since it enables all children controllers to enjoy the core interfaces of the BaseController but at the same time can inject object specific business logic. 

Another aspect of uniqueness is the different table names and table fields. Different fields not only requires different validation rules but also different fields to be presented on the browser. To solve this, we had a structured way to set the table names, fields, validation and columns to present in the Model. We found multi-dimensional array easy to use as shown below:

  • Configure fields to be presented in the browser

    public $viewFields = array(         'name' => array(1, 'text', 'like', 1),         'age' => array(1, 'text', 'like', 0),         'gender' => array(1, 'select', 'like', 0),         );

  • Configure the validation rules

    public $createRules = array(         'name' => 'required',         'age' => 'required',         'gender' => 'required',      );

#Hurdle 3: Which object to call

Now that we have the StudentController and ClassController inheriting from the BaseController, we needed a clear way to call each of the five functions. We resulted to using RESTful endpoints that map to each of the functions. eg for StudentController we have the following routes

  • school/create/student => StudentController@postCreate
  • school/update/student =>  StudentController@postUpdate
  • school/create/class =>  ClassController@postCreate
  • school/update/student =>  ClassController@postUpdate

Having a consistent way of naming your endpoints makes it easier for debugging and also enabled us to have the same object name in different modules within the same application.

The Base MVC pattern has enabled us to offload most of the heavy-lifting of common tasks or actions to a base object thus reducing development time, maintenance headache and making it easier to add functionality that will propagate to all the other children objects. 

That said, the main risk to this pattern is the the base code become the single point of failure if something goes wrong. We mitigate this by ensuring the Base Controller is thoroughly tested before moving to production. 

In the next part, I'll share how we simplified the generation of forms used to creating and updating objects. 


Kamochu commented 4 years ago
I like the pattern and indeed saves a lot of development time!

Submit a comment

Your email address will not be published. Required fields are marked *

Back to list

About us

Sapama ERP is a cloud-based Enterprise Resource Planning (ERP) software for small and medium sized organizations.