Wednesday, September 09, 2009

SOLID part 3: Liskov Substitution Principle

This is the third part of the series about the SOLID principles, which governs good object-oriented development. You may want to subscribe to the feed to be updated on new issues of this series.
Check out the previous parts if you missed them.

Every function or method which expects an object parameter of class A must be able to accept a subclass of A as well, without knowing it.
The meaning of this principle is that every time you write a subclass, you have to make sure it is substitutable in every place where you use an instance of the original class. The subclass must respect the contract of the superclass, without changing a behavior in such a way that would be impossible to recognize the new instance as belonging also to the superclass.
The name of this principle came from Barbara Liskov, professor at MIT.

The principle is about bad use of inheritance: long chains of inheritance will probably break it as the leaves of the class tree will likely try to reuse code without being proper subclasses. Let's see an example.

In your application you are writing the (overused example) Car class, and suddenly you feel the need for a Motorcycle class to use along for urban traffic simulation. Since there is much in common in these two classes, like the Engine, Brakes and the correlated calculations and wiring in Car's code, you write Motorcycle as a subclass of Car, redefining the methods where its behavior obviously disagree with Car's one, such as getTires() since it has only two tires instead of four.
This redefinition is a violation of LSP: a feasible method checkUp(Car $c) will be broken if it expects four tires to blow up. The language will allow us to pass a Motorcycle instance since it is an instance of Car also, but it is not really a subtype of Car since its contract is less restrictive of Car's one.

A common rule to discover is the subclassing choice is right is the instanceof operator consistency, available in many object-oriented languages. This operator will return true if the variable under test is built from the chosen class or from a subclass ($a instanceof Car). This means in our example $yamaha instanceof Car will return true, which we know it's a bad behavior of the application since its domain model slides away from reality.
The refactoring choice to fix this design it's to abstract away the common behavior of Car and Motorcycle in a Vehicle base (and possibly abstract) class, or to stop using inheritance altogether. Inheritance is widely overrated in the object-oriented programming and composition should be favored in it.

Inheritance is the right choice when an Is-a relationship is present, and in the majority of design should be limited to two or three levels without harm. The original paper from Uncle Bob uses Square and Rectangle as examples. It's obvious that a Rectangle could not be subclassed from a Square, so the reverse is tried. But the contract of Rectangle say that we can change height and width independently (setHeight() and setWidth()), while even if we redefine the methods we cannot in a Square as changing a side will change the other to maintain Square's properties.
There are other designs which will solve this particular problem, like writing immutable objects, but my choice would be to write an helper class which contains common logic and do not chain Square and Rectangle in inheritance at all.
From a more theoretical point of view, preconditions of methods cannot be strenghtened by a subclass while postconditions cannot be weakened: the Square redefinition of setHeight() to modify also the width does not respect the stronger post conditions of Rectangle's method to leave width unchanged; thus, a subclassing is not feasible. This is a bit of design by contract which helps us to detect a bad inheritance strategy: in a particular sense, a Square is not a Rectangle, although it indeed is in a geometric definition; since a Rectangle is identified by an entity whose sides couples can vary indipendently, a Square that forces all four to remain equals is not an instanceof Rectangle.

I hope you're starting to grasp the principles and see the connections between them: to follow religiously one of these first three you're going to apply also the others.
Stay tuned for the next principle explanation, the Interface Segregation Principle.

The image on the top is a photograph of Loris Capirossi on the Ducati Desmosedici, during a MotoGp race. Is a RacingMotorcycle a Motorcycle?

Tuesday, September 08, 2009

SOLID part 2: Open/Closed Principle

The Open/Closed principle is the second of the SOLID principles which governs object-oriented development, formulated by Uncle Bob in the 90s*.
Check out the previous part if you missed Single Responsibility Principle.

Classes and methods should be open for extension but closed for modification.
The meaning of this principle is that when a requirement is added to your application, you should be able to handle it without modifying old source files (supposing you have one class per file), but only by adding subclasses and new implementations and changing the configuration.
Why it is important to be open for extension? Change is the keyword in software development and software components are inserted in new projects and environments every day. What makes them useful is the ability for a developer to write adapter and subclasses to get a job done without reinventing the wheel, but only by smoothing and tuning it.
Why it is important to be closed for modification? Because when a closed unit is fully tested and deployed, if it's not modified it can't break. This is a simple consequence of not changing what already works: it will continue to work.

These are some examples of patterns and techniques that help you follow the OCP:
  • programming to an interface, not an implementation: a oo interface is closed for modification, and multiple implementations can take new behavior and possibilities into the software system;
  • Template Method: some empty methods are called during an algorithm execution to allow overriding by a subclass, providing it hooks in the code flow;
  • Iterator Pattern: abstracts away the mechanics of an iteration to let other iterators substitute it in particular conditions.
Every good pattern resemble the OCP. The Iterator Pattern has been particularly developed in php: we have Iterator and IteratorAggregate instances which can be swapped in foreach construct; but we also have a bunch of subclasses that extends the core behavior: FilterIterator, CachingIterator, LimitIterator, RecursiveIteratorIterator...
The strategy of extending behavior without cluttering a base unit is one of object oriented pillars: subclassing, decorators and helpers are only strategies to keep responsibilities out of the base class, which can quickly became a God one if too much code fills it.

Let's take the Car example from part 1 and see if we are violating OCP: a Car is composed by an Engine, a Trasmission and the Brakes. What if we need to move the Car without using a gas or diesel engine? We can design a ElectricEngine subclass which will substitute the former Engine without breaking its contract. The same can be done with CarboniumBrakes or BremboBrakes.
What if the Engine has a method called injectGas()? This violates encapsulation and affects OCP also. An electric engine would not use gas as a combustible and thus the contract is not closed for modification: the problem is in the abstraction of an Engine which is in reality an abstraction for a gas engine. What can be done it's decoupling the Engine with an interface Propulsor which will contain a GasEngineElectronicBoard which translates to the Engine the commands from the driver.
Now if we want to put in an ElectricEngine, we will provide a Propulsor instance which governs the ElectricEngine in some way, with electronic or analogic circuits. Take the time to think about possible changes and how they affect your software systems: find a way to add features without have to resort to old classes modification.

Encapsulation is a checkpoint to achieve OCP: the more you keep private and hide from the public view, the less is assumed in the behavior an interface or an abstract base class. This leads you to write implementations which exposes very few methods and can perform work in unthinkable ways: the Propulsor interface can be implemented by a ElectricEngine but also from a ReactionEngine or a SteamEngine or a HyperDriveEngine if you are a science fiction passionate. The only requirement is that it manages to accelerate the Car and choosing this abstraction makes this parts totally interchangeable.
The Propulsor interface is an example of closure: not only it is not editable since clients expects determinate features, but we cannot add methods because they will break the implementors, especially if their code is not under our control.

Summarizing, Open/Closed Principle forces decoupled and extendable code: it's another milestone towards a maintainable and functional object-oriented application.

You may want to subscribe to the feed to be notified of new articles in this series. The picture at the top is the Usb symbol: nowadays every device that uses Usb and provide a proper driver can extend the behavior of a pc without having to open the case: webcams, printers, scanners...
*
Rogerio Liesenfeld points out in the comments that the original formulation of this principle comes from Bertrand Meyer.

Monday, September 07, 2009

SOLID part 1: Single Responsibility Principle

The Single Responsibility Principle (SRP) is the first of the five SOLID principles which governs the object-oriented design. They have been formulated by Robert Martin aka Uncle Bob and are universally recognized as good architecture.

This post is the first in a five-part series which will give an introduction to every principle. You may want to subscribe to Invisible to the eye feed if you want to stay tuned on new issues of this series.

There can be only one reason for a class to change.
This is the common formulation of SRP, the Divide et impera of software development. The meaning of this phrase is that when you're adding features to your application, two different, unrelated stories to implement should not affect the same class. What is implied by this principle is that every class you design should have only one responsibility, and often in software development change is the unit of measure: since your class Car have only one responsibility, only a change in the requirements of this responsibility should make you open the source file and modify the code of the class.

Here are some examples of classes which does not follow the SRP:
  • a Car which fills its fuel tank by itself
  • a CreditCard which knows how to charge itself (the classic Misko Hevery's example)
  • a CreditCardProcessor which knows how to do http requests
  • a Comment which sends mails
The scope of your application decides when responsibility should be splitted among more than one class: if braking and accelerating are complex processes, they should be factored out from the Car class, in two classes such as BrakeSystem and Engine respectively (or maybe Transmission, which will decouple Engine from the Car). Abstracting what is really complex is the point of this principle: if you need only to save the number of wheels in a Car you probably do not need to write a Wheel class whose instances will be placed in the Car one: it is a unuseful layer of indirection. If your wheels needed to know when they are totally consumed or are going to explode due to external solicitation, then they would become instanceof Wheels and would earn a class on their own: this is an example of refactoring. Until then, you are building a model of reality and you should not include a customer eye's color in their bank account information.

A rule of thumb to make this decision is to describe the behavior of a class with a single phrase. If you cannot formulate such a phrase or it contains the word and or other connectives, probably the behavior should be divided in more simple parts.
Particularly, entity classes (in respect to service ones) should have only the purpose to maintain state along with their business, inherent behavior. That's why a Comment instance contains name, text and mail fields but not a method warnAuthor(), which sends mails, to call on subsequent comments insertion.
The advantages of religiously following SRP are:
  • classes are more reusable, since you can pick only the one which implements a specific behavior without reusing a God class which can do everything and depends on everything.
  • classes are shorter and simpler to maintain.
  • design is more fine-grained, because every bit of behavior has its place in a small class. Knowing what you are going to modify it's half of the work in object-oriented development: with smaller classes, it will be obvious where a change belongs.
  • writing small and cohesive classes leads to testable code, while writing God classes leads to a non-testable ball of mud. A maintainable system is composed by a graph of object whose classes depends on each other for collaboration: this picture is obtained with dependency injection techniques.
Think of a complex object, like your computer: it composed by a moltitude of objects, but it respects the SRP; every component has its responsibility, from the resistor to the monitor, and complex components are built by wiring together smaller and cohesive ones.
Now that we are inspired by the principle, let's factor out some responsibilities from our example classes:
  • a GasStation or a GasPump will fuel a Car's tank
  • a CreditCardProcessor should take care of charging a CreditCard
  • a CreditService will insulate CreditCardProcessor from the Internet
  • a CommentRepository will call a Mailer or a CommentSubscriber whenever a new Comment instance is add to it
I hope you start to consider Single Responsibility Principle whenever you are designing a component of your application. It's a bit difficult to grasp at the exact level of detail, but if you find the right level of abstraction that is needed, the benefit will be beautiful and simple code; which, for a complex application, is a great result.

* The object in the image at the top of the post is Bicycle Wheel from Marcel Duchamp, a surrealist artist. It is an artwork, but to me is a perfect symbol of an object that does too much.

Friday, September 04, 2009

Twitter virtues and vices

After some weeks of Twitter usage, I came to the conclusion that it's a good networking tool and I do not regret opening my account. Some technological faults however are preventing me from fully enjoy the experience.

Rapid conversation: +1
Communicating via twitter is like sending phone text messages: the conversation flows and there is a need to rephrase to get to the point quickly. Shortened words and messages are normal as in informal sms communication.

Following @weierophinney: +1
It is often said that people who get things done have no time to tweet, but it seems that Twitter does not kill productivity if used correctly. And if it's the lead developer of Zend Framework, it must means that it's more a matter of choice: reserving a bit of time once a day to answer questions and to formulate ones it's not an action that will kepp you from doing real work. In fact, it will kill you if you keep staring at the screen trying to read every new tweet, but it is different from rss: you don't have to check them all.

The space to say what you want: +1
Many times, during the day, I think about some issues or ideas which does not earn a blog post on their own, but must be kept somewhere "just in case". This is pure tweet material and my timeline is full of thoughts which will could become posts or projects, or simply remain there to give evidence to myself that I always triaged Google Reader entries.

Reply system: -1
Whenever you reply to someone, you start a new tweet. There is no association with which one you are responding to, and neither quoting is present.
For instance, if you are replying to a tweet which has been posted some hours ago and it's not in the top of the timeline, probably no one will understand what are you talking about. Moreover, replies to other people obscure other tweets which might contain some useful links or information.

Limited web interface features: -1
If you want to improve your user experience, you must consider a third party client. I cannot find how to retweet a link in the web interface (the button might be somewhere) as a Tweet has only two ones: favorite and reply. I don't know what happens when I push the former but a star lights up.

Filtering: -1
The only possibility for searching is a full text one with tags such as #php or @giorgiosironi. This is not a problem since Google works in the same manner. Online filtering is unfortunately not possible: I'd like to simply concentrate my timeline when I consult twitter and I have to read all the noise from people who is replying to someone else.

Summing it up, there are pros and cons to manage a Twitter account. I now think that having one is a good move for enhance your networking, since it's much more simple to contact someone with a short tweet than via email (except when twitter.com is down, but it does not result in a -1 since outages are far less frequent than in the past). If you can tolerate the limitations of a system based on unorganized 160 characters messages, you should definitely register. And if you like this blog, remember to follow me.
Any other panegyric or rant?

Thursday, September 03, 2009

Coding standards and religion wars

A common tip in the "guidelines for good code" posts is to adopt a coding standard and stick to it. What is a coding standard and why you should adopt one now? Don't be worried about which one.

A coding standard gives a coherent look&feel to your code, promoting predictability. For a software system, predictability is almost always a good feature since a developer cannot hold a picture of all the code in his head, and has to guess what other unit of the systems will do in some situations as they collaborate with the one under development.
This applies on a behavior level, but also on a more physical Api discovering; while the description of the correct behavior resides in specification, tests and mocks, the appearance of the code and the classes and methods it expose is generated by a coding standard. If the names of methods (and their capitalization) are analogue and have the same structure, it becomes easy for a developer to program against it.

Code reading and analysis
Every coding standard forces an organization in the code to make it readable. Indentation, tabs vs spaces, control structures organization are all techniques which maintains order in a codebase, but there is a free choice
As an example, let's talk about the Java methods bracing in contrast with the php one. Java prescribes the developer has to put the opening brace { on the same row of the method signature definition; php coding conventions instead tell the developer to place it on the subsequent row, at the same level of indentation of the signature:
void doSomethingJava() {
// ...
}
public function doSomethingPhp()
{
// ...
}
There is no functional difference in the two cases; compilers and interpreters ignore whitespace, indentation and line breaking. All these rules serve no functional purpose.
The problem they address is style: a book can be beautiful and well-written, but if it's printed in an unreadable font, in pages of different sizes kept together by nylon threads, it will be very difficult to read without exhausting your nerves. The importance of a coding standard does not derive from which one you choose but from the constance in sticking to it, particularly in large or open source projects where many different people patches and rewrites code at the same time.

Subjective rules
Meaningful variable names is a subjective rule, since it cannot be cheked to a great extent from a static analysis tool. However, it is applied to improve the readability of the code, again. The convention on capitalization (CamelCase for instance) is a real coding standard, but the identifier names is more a matter of programming style, as long as you do not call variables $a1 and $a2.

If you are not organizing your source files, adopt a coding standard now. In the php world, Pear coding standard is the most famous one: I use Zend Framework one which is nearly identical to it. However, every project has conventions: if you want to be considered serious, follow a standard.

Wednesday, September 02, 2009

Deployment of php applications

Deployment is the process of taking live a codebase: make a web application work by transporting it to the production server, configuring it in the local environment and start the needed daemons. Here is a checklist for deploying php applications, which have the advantage of not requiring compilation.

Transporting the codebase
I used mainly two types of file transfer to get a working copy of an application:
  • ftp: it is the most proven technique and was the right choice for uploading a large amount of data. It is slowly becoming obsolete for deployment purposes but almost every hosting provider offers an ftp service.
  • ssh and subversion: where available, a remote shell with a working copy of the codebase under version control is a powerful choice for rapid updates, since it keep track of local "hot" changes and it transmits only modified and new files over the network.
It is considered good practice to checkout in an auxiliary folder and to work on it until the application is ready. A symbolic link is then established to this new folder for simple rollback is something goes wrong (and it will).

Setting up the environment
You should never forget to check source files and environment properties to make sure the application is runnable and it can act on the right data.
  • writable (aka public) folders: some folders have to be writable from the php process because files will be kept in them after uploading or elaboration. Ftp transfer normally does not mantain chmod permissions, so you may have to tweak it manually.
  • file permissions: the same configuration applies to writable files, like sqlite databases or similar.
  • database schema: every version or release of an application which uses a relational database will work along with a particular version of the schema, the definition of tables and their columns. A migration script should be prepared to upgrade the table from the previous structure. If it's the first deployment, the database must be created ex-novo.
  • other setup: any product will probably have a configuration script or web page to run, or a config file to compile. For example blogs and cms need database credentials that must be entered in a config.php file which will be included in every http request.
Starting the daemons
About the php case, the database and web servers are always running, being them on a shared or virtualized server. Php applications have a shared nothing architecture, so once they are configured the web application should run smoothly: this is a very different workflow from Java one, where you have to recompile and/or a packing a new jar. It theory, you can work by manually modifying scripts and uploading to a web server, but it is not a very good practice.
In some cases, a restart of webserver is needed, for instance if using aggressive apc options which cache in memory the content of php scripts. Otherwise, php scripts will be interpreted as needed by user requests.

Be sure to double check your assumptions; going live is a delicate procedure but is the key to show the world your beautiful product.

Tuesday, September 01, 2009

Introspection of php namespaces

Php 5.3 introduced the use of namespaces, a mean to organize classes and functions in packages with a common base name. Some php features that works on classes, such as Class/Object functions and variable class names, still work without confusion with a bit of attention on the data used.

Php namespaces organizes classes in a naming scheme which uses the standard separator \ to build groups and subgroups of elements, to shorten long class names and preventing naming conflicts. The classic name convention of My_Class is now becoming My\Class. Some functionalities are affected by the instantiation and I made a list of what changes when introducing the namespace keyword in your php source files.

Strings containing class names
Backslash (\ character) is the chosen separator for namespaces usage. This means that when used in a php single- or double-quoted string, it should be backslashed another time to prevent parsing: "My\\NameSpace\\Class" is a valid example.

Class/Object functions
Remember that this functions requires and returns fully qualified class names. In this group of function we find class_exists() and get_class(). Their argument is required to be a full class name (such as My\Class) and the returned values will contain full class name, for instance a call to get_declared_classes().
This is straightforward if you consider the namespace name resolving process as done at the compile time: since an argument to this functions is a literal string or a variable, it cannot be considered as a base class name of some namespace since this will involve php namespace resolutioon parsing string parameters, while it is built to work on code.
Finally, fully qualified class names never have a leading backslash. They are as simply as My\Class.

Autoloading
autoload() function and standard autoloaders pushed to spl_autoload() should work with the fully qualified class name. This is the same argument discussed on Class/Object functions.

Variable as a class name
This case is a bit trickier: again namespaced elements are resolved at compile time, so the instruction new $class is executed in the subsequent global environment, and assuming you have a fully qualified name in $class you should not prepend a backslash to make it work. Always use fully qualified names in code like this: tying $class to the executor specific namespace is not possible.
$resolvedClassName = 'NameSpace\\Other\\ClassName';
$object = new $resolvedClassName;
Standard Php Library (SPL)
Spl classes now reside in the global namespace. So every time you wrote a namespaced file, for instance a class one, you should refer to ArrayObject, Iterator etc. as \ArrayObject and \Iterator, or write a use instruction at the top of your file along with the namespace declaration.
Except if you are instantiating them via a variable class name, like in the last paragraph. If you prepend a backslash, however, it really doesn't matter and it will be stripped.

I hope these tips will help you take advantage of namespace features without wondering about what type of names should be used in coding.

Featured post

A map metaphor for architectural diagrams

It is a (two-dimension) representation of a pipe. The map is not the territory , but in software engineering terms they are models of it....

Popular posts