CSC/ECE 517 Fall 2013/ch1 1w29 rkld

From Expertiza_Wiki
Revision as of 18:49, 17 September 2013 by Rkazi (talk | contribs) (→‎Motivation)
Jump to navigation Jump to search

Convention over configuration

Convention over configuration is a software engineering design paradigm which aims at reducing the developers efforts by helping him take lesser decisions while still allowing flexibility.<ref name="coc">Convention over configuration. Retrieved from http://en.wikipedia.org/wiki/Convention_over_configuration </ref> The idea of convention over configuration is that rather than having to configure several or may be even one large configuration file, one must use conventions to determine how code should work without configuration. Convention over configuration (also known as coding by convention) simply requires to developer to adhere to the conventions specified by the underlying framework . If these are followed in the correct and appropriate manner, the framework interprets the code and delivers output as one would expect from a well defined configuration file.

Motivation

Many frameworks generally require programmers to use configuration files in order to configure and set up the framework. Configuration files essentially are used to provide mapping between the classes and the resources. Thus adding more classes and resources to the application leads to an ever growing configuration file. Over the period of time it gets difficult to maintain these configuration files as more code gets added in the application.

<hibernate-mapping>
<class name= “Post” table=“posts”>
   <id name=“ID” column= “id” type=“integer”>
	<generator class=“assigned”></generator>
   </id>
   <property name=“category” column=“category” type=“string” />
</class>
</hibernate-mapping>
CREATE TABLE posts (
   id INTEGER(10) NOT NULL,
   category VARCHAR(2),
   PRIMARY KEY(id)
);

As seen above Hibernate<ref name="Hibernate">Hibernate- Storage and retrieval of Java domain objects via Object/Relational Mapping. Retrieved from http://www.hibernate.org/</ref> uses configuration files and maps the objects to the corresponding table in the database. Thus if we create an instance of the Post class and provide it with an ID and category, then simply calling the getId() function using that instance will perform a lookup in the database in the ID column and retrieve the relevant record. The Hibernate file shown above is an XML file. It becomes difficult to maintain these files as the complexity of the application code grows, leading to errors in the configuration files which may not be detected at compile time but rather only at run-time. Errors like ClassNotFoundException<ref name="ClassNotFoundException">ClassNotFoundException Retrieved from: http://docs.oracle.com/javase/7/docs/api/java/lang/ClassNotFoundException.html</ref> are typical examples of this situation.<ref name="DCOC">More on Convention over configuration Retrieved from: http://softwareengineering.vazexqi.com/files/pattern.html</ref>

A naming convention that is followed is :

  1. Database table names are pluralized form of the corresponding class name
  2. Columns of the database should have the same name as that of the corresponding fields in the class to which they map.

Developers generally follow these naming conventions while writing code. Thus the convention over configuration paradigm rewards developers by not having to configure any files by aiming at building and integrating it directly into the framework. Thus as long as the developer adheres to the standard conventions as defined by the underlying framework, he need not write any configuration files. The framework will automatically (sometimes termed as automagically) query the database and find the corresponding table and the corresponding column in the table depending on the method and class used to invoke it. Thus convention over configuration reduces the amount of configuration by using a set of conventions that developers should strictly follow.

Benefits

  1. Once developers learn the basic conventions followed by the framework, the overall speed with which they will develop the application is increased. They do not need to worry about setting up configurations to get the application to behave as expected. Simple naming paradigms take care of basic routing, associations and application resource usage.
  2. Developers can easily grasp and understand how the modules of an existing system are set up. Making modifications to such modules developed by the team becomes a very fast and clear-cut process. Since the code follows the same basic sets of rules when it comes to naming, the design of the different modules is very straight lined, consistent and easy to understand.
  3. If the naming is done well and adhering to the established conventions, the possibility of manual error when making changes to an existing system is reduced. Uninformed changes to configuration files without a proper understanding of their usage can cause an entire system to halt and throw up errors.
  4. The system understands some things inherently and we don't need to explicitly guide it or tell it to take specific actions for different cases.

Usage in Ruby on Rails

Ruby on Rails promotes the idea of convention over configuration. Rendering by default is one example where this paradigm is used in Rails. By default Rails automagically renders views which have names which correspond to valid routes.

Consider the code in the UsersController class

class UsersController  < ApplicationController
end

Also consider the following present in the routes.rb file

resources :users

And lets say there is a view file in app/views/users/index.html.erb

<h1> Users should be here soon ! </h1>

Now when the application starts and when you navigate to /users you should see “Users should be here soon !” on the page. Lets say we add an index action to our UsersController

class UsersController  < ApplicationController
    def index
	@users=User.all
    end
end

Here at the end of the index action we do not render anything. Thus since Rails follows the convention over configuration principle, it will automatically look for action_name.html.erb template in the controllers view path and render it. Hence it simply renders app/views/users/index.html.erb file.

Another example of conventions followed by Rails is the naming of the model classes, controller classes and the views. The corresponding model class for the "UsersController class" will be named as "User" whereas the folder where all the view for the "UsersController" are stored will be name as the pluralized form of the model class. Hence all views related to this class will be found in app/views/users/... Again the database table related to the user model class will be named as the pluralized form of the model class and hence will be named as "users". However the names of the columns in the database table should be identical to that of the fields of the class.

Since Rails uses the Model-View-Controller (MVC) paradigm. Thus a developer will find himself looking at controllers and views and models for the applications database. Thus the Rails framework has set up rules to make things easy for the developers in order to reduce the need to set up heavy configuration files. Thus developers working on Rails should adhere to the conventions that Rails has to offer. These conventions when followed correctly will keep the code concise and simple and most important they allow for a smooth workflow and easy navigation through the application.


Lets say a validator needs to be defined for a class. Ruby on Rails convention over configuration technique makes this tasks easy. The naming convention followed is that if validator name is always the pluralized form of the class name followed by the word “Validator”. Thus if the class name is “Post”, its corresponding validator would be “PostsValidator”. Inside the “PostsValidator” class the validating methods need to follow the naming convention in which they need to be of the form valid_x where x may be any descriptive word used for the validation.<ref name="DCOC">More on Convention over configuration Retrieved from: http://softwareengineering.vazexqi.com/files/pattern.html</ref>

class PostsValidator

  # Checks that post content is within certain length
  def self.valid_length?(post)
    post.content.length < 20  
  end

  def self.non_recognised_method
    # This method will not be called during validation
  end

end

class Post < Validatable

  attr_accessor :content # create getters and setters 
  
  def initialize(content)
    @content = content
  end

end

Post is just a simple class that has a field: content. The PostsValidator has a method that checks if the post content is within the restricted length. The method non_recognised_method is a dummy method simply kept there to demonstrate that the validation system does not call that method since it does not conform to the agreed upon naming convention.<ref name="DCOC">More on Convention over configuration Retrieved from: http://softwareengineering.vazexqi.com/files/pattern.html</ref>

class Validatable

  def validate
    unless @validator 
      validator = instance_eval(self.class + 's' + "Validator")
      validator.methods.grep /^valid_/ do |m| 
        puts "Method " + m + " failed" unless validator.send(m, self) 
      end
    else
      validator = instance_eval(@validator)
      validator.methods.grep /^valid_/ do |m| 
        puts "Method " + m + " failed" unless validator.send(m, self) 
      end
    end
  end

end
post = Post.new(“This is a valid post”)
post.validate # No o/p

post = Post.new(“This is an invalid post because it exceeds the length of 20 characters and hence will produce a validation failed message”)
post.validate # produces Method valid_length? failed

Also consider this special configuration case. If the validator instance variable is defined, then the validate method uses that for the class name of the Validator. This is necessary in places as shown below<ref name="DCOC">More on Convention over configuration Retrieved from: http://softwareengineering.vazexqi.com/files/pattern.html</ref>

class GroceriesValidator

  def self.valid_weight?(grocery)
    grocery.weight < 50
  end

end

class Grocery < Validatable

  attr_accessor :weight

  def initialize(weight)
    @weight = weight
    @validator = "GroceriesValidator"  # Validator needs to be defined as such
  end

end

Simple convention rules cannot take care of certain pluralized form of words. For e.g. the plural of Grocery is Groceries. Thus in such cases we need to explicitly tell the validator which class it needs to map to.<ref name="DCOC">More on Convention over configuration Retrieved from: http://softwareengineering.vazexqi.com/files/pattern.html</ref>

grocery = Grocery.new(80)
grocery.validate #produces Method valid_weight? failed

Major frameworks employing this paradigm

ASP.NET MVC

The .NET MVC framework mainly uses directory structure and naming conventions to enforce convention over configuration. It requires the developers to follow a set of rules for automatic routing and avoid configuration files for some default behaviors. Some of the rules are,

  1. Controller class names need to be suffixed with the word “Controller”<ref name="Controller">MVC Framework and Application Structure. Retrieved from http://msdn.microsoft.com/en-us/library/dd410120%28v=vs.100%29.aspx</ref>
  2. Views should be placed in the folder “views/controllerName”<ref name="Controller"></ref>
  3. Form fields should match the names used for Model properties for proper data binding <ref name="Data Binding">The Features and Foibles of ASP.NET MVC Model Binding. Retrieved from http://msdn.microsoft.com/en-us/magazine/hh781022.aspx</ref>
  4. The default view for an action method should be named after that method. <ref name="Action Methods">Controllers and Action Methods in ASP.NET MVC Applications. Retrieved from http://msdn.microsoft.com/en-us/library/dd410269%28v=vs.100%29.aspx</ref>

Spring Web MVC

This framework relies on the naming conventions used in the application to set up handler mappings, view resolvers etc. It cuts down the amount of configuration that might be otherwise required for the set up. The paradigm support is mainly in the models, view and controller. Some of the conventions are, <ref name="SpringMVC">Convention over configuration. Retrieved from http://docs.spring.io/spring/docs/3.0.0.M3/reference/html/ch16s10.html</ref>

  1. Controller class names are suffixed with "Controller" for automatic request URL mapping
  2. The model has a ModelMap class which allows to make adding objects to be displayed in a view to stick to some existing naming conventions
  3. View names (.jsp files) need to match the view requested in the request URL

Various other frameworks like Ember.js, Grails, Apache Maven also support the convention over configuration paradigm.

Drawbacks

  1. Frameworks which follow this paradigm require the developer using it to be familiar with the various conventions set up. The initial learning curve can be steep as conventions can vary across framework.
  2. Since the framework automatically does some things mainly based on conventions, the automatics are actually built into the framework which means a more heavier framework.
  3. It is very difficult to change conventions established in a framework. Upgrading from a previous framework to a newer framework with some changed conventions will more often than not break the existing applications built on the framework.
  4. It is difficult to make changes to applications based on frameworks following this paradigm without a good amount of knowledge of how the framework works. You cannot just jump in and make changes as there is a lot of stuff which is done internally which might be dependent on something as simple as the names of modules.

References

<references />

External Links

  1. Coding By Convention
  2. Ruby on Rails
  3. Hibernate - JBoss Community
  4. Web MVC Framework