Object-Oriented MVC Web Programming

Wednesday, June 27th, 2012|Beginner tips, Misc|by Romans

After I have personally whitened the transformation of computer industry with unification of User Interfaces (by Mac and Windows) which is possible through use of Object-Oriented programing techniques. Object-Oriented programming offers many powerful tools to a skilled developer. Similarly Model-View-Controler concept have proved to be easy to understand and use. Unfortunately the typical MVC implementation is not very object-oriented.

If you combine object-oriented principles with Model-View-Controller paradigm properly, this will result in a much more efficient web development environment. In this article I explain object-oriented principles can be combined with MVC paradigm.

NOTE: I am the author and maintainer of Agile Toolkit. Me and my colleagues have built Agile Toolkit according to the principles I describe here. This article, however, is for promoting the fundamental ideas. If you would like to see a fully-practical implementation of Object-Oriented MVC, read introduction to Agile Toolkit. You are also welcome to implement ideas described here in your favourite programming language / framework / development environment or simply extend your out-look and expand your vision of Software Development.

Understanding Objects

If you are unfamiliar with object-oriented programming, method overloading and abstraction, let me start with an example.

Suppose that you must develop an application which draws shapes on the screen. The shape you need to implement would be Circle, Square and Line. Each shape have a set of different properties such as dimensions, lengths etc. The way how each shape is drawn would also be different. Therefore we would define a base-class first:

[php]
abstract class Shape {
public $x, $y;
abstract function draw();
}
[/php]

Afterwards you would extend this class to create Circle, Square and Line class. Each class would add some additional properties and implement draw() method differently. What is important is that you can abstract interactions with shape in the main body of your program. For example:

[php]
foreach($shapes as $shape){
$shape->draw();
}
[/php]

Regardless of how many different shape classes we have defined, how complex they are and how many properties they hold, the code above will remain as it is. This principle is called Abstraction and is often used in Object-Oriented application design.

Composition

The second important principle of Object-Oriented programming is Composition. That is ability of one object to rely on implementation of other objects to achieve it’s goal. Consider the following implementation of the “Square” class:

[php]
class Square extends Shape {
private $lines;
function draw(){
$lines[0]->draw();
$lines[1]->draw();
$lines[2]->draw();
$lines[4]->draw();
}
}
[/php]

In this implementation, Square relies on four other line objects to do the job. Of course Square can also be implemented differently, but the important thing is that it re-uses other objects to achieve minimum code and simplify implementation of a Square.

Both principles work extremely well in Web development, but many developers neglect to use them on a regular basis.

Planning Web Software with Object-Oriented approach

When any new application or a system is designed, software architect tries to anticipate what kind of flexibility will be required from the software and will attempt to use some of the development paradigms (including those two I have described above) to improve flexibility and efficiency of the software.

Let’s walk through the typical web application and see what areas of the application we anticipate to be extended and will require flexibility.

1. Data Model

M in MVC stand for Model. Model is an object which represents piece of physical data in your application. This can represent User, Order, Record, Message and many other things. There are many great frameworks which will help you convert your SQL data-base into Model structure at the expense of losing ability to use some powerful tools of Object Oriented Programming:

  • Generated Models typically will not use inheritance
  • Generated Models will not use abstraction
  • Generated Models will not use composition

There are many cases when use of the methods will save you some grief and all you need to do is to learn and recognize them. Here are few examples:

Inheritance: Publisher and Advertisers

Suppose you build web application where some users can publish articles and other users can advertise on the sidebar. Both type of users pursue different goals and are permitted to do different functions. They do have, however, some things in common such as ability to change their password.

A skilled software architect would create a class for a “User” which then would be inherited by Publisher and Advertiser. Method for changing password would be described in the “User” class and will be inherited by both Publisher and Advertiser.

You can also create a User class which incorporated features of both Advertiser and Publisher, but then any change to Publisher logic might impact Advertisers making your project less stable. The project will also become less flexible and it wouldn’t be as easy to introduce a new class of users without affecting existing functionality.

Through proper use of object-oriented inheritance principle you can achieve a much better structure source code.

Composition: Model Features

Models can have certain features such as soft-delete or ability to produce audit records. This functionality can be implemented through a separate objects instead of making model support it all. This is where composition principle is used. Some ORM systems will allow you to “enhance” your model by incorporating additional features through 3rd party classes. With composition you can also define your own patterns and make use of other classes inside your model.

With composition you can implement field encryption, validation and behavior extensions – all of these are very useful for a flexible application.

Abstraction: Generic Views

Suppose you have two models: “User” and “Order”. They do have a different set of columns, operate with different data-sources and behave differently and would also contain different set of methods. However they might be based on a generic model class. This way some User-Interface code can assume certain things about your models.

The most basic things to assume is how to create, delete update and list records. However views could also extract information about model fields from the model in which case they can build tables and forms for you without the need to re-define them all again.

Your model can be used by a restful API implementation which will transparently support manipulation with any model your system has. More importantly, you can also produce up-to-date SOAP specifications on the fly without any intermediate code.

That is the power of Object-Oriented abstraction.

2. User Interface

Let’s now switch to the User Interface of your web application and try to find where the similar principles can be used and applied. It is more challenging to design Object-Oriented User Interface for web software, simply because everyone wants to have a unique design, but it is still doable.

Any user interface design will be based around some concepts. You would operate with things like frames, buttons, layouts, headers, boxes, pop-ups and so on. Each element could be described with a piece of HTML code and some logic code. Frame, for example, would have two dynamic areas – title and the content.

Commonly the MVC principle uses no Object-Oriented principles in building Views instead it relies on template engine to do all the work. Templates do allow you to perform includes but are not object-oriented in any way. You can’t inherit a template and pretty often virtualization principle is not working either. If you are using regular MVC approach, you end up losing the flexibility of object-oriented programming.

This can be solved by working with objects. Suppose our objects are: Frame, Button, Paragraph. Because we enjoy customization we would also need a object with a custom HTML template which we can call “View”. With Smarty templates often include one another. With objects we already have a great principle called composition.

Composition: Form

Probably the best UI component which relies on composition is Form. The form class on it’s own can do very little, however it relies on “Field” and “Button” classes.

Composition principle in software with Object-Oriented user interface would go beyond forms and will allow any view to be composed of other views.  A frame could contain a form. A form field could contain a button. Finally the page could also be an object.

We are not eliminating templates, but templates are now used by each object individually. You no longer include templates but you now incapsulate objects.

Abstraction: Generation of HTML

Ultimately any Web Software must produce a HTML output for browsers to work with. If our User Interface consists of objects, then we will have to rely on abstraction when generating HTML. This way we can ask Frame object to render() itself into HTML and Frame would rely on other object ability to produce HTML and so forth.

[php]
echo $page->render();
[/php]

Inheritance: Widget customization

Now that we are incapsulating objects and not templates, it’s much easier to produce general-purpose widgets which can be part of the page. Such widgets can communicate with other components or the system or even with JavaScript on the browser-side. But in addition to the selection of the base widgets it’s now extremely easy to add new widgets by inheriting existing ones. If you need to build a signup form, you extend a regular form then tweak some behavior and properties.

This approach to the project will promote creation of new components and their re-use. By extending widgets (views) and not adding more functionality into them you can keep basic performance fast and avoid creating un-stable code.

3. Application Class

After models are defined and the UI components are defined too, there are the binding element to it. That’s the application class. Application is typically a class which is responsible for doing EVERYTHING. Of course application class uses composition to divert implementation towards other classes. The Data-Model and User Interface is something I have mentioned already. However there might be some other classes, which are typically called Libraries.

Inheritance: Multiple API classes.

Application must be a valid objects. It should be possible to create several instance of application object and also have ability to inherit applications. One application may be focused around serving one user segment and other application could be used for website administration purposes. Some API classes may be focused to be called from command-line or from scheduler. Other API may produce HTML, XML or JSON output.

Composition: Implementing Routing

A web application must respond to different URL formats and connect them to different classes. How the mapping is done is defined through “Routing”. For example http://example.com/testpage/ might be routed to a class called “page_testpage”. Ability to divert page-specific functionality into page classes is implementation of composition in Web Application front-controller.

The principle, however, is depending on the nature of API used. Command-line API typically do not require routing. Implementation of RESTfull API can be implemented by connecting to models directly.

Abstraction: Application Roles

There are many general web application categories such as Content Management Systems, eCommerce solutions, Ticket systems. Certainly you can implement a ticket-system. However – can you deliver such a system as an abstract class which could then be further extended?

Majority of MVC frameworks would not allow to do that. This is an incredibly powerful concept which can create a more flexible closed-source web software distribution, implement a stable multi-interface web system and even build one open-source project on top of another with a very tight integration and minimum overheads.

The Object-Oriented MVC

Here I have described my view of Object-Oriented MVC. Models fully capable of all object-oriented features. Views implemented as objects, not templates relying on object-oriented features. Finally the application which controls all of the process yet will not take away any of the advanced object-oriented techniques.

Object Oriented development offers a powerful concepts used by majority of developers word-wide. Web Frameworks usually restrict developers and take away power of Object-Oriented development. Only by combining and designing a web framework from the ground-up to permit and use full power of object-oriented programming maximum web development efficiency can be achieved. But not without some learning.

4 Comments

Don
Posted June 29, 20126:03 am

Thanks for the insightful post. I am just learning about Agile and this is helpful. Ps. Change ‘loosing’ to ‘losing’.

Fabio Souto
Posted July 6, 20121:09 pm

Form object writes to and reads from User-Interface. Simillarly, Model objects write to and read from database. A Form object can be linked to a Model object. A Form may have child forms. In your controller you just nest one form inside another and call a method, say, ->run(). A good framework should do everything automatically for you based on fields specification of both form and model objects (save parent data then save child data, if there are validation errors return data properly formatted so that the User-Interface can be re-built). No framework I have seen so far handles all that, not even so-called Zend. I have seen models receiving data from POST and FILES array when it should only process data in a general format so that models can be reused in diferent contexts. Therefore I am building my own framework.

Romans
Posted July 6, 20122:08 pm

So how close is this: http://agiletoolkit.org/codepad/gui/form to what you’re have in mind?

Romans
Posted July 6, 20122:15 pm

Here is the docs with more info and styling guide: https://agiletoolkit.org/doc/form