Another talk I’ve atended at PHPUK 2010 was AntiPHPatterns by Stefan Priebsch. While design patterns are core implementation independent solutions to problems that occur over and over again which also serve as a great vocabulary, anti patterns are software patterns that are ineffective or counterproductive. In his presentation Stefan describes some of these anti patterns:
1. Constantitis. Excessive use of global constants is considered to be a code smell. Global constants can be defined anywhere in the code base, there is a risk of name clashes if a constant is already defined, global constants make the code more coupled, testing gets more complicated since constants have to be known beforehand and defined explicitly which might be even more troubling if a constant has to change it’s value for another test. Since class constants are not global it’s OK to use them. Cure for constantitis is not to use global constants and instead use dependency injection.
2. Globalomania. Global variables share the same problems as global constants. Because global variables can be changed it makes them more dangerous than global constants since a change in one part of the codebase can affect the other without anyone noticing. Global variables can be cured by using dependency injection.
3. Singletonitis. Singleton is one of the most popular design patterns. It’s wide success is due to the fact that singletons by implementation are available globally in the entire application. The problem that singleton design pattern tries to solve is to prevent having multiple instances of the same class. This is rarely the problem in most applications and most singletons are being used as global variables instead. Singletons share the same problems as global constants and global variables and therefore should be avoided. Singletonitis has the same cure as constantitis and globalomania.
4. God classes. According to object oriented best practices classes should do one thing only and do it well. Classes should be refined and granular. One of the ways to think about this is to ask yourself what are the responsibilities of this class. In an ideal case you will be able to describe it in one sentence without any “and’s”. When classes start having too many responsibilities they become god classes. Usually the whole application relies on one of the god classes which makes the application tight coupled and therefore more difficult to maintain. To cure god classes minimize class responsibilities so that objects know everything about themselves and little about others.
Lost Art of Simplicity by Josh Holmes was the keynote talk at the PHP UK 2010 conference. I found it to be an interesting talk with lots of good advice. While listening to Josh I was able to identify myself in the past participating in all the common software development pitfalls. I would like to share what I consider to be at least some of the most important points from the talk:
- Work with your users. Focus on them and their exact needs. As developers we often tend to forget that actual users will be using our systems. We should stop and think is what we’re doing going to fulfill the actual needs of our users.
- When deciding which tools to use for a particular problem or a project always carefully weigh all the benefits and downsides to pick the best tools for the job. If for example most of your company’s software is written in PHP and is using MySQL doesn’t necessarily mean that you should keep doing so. It might be that another language such as Python or another type of a data store such as CouchDB might be a better choice for your next project. Developers also like to play with new shiny experimental toys but it doesn’t mean that it’s the best idea for your company to use it for a particular problem.
- Do the simplest thing possible. As Albert Einstein once said “Things should be made as simple as possible, but not any simpler”. “Cleverness” might not always be a good solution. Complexity involves more moving parts and more possibilities for things to fail. As developers we tend to think about possible future developments. While it is good to do so it is also important not to over do it. While it may be reasonable to believe that a different caching mechanism might be used for a project that you work on it’s less likely that another database vendor will be used in the future.
- Invented here syndrome. It is very likely that any problem you will have will be already solved by many other people before you. If instead of inventing your own solution to the problem you can use someone else’s tools by all means do so. Not every tool might do exactly what you need, not every tool might seem trustworthy enough but there’s no excuse for not trying to find the best available tools.
If you are interested to learn more take a look at Josh’s blog where presentation slides and a full transcript is available.
I’ve always been interested in Python. Python is a dynamic programming language with a very clear and readable syntax, strong introspection, intuitive object orientation and so on. It’s been used in many successful projects such as Trac, Django, Mercurial, YUM. It’s used in companies such as Google or Yahoo. Python has a vast standard library allowing to solve almost any domain problem. From the early beginning Python had a design philosophy behind it which is probably one of the reasons why Python is such a successful programming language now days.
All these and other reasons make Python an interesting and valuable language to learn. I’ve chosen to review Expert Python Programming as my next book. Having used Python for personal projects such as PyDumpy or work related tasks such as continuous integration with BuildBot I hope it will be an interesting read that will help me to improve my understanding of Python.
For those interested Packt Publishing offers a sample chapter of the book.
Zend Framework has a powerful input filtering component Zend_Filter_Input. It provides an interface to define multiple filters and validators and apply them to a collection of data. By default values returned from Zend_Filter_Input are escaped for safe HTML output. An example of such functionality:
$validators = array(
'id' => array(
'digits',
'allowEmpty' => true,
),
'name' => array(
'presence' => 'required',
new Zend_Validate_StringLength(5, 255),
),
'date' => array(
'presence' => 'required',
new Zend_Validate_Date('d/m/Y'),
),
);
$filters = array(
'*' => 'StringTrim',
);
$input = new Zend_Filter_Input($filters, $validators, $data);
if ($input->isValid()) {
print_r($input->getEscaped());
} else {
print_r($input->getMessages());
}
The code above validates the $data array by checking that the id key consists only of digits or is empty, that name is present and it’s min length is 5 and max length is 255 and that date is present and it’s format is d/m/Y. The StringTrim validator removes any spaces in front and at the end of all the $data values. If the $data array is valid all escaped values are outputted and if not a generated list of error messages is presented.
Recently I’ve ran into a small problem while using Zend_Input_Filter. According to the best security practices all data coming from the user should be escaped before being outputted to the screen. This also means data coming from a database. This requires to escape every single output statement in every view. In my opinion this adds unwanted verbosity, performance overhead and a possibility to easily miss that something was not escaped in one of the views. That is why if there is a possibility I would prefer to trust the database and not worry about the data incoming from it. It may not be a very good option if data in the database is most often presented in other documents than HTML. Since all values would need to be decoded which defeats the whole purpose. Though this is rarely the case.
By default Zend_Filter_Input escapes values by using the htmlentities function. Which converts all applicable characters to HTML entities. This means that for example Danish language characters Æ Ø Å would be stored as Æ Ø Å Which means that it would take 7 bytes on average to store a single letter that otherwise could be stored using 1 – 3 bytes using UTF-8 encoding support in MySQL. This could also potentially ruin collation sorting.
To overcome this issue a very similar function htmlspecialchars could be used. It escapes only a few certain characters such as > < ” without escaping all international characters. The actual problem with Zend_Filter_Input is that it does not have an escape filter that uses htmlspecialchars. To solve the issue I’ve created a copy of HtmlEntities filter which uses htmlspecialchars function instead.
The filter can then be used like this:
$input = new Zend_Filter_Input($filters, $validators, $data); $input->setDefaultEscapeFilter(new Company_Product_Filter_HtmlSpecialChars());
Zend_Filter_Input is a great tool to ease form validation and filtering. I would be very interested to hear from you how this problem could be solved.
I’m pleased to say that I will be attending the PHP UK conference 2010 in London. Last year I attended PHPNW 2009 which was great and I hope PHP London to be even better. It will be certainly interesting to listen to famous PHP speakers such as Stefan Priebsch, Fabien Potencier author of Symfony. The conference schedule has been announced and these are the talks that I’m going to attend:
- The lost art of simplicity
- AntiPHPatterns
- PHP 5.3 in practice
- PHPillow & CouchDB & PHP
- ‘In search of…’ – integrating site search systems
- PHP on the D-BUS
The keynote talk about lost art of simplicity sounds very promising. Also very eager to see Fabien’s presentation on how PHP 5.3 can be used in practice.
20
Zend Framework Database Profiler Reporting
1 Comment | Posted by Žilvinas Šaltys in Frameworks, PHP, SQL
Zend Framework has a powerful Database Profiler component. It is remarkably simple to integrate the database profiler with the Zend Framework front controller with the use of Firefox addons FireBug and FirePHP:
// In your bootstrap file
$profiler = new Zend_Db_Profiler_Firebug('All DB Queries');
$profiler->setEnabled(true);
// Attach the profiler to your db adapter
$db->setProfiler($profiler);
Or just by enabling it in the database configuration:
$db = array(
'type' => 'pdo_mysql',
'host' => 'localhost',
'dbname' => 'dbname',
'username' => 'username',
'password' => 'password',
'profiler' => array(
'enabled' => true,
'class' => 'Zend_Db_Profiler_Firebug',
)
);
Producing nicely formatted results:
Firebug profiler is great tool. But it requires to use Firefox and have FireBug and FirePHP addons installed. Not everyone in your organization may be Firefox users or have these addons installed. Another drawback is that sometimes queries may be quite big and complex. It’s not easy to analyse them in a Firebug window or to copy them to an editor that supports SQL highlighting.
To solve that it is possible to create a custom database profiler reporting mechanism. To output the profiler queries I’ll create a custom Zend Framework action helper:
class Company_Product_Helper_Profiler extends Zend_Controller_Action_Helper_Abstract
{
protected $_profiler;
protected $_view;
protected $_config;
protected $_db;
public function __construct(Zend_Config $config, $db)
{
$this->_config = $config;
$this->_db = $db;
}
public function init()
{
$this->_view = new Zend_View();
parent::init();
}
public function postDispatch()
{
$this->_profiler = new Company_Product_Db_Profiler_Report($this->_db1);
if (!$this->_isProfilerEnabled()) {
return false;
}
$this->outputToScreen();
}
protected function _isProfilerEnabled()
{
if ($this->_config->environment == 'live') {
return false;
}
if (!empty($_SERVER['HTTP_X_REQUESTED_WITH'])) {
return false;
}
$profiler = $this->getRequest()->getParam('profiler');
if (!empty($profiler)) {
return true;
}
return false;
}
protected function outputToScreen()
{
$this->_view->headLink()->appendStylesheet('/css/highlight/default.css', 'screen');
$this->_view->headScript()->appendFile('/js/highlight.pack.js');
$this->_view->headScript()->appendScript('
hljs.tabReplace = \' \';
hljs.initHighlightingOnLoad();
');
$this->getResponse()->appendBody($this->_profiler);
}
}
The action helper uses a post dispatch hook. The post dispatch hook is called after the Zend Framework dispatcher dispatches a request. A post dispatch hook is used to ensure that all queries have been run and to integrate the profiler with the Front Controller without changing any of the controller classes.
Action helper profiler checks to see if any profiling information should be outputted. It checks if the current configuration environment is not production to not allow unauthorized people to use the profiler. It also checks if a request is not an AJAX request, since AJAX requests may be returning JSON data structures and any additional output can break the client which sent the request. Profiler can be enabled by adding a URL query parameter ?profiler=1.
To highlight the SQL queries profiler uses a third party JavaScript highlighting library Highlight.js. On page load highlight.js finds all <code> nodes in the DOM structure, detects the programming or markup language type of the content inside them and highlights it.
The profiler action helper also uses another class to format the profiler report. The profiler report class implements an iterator interface and the __toString method allowing to use it in different ways. It could also be used to format profiler output for environments such as terminals which can’t interpret HTML.
class Company_Product_Db_Profiler_Report implements Iterator
{
protected $_profiler;
protected $_html = false;
protected $_position ;
public function __construct($db, $html = true)
{
$this->_profiler = $db->getProfiler();
$this->_html = $html;
$this->_position = 0;
$this->_profiles = $this->_profiler->getQueryProfiles();
}
public function setOutputFormatToHtml($value)
{
$this->_html = !empty($value);
}
public function __toString()
{
$out = "";
if ($this->_html) {
foreach ($this->_profiles as $key => $query) {
$out .= $this->_formatProfileAsHtml($key, $query);
}
} else {
foreach ($this->_profiles as $key => $query) {
$out .= $this->_formatProfileAsText($key, $query);
}
}
return $out;
}
protected function _formatProfileAsHtml($key, $query)
{
$out = "<pre><code>{$key}. " . wordwrap($query->getQuery(), 150) . "\n\n ({$query->getElapsedSecs()} s.) </code> </pre>";
return $out;
}
protected function _formatProfileAsText($key, $query)
{
$out = "$key. {$query->getQuery()} ({$query->getElapsedSecs()} s.)\n\n";
return $out;
}
public function rewind()
{
$this->_position = 0;
}
public function current()
{
if ($this->_html) {
return $this->_formatProfileAsHtml($this->_position, $this->_profiles[$this->_position]);
} else {
return $this->_formatProfileAsText($this->_position, $this->_profiles[$this->_position]);
}
}
public function key()
{
return $this->_position;
}
public function next()
{
++$this->_position;
}
public function valid()
{
return isset($this->_profiles[$this->_position]);
}
}
To make Zend Framework aware of the profiler action helper add the following lines of code to the bootstrap file:
Zend_Controller_Action_HelperBroker::addHelper(
new Company_Product_Helper_Profiler($config, $databaseConnection)
);
When done the output of the profiler should look something like this:
20
Subversion Self Signed Certificates
0 Comments | Posted by Žilvinas Šaltys in Apache, SSL, SVN
When connecting to Subversion repositories using SSL connections the SVN client checks the server certificate if it is not expired, if it’s host description matches the host of the repository and if the authority which signed the certificate is trusted.
If the certificate fails to comply with any of the above rules the SVN client will respond with a message such as this one:
Error validating server certificate for ‘https://hostname:443′:
– The certificate is not issued by a trusted authority. Use the
fingerprint to validate the certificate manually!
Certificate information:
– Hostname: hostname
– Valid: from Tue, 16 Feb 2010 16:58:39 GMT until Fri, 14 Feb 2020 16:58:39 GMT
– Issuer: company.com, London, Berkshire, GB
– Fingerprint: d5:4e:d8:12:33:12:a5:f1:18:91:77:40:c4:77:3b:0b:f8:51:71:cd
(R)eject, accept (t)emporarily or accept (p)ermanently?
The certificate can still be accepted permanently manually. It may not be a solution if SVN commands are issued by non interactive processes. For example a PHP script run by apache trying to export a branch from the repository.
Certificates signed by trusted authorities such as Verisign should not have any problems. But self signed certificates will not be recognized by the SVN client which in turn will respond with the response above. Self signed certificates can be be made trusted by the SVN client by using the ssl-authority-files configuration option:
ssl-authority-files = /home/void/.subversion/company.crt
The configuration file named servers which holds this configuration option can be stored in multiple locations on the filesystem. First the Subversion client will try to look for it in the home folder of the user that is executing the SVN command. Users such as apache will most likely not have a home folder. In such cases SVN tries to look for the servers file in the /etc/subversion directory. It may or may not exist depending on the OS distribution flavour. For example it exits on Ubuntu but does not exist on CentOS a flavour of RedHat.
18
Starting services in a clean environment
0 Comments | Posted by Žilvinas Šaltys in Apache, Linux, SVN
I was working on a small web application that creates Subversion branches and tags. In short it just executes SVN commands on the repository. Whenever a user executes an SVN command the SVN client tries to check user’s local home folder for the .subversion configuration directory. The issue that I was running into was that for some reason apache’s home folder was pointing to our system’s administrator home folder which in turn would result in a permission denied error when apache would try to access the .subversion folder.
It just didn’t make any sense. Turns out if you start a service through /etc/init.d/ it starts that service with environment variables belonging to the user that started the service. In this case our system’s administrator started the service using his own user.
To start services in a clean environment a special utility called service should be used. It usually resides in the /sbin directory. So for example instead of starting apache like this:
$ sudo /etc/init.d/httpd start
It should be started like this:
$ sudo /sbin/service httpd start
Which will result in $HOME environment variable being empty and the SVN client not getting a permission denied error.
18
Command Query Responsibility Segregation Open Talk
0 Comments | Posted by Žilvinas Šaltys in Domain Model, Patterns
I went to see Udi Dahan speaking on Command and Query Responsibility Segregation. The open talk was organised by Skills Matter who support the Open Source community by organizing free events and courses.
Udi Dahan is a world renowned software architect and speaker. Udi is a specialist in SOA and distributed systems. It is a pleasure to listen to Udi speak because of his ability to present ideas clearly and keep others wanting to see what the next slide holds.
Command Query Responsibility Segregation or CQRS is software architecture pattern. The pattern is about separating (Segregating) the read side (Queries) and write side (Commands) of the system.
A simple example would be an application that does event reservations. All read commands would be executed against a reporting database which is stale and can be de-normalized. All calculations needed to display the data have been done before populating the reporting database. All write commands like making an actual reservation or adding a new event is executed against a Domain Model with it’s own database. Domain Model is never used to execute reporting queries. Reporting databases are generated from the write side database after all needed calculations have been performed.
This architectural pattern simplifies the Business Domain Model making it behavior only making it easier to maintain. Another strong advantage of CQRS is system performance. CQRS approach accepts that reporting data can be stale. This enables easier development of highly scalable distributed systems.
18
Domain Model Logic Patterns
0 Comments | Posted by Žilvinas Šaltys in Domain Model, Model, PHP, Patterns
A great thing about patterns is that it provides a vocabulary. It allows developers to communicate efficiently. Complex ideas can be described at a high technical level without going into small details. Patterns are like butterflies and come in many colors, sizes and shapes and there’s.. lots of them. As butterflies patterns are grouped into families. One of such families is Domain Logic Patterns described in Martin Fowler’s book Patterns of Enterprise Application Architecture.
It’s one of the fundamental families because virtually every application written is described by any of the three patterns that belong to it. To say it simply there are three major ways how an application can be designed. What is more interesting that each of those patterns can be sorted by the amount of effort required to change the application depending on it’s complexity. Deciding which pattern to choose can be tricky because these patterns depend on various characteristics of the project being developed. The size, the complexity, the lifetime of a project and most importantly the skills of the developers.
Transaction Script
Transaction script organizes business logic by routines where each routine handles a single request from the presentation layer. It is the most common way how software beginners write applications. Required steps to perform a task are identified and expressed using language semantics. Common routines can be broken into subroutines. Transaction Scripts can be organised as classes or as global functions. A single file can contain many Transaction Scripts at once. A lot of developers may think they are proficient OOP users while in reality they write data centric Transactions Scripts wrapping them into classes which could be just as easily replaced with simple procedures.
However Transaction scripts have benefits. It’s a simple procedural model so most developers can understand it, it works well with a simple data access layer using Row Data Gateway or Table Data Gateway.
An example transaction script may be booking a hotel room where a single procedure is responsible for checking the availability of the room, calculating the price and updating the database.
class Hotel
{
public function __construct(Data_Access_Gateway $gateway)
{
$this->_gateway = $gateway;
}
public function bookRoom($userId, $fromDate, $toDate)
{
$roomId = $this->_gateway->_getRoomIdBetweenDates($dateFrom, $dateTo);
if (!$roomId) {
return false;
}
$days = $this->_getAmountOfDays($fromDate, $toDate);
if ($days < = 7) {
$price = $days * 100;
} else {
$price = $days * 80;
}
$data = array(
'userId' => $userId,
'roomId' => $roomId,
'fromDate' => $fromDate,
'toDate' => $toDate,
'price' => $price,
);
$bookingId = $this->_gateway->insert('bookings', $data);
return $bookingId;
}
}
Table Module
A Table Module is many ways the middle man between a Transaction Script and a Domain Model. A Table Module tends to organize domain logic with one class per table in the database. While a Transaction Script will have one class Hotel to do reservations a Table Module may have more fine grained classes like Hotel, Booking, Room. Even though these classes may be singular they do not actually represent individual entities and manages whole collections of entities. For example a Booking class would be responsible for mosts actions performed on the bookings database table. Like a Transaction Script a Table Module is a very data centric model approach and usually has a strong connection with the data access layer.
Table Module has a few benefits over a Transaction Script. There’s less duplication, domain logic is more organized and structured around domain entities. It works well with simple data access layers. However, Table Module doesn’t give you full power of objects in organizing complex domain logic. It lacks instance to instance relationships, has weak support for polymorphism.
To show an example of Table Module let’s re-factor the Transaction Script:
class Hotel
{
public function __construct(Data_Access_Gateway $gateway, Booking $booking)
{
$this->_gateway = $gateway;
$this->_booking = $booking;
}
public function bookRoom($userId, $fromDate, $toDate)
{
$roomId = $this->_booking->getRoomBetweenDates($fromDate, $toDate);
if (!$roomId) {
return false;
}
$days = $this->_getAmountOfDays($fromDate, $toDate);
if ($days < = 7) {
$price = $days * 100;
} else {
$price = $days * 80;
}
$bookingId = $this->_booking->addBooking($userId, $roomId, $fromDate, $toDate, $price);
return $bookingId;
}
}
class Booking
{
public function __construct(Data_Access_Gateway $gateway)
{
$this->_gateway = $gateway;
}
public function getRoomBetweenDates($dateFrom, $dateTo)
{
return $this->_gateway->getRoomBetweenDates($dateFrom, $dateTo);
}
public function addBooking($userId, $roomId, $fromDate, $toDate, $price)
{
$data = array(
'userId' => $userId,
'roomId' => $roomId,
'fromDate' => $fromDate,
'toDate' => $toDate,
'price' => $price,
);
$bookingId = $this->_gateway->insert('bookings', $data);
return $bookingId;
}
}
Domain Model
Domain Model organizes domain logic into well defined domain entities that contain both behavior and data. Usually each entity class represents a single entity in the data layer. Domain Model creates a hierarchy of inter connected objects that interact with each other by triggering behaviors on each other. Domain Model shines over Transaction Script and Table Module when it comes to handling domain complexity. It enables the full power of object oriented programming and all available design patterns. Even though Domain Model may sound like a silver bullet to all software development problems it is not. Learning to design applications using Domain Model requires a “paradigm shift” to start looking for entities and behaviors instead of looking for routines. The main downside of Domain Model is the way it works with relational databases. To compare I would like to quote Martin Fowler:
“In many ways Domain Model treats the relational database like a crazy aunt who’s shut up in an attic and whom nobody wants to talk about.”
Domain Model tries to be data layer agnostic. This is what object relational mappers also known as ORM’s as Hibernate try to solve by hiding the data access layer away.
To show an awkwardly simple example of Domain Model let’s re-factor the Table Module approach. To keep the example simple I’ll ignore the data access layer.
class Hotel
{
protected $_hotelId;
protected $_rooms;
public function bookRoom(User $user, $fromDate, $toDate)
{
$room = $this->_getRoomBetweenDates($fromDate, $toDate);
if (is_null($room)) {
return false;
}
$booking = $room->bookRoom(User $user, $fromDate, $toDate);
return $booking;
}
}
class Room
{
protected $_roomId;
protected $_bookings = array();
public function bookRoom(User $user, $fromDate, $toDate)
{
$days = $this->_getAmountOfDays($fromDate, $toDate);
if ($days < = 7) {
$booking = new Booking($user, new ShortBookingStrategy($user, $days));
} else {
$booking = new Booking($user, new NormalBookingStrategy($user, $days));
}
return $booking;
}
}
class NormalBookingPriceStrategy extends BookingPriceStrategy
{
public function getPrice()
{
$price = $this->_days * 80;
if ($this->_user->isLoyal()) {
$price = $price / 2;
}
return $price;
}
}
class ShortBookingPriceStrategy extends BookingPriceStrategy
{
public function getPrice()
{
return $this->_days * 100;
}
}
As you can see there is an instant explosion of classes and the data access layer is out of the picture. Responsibility to efficiently load and keep track of loaded entities is left to object mappers like Hibernate.
The End
Everyone of these domain model patterns have their benefits and downsides. It takes experience to be able to decide which approach to take. For those who are new to Domain Model it is advised to have an experienced team member who is able to guide you through it. While Transaction Script or Table Module can seem like a good solution at some point it may not be as effective later on. It is important to recognize when a different domain model approach might work better. It’s been a long ride for me. Through the years I’ve learned a few things about designing software but I still don’t feel very comfortable writing about it. I would love to hear feedback from you how this article and these examples could be improved to enable better understanding between the different modeling approaches.


