Friday, July 31, 2009

Global state is rarely a salvation

This post is a response to Domain Events - Salvation from Udi Dahan, where he shows a design to manage the Domain Events pattern. He suggest to use a static class to handle publishing and subscribing, but I argue that a static class solution is not pure as it seems.

Disclaimer: Udi Dahan is an authority in DDD and enterprise application development. I think it is a person who gets things done and I do not contest the validity of his approach in production environments. Active Record often gets the job done also and I used it a lot in the past, but there are cleaner solution arising.

In the Domain Events - Salvation post, Udi proposes the third reworking of his Domain Events implementation. DomainEvents is a pattern similar to Observer or Publish/Subscribe applied to a Domain Model, where the domain objects are observed or observers.
He sustains that you should not never inject anything in Entities, and I agree since Entities are not injectables. Here's how he raises an event:
public class Customer
{
public void DoSomething()
{
DomainEvents.Raise(new CustomerBecamePreferred() { customer = this; });
}
}
Then he says:
We’ll look at the DomainEvents class in just a second, but I’m guessing that some of you are wondering “how did that entity get a reference to that?” The answer is that DomainEvents is a static class. “OMG, static?! But doesn’t that hurt testability?!” No, it doesn’t. Here, look:
and he proceeds to show a (not) unit test where an event is raised.
Now, let's clarify some points:
  • a static class is more or less a singleton. They both have reset-like methods and a unique copy of data globally accessible wherever you want. You can make the class package-private in some languages, but every class have potential access to the singleton instance.
  • Singletons are pathological liars. They hide dependencies and carry global state around, between tests.
  • This solution uses a static class.
We can conclude that this Domain Events implementation is not a beautiful architecture as it was proposed. Let's explore the problems it raises:
  • If you forget to reset() the static class between tests, the test suite can blow up suddenly in a strage place and the fault will be hard to locate. An instance can fire an event that is forwarded to subscribers that do not exist anymore. This is global state in action.
  • Everytime you test an entity class, you're testing also DomainEvents class, since it cannot be mocked.
  • There is a compile-time dependency on DomainEvents. In other languages like Php this would not be a problem since there's no compiling, but Udi's examples use .NET and Customer is now dependent on DomainEvents. A possible solution would be defining events support directly in the language, but it is a big shift in the object-oriented paradigm.
  • Production code will be an action at a distance.
Let's explore the last issue.
The code of a service or controller layer will be similar to:
// in the setup
DomainEvents.Register(
b => creditCardProcessor.charge(b.Customer, b.Amount)
);
// Customer class, an Entity
public class Customer
{
public void bill(int amount)
{
DomainEvents.Raise(new CustomerBilled() { Customer = this; Amount = amount });
}
}
// some controller, client code
Customer c = new Customer();
c.bill(1000); //someone is billed? but who? what happens when I call this? if I not persist this customer instance nothing has happened, right? No.
compare it with:
billingService.charge(c, 1000);
or
c.bill(billingService, 1000);
The billing service does not lie: it requires a CreditCardProcessor in the constructor. Now I see what happens: the credit card of the customer is charged for 1000.
My solution is always the same: if a method of an entity requires an injected dependency, place it on a service class or ask for the dependency in the method parameters, extracting an interface to put in the signature. Asking in the constructor is fastidious since we want to be able of create stateful objects like entities simply by calling new, or whenever we create one we have to ask for a factory.

My conclusion is that using a static class in an entity class and say that you're not injecting anything is right, because you're not applying Dependency Injection at all. The phrase:
The main assertion being that you do *not* need to inject anything into your domain entities.
should be changed to The main assertion being that you do *not* need to inject anything into your domain entities: simply throw in a static class so that your entity stops asking for things and begin looking for things, abandoning Inversion of Control/Dependency Injection.
Again, I do not question that this design gets the job done. But don't say "I'm not injecting anything, that's good" if you're nail down a lightweight newable class to a static infrastructure one.

Wednesday, July 29, 2009

When to inject: the distinction between newables and injectables

Dependency Injection is a great technique for producing an application with decoupled components; but injecting every single object of any lifetime is not useful. Where do you find a Mail that sends itself?

In the last post, I introduced Dependency Injection and show useful cases where it allows classes decouplng. I also wrote about the problem of how to inject a service in a class that has to be instantiated not application wide but in the business logic.
class Mail
{
public function __construct(MailService $service)
{
...
}
}

class CommentsRepository
{
public function sendAMail()
{
$mail = new Mail(...); // what I should pass?
$mail->send();
}
}
The problem is that CommentsRepository sends a mail basing on some input data (if someone has posted a comment), so we cannot instantiate Mail at the bootstrap of the script like we do with CommentsRepository or other request-lifetime objects (session-lifetime in case of a Java application instead of a Php one).
The simplest solution is of course, to use a factory:
class CommentsRepository
{
public function __construct(MailFactory $f)
{
$this->_mailFactory = $f;
}

public function sendAMail()
{
$mail = $this->_mailFactory->createMail();
$mail->send();
}
}
This approach let CommentsRepository depending only on Mail and MailFactory (which could be an interface); dependency injection is correctly applied from the technical point of view. A Factory should be created for every object lifetime: the main services like an MVC stack are request-lifetime objects and should be create by an application factory, while other objects that are created during the execution should taken care by a smaller factory to pass where it is needed. Because a parameter in the constructor expresses dependency, CommentsRepository says that it creates Mail in its methods.
However, a factory for Mail trigger some problems:
  • Every time we create a mail, also for testing purposes, we have to use a factory for obtaining an instance, that shield our code from changes in the constructor of Mail. Considering that an instance of Mail is likely to be passed around as a method parameter and we'll need to mock it every time, this is a smell that the current design has some flaws.
  • In production code, if a class create a mail but does not send it, the former must use a factory and so is coupled to the mail sending classes. For instance, a collaborator of the CommentsRepository that creates a nicely formatted html Mail object.
  • Serialization of a mail to send it in another moment is not possible since at the wakeup it won't know where to find its MailService.
  • If Mail was a string, will you inject a StringFactory? I don't think so.
What is the problem? That a mail knows how to send itself. Have you ever seen a mail that sends itself, or a credit card that process itself (like Misko Hevery, the Google testing guru, denounce often)?
This lead to achieve a fundamental disctintion in business objects: Entities and Services. I write them starting with an uppercase letter to denote that they are precise concepts in object-oriented programming and the meaning of the two words is different from their use in common language.
  • Entities are stateful; their job is to maintain their state and to be saved (and not saving itself) in some place or in memory. Services are stateless: you can instance a MailService many times, but it is always the same service for the end-user.
  • Entities are newables, Services are injectable (this is Misko Hevery terminology). Entities should be create with new operator every time you need them, while Services should be created by a factory or a dependency injection container.
  • Services depends on entities, while the opposite should not happen. It can happen in some programming models when they are coupled to a Service interface.
With these distinction in mind, let's review our design:
  • Mail is an Entity
  • String is an Entity (it is a ValueObject, but in a pure Entity/Service distinction it is an Entity)
  • CommentsRepository is a Service
  • MailService is, obviously, a Service
How do we evaluate such a difference? Mail is a stateful object: we can change its subject, text, formatting. It must be a Entity. CommentsRepository have no properties that maintain a state - we cannot make our repository tall or short, thin or fat. The same is true for MailService: every time a factory creates it the result is always the same and probably it is a singleton in our application or there is a limit on the number of instances if is a generic class.
So Mail should knot know about Services, only Services could:
class Mail
{
public function __construct($title, $text)
{
...
}
}

class CommentsRepository
{
public function __construct(MailService $service)
{
...
}

public function sendAMail()
{
$mail = new Mail(...);
$this->_service->send($mail);
}
}

interface MailService
{
public function send(Mail $mail);
}
Now, CommentsRepository is tied to MailService interface, but it was already coupled indirectly by Mail when we started refactor. Mail does not know about anything, and MailService has a dependency on a concrete but small and compact class.
In the first refactoring, we treated Mail like it were a Service, but a similar deference should be adopted when dealing with more complex classes, while Mail is more or less a Value Object. If we wanted to create lazily the MailService, we would have inject a MailServiceFactory or a DI container in CommentsRepository. Beware of not slide towards an Anemic Domain Model, a procedural approach, putting methods that belong to Mail in Services: Mail is by the way a class, not a C structure or an array of fields.
Hope that this design satisfy you - it is very simple to test and loosely coupled as we should strive for every day.

Tuesday, July 28, 2009

Never write the same code twice: Dependency Injection

Is Dependency Injection difficult? Is it hard to do? Certainly it provides value. Particularly in Php, but also in other object-oriented languages, Dependency Injection gives steroids to the process of class reuse, designing components as loosely coupled objects.

In object-oriented programming, Dependecy Injection is an uprising pattern to achieve Inversion of Control. It consist in breaking the dependencies between classes and inject the collaborators of an object instead of having it find them without external aid. This collaborators are other objects which are passed to the unit in question in the constructor or by setters. There are many benefits of this technique other than code reuse, but today I will talk about this aspect.
DI is a fundamental practice that leads to testable code: Test-Driven Development forces the programmer to write code that is testable at the unit level. Unit testable code is necessarily decoupled code: if a class is totally coupled to another, the unit test became an integration test.
The hardware industry follow this pattern - integrated circuits are designed for testability. They're also very decoupled, as they can be connected on boards to build nearly anything. At the high level, the PC industry is full of standards for interchangeable parts: PCI bus, Usb and more. This decoupling is what let you change your monitor or keyboard without throwing away the pc.
Many posts have been written on Dependency Injection and I prefer to show an example here to get to the point: it is simple to write injectable classes, that can be reused later because their collaborators are wired but not soldered together. The language used here is php, but the concept is universal and any object-oriented language could be adopted. Sorry for the bad indentation but it's blogger fault (unit test it and you will see that it mangles spaces).
Let's start with this class:
class MailApplication
{
public function __construct()
{
$this->_service = new GmailService();
}

public function list()
{
$mails = array();
foreach ($this->_service->getMailFrom('xxx@gmail.com', 'password') as $mail) {
// .. do some work and highlist
$mails[] = $text
}
return $mails;
}
}
Here's a component which is very coupled to the collaborator and that is not unit testable: we cannot call list() if we are not connected to the Internet and when its unit tests are run they will take a lot of time to dialogue with Gmail servers. There's more: we are testing not only our class but also the GmailService class; if one of them breaks, the test does not tell us which one is not satisfying its responsibility. If the interaction is not between two objects but five or six, the test became useless since we do not now where to search for a bug.
From the reuse point of view, imagine we have a customer that uses Yahoo and wants to adopt our beautiful application, but only if he can integrate his emails management. We write a YmailService class, but MailApplication knows only Gmail and we cannot tell it to use YMailService. There's no class reuse or extension.
According to DI principle, we should inject in MailApplication its dependency:
class MailApplication
{
public function __construct(GmailService $service)
{
$this->_service = $service;
}
// ....
}
This way, we could subclass (mocking) GmailService and inject a stub object that returns canned results when its method list() is called. We can also extract an interface for GmailService if we want to have multiple implementations like in the Ymail example:
class MailApplication
{
public function __construct(MailService $service)
{
$this->_service = $service;
}
// ....
}

class GmailService implements MailService ...
The test is now a real unit test and not an integration one. If it fails, we know who to blame: MailApplication since the other component is stubbed and returns fake results.
That's all very good; but how a MailApplication object is built?
This is the job of a factory:
class ApplicationFactory
{
public function getMailApplication()
{
if ($this->_config == ) {
$mailService = new GMailService(..);
} else {
$mailService = ....
}
return new MailApplication($mailService);
}
}
// in the "main" php script:
$factory = new ApplicationFactory($configuration);
$mailApplication = $factory->getMailApplication();
Depending on configuration (again, injected configuration), the factory instance builds an instance of the application. Ironically, it's a factory that builds the major parts of your computer: you're certainly not expected to weld hardware components together, because it's not your job and you do not have the mandatory competence.
The simple approach needs refinement, as it leads to problems: suppose we have a CommentRepository. When you write a comment on this blog, it sends a mail.
class Mail
{
public function __construct(MailService $service)
{
$this->_mailService = $service;
}

public function send($to)
{
$this->subject = '...' . strtoupper(...); // some work
$this->_mailService->mail($to, $this->subject, $this->text);
}
}

class CommentsRepository
{
public function sendAMail()
{
$mail = new Mail(...); // what I should pass?
$mail->send();
}
}
Again, reusing is important because now we send mail with these classes but in the future we can switch to a library which provides html or attachment management, or reuse this CommentsRepository without even sending mails because another application does not require it.
However, we cannot create the Mail object and pass it to the Comments in the constructor, since we don't know at the creation time (bootstrap of application, pre-Mvc dispatch, or whatever) how many Mail object it will need or if they will be used at all. Putting every dependency of Mail class in the constructor of CommentsRepository is ugly and makes CommentsRepository coupled to collaborators that it does not use.
There's more than one solution, and we will see them in the next post. But I tell you in advance that using another factory is not always the best approach.

Monday, July 27, 2009

How to stop getting megabytes of text when dumping an object

Php has a useful var_dump() function that helps debugging and unit tests writing by providing a text dump of all the properties of an object, being them public, private or protected. However, with an object that has a reference to the whole object graph, like a factory or an object that uses an abstract factory, the dump will be recursive and so long that it runs forever (probably it lasts several megabytes). Here's how to avoid it.

In the browser
When you are using a browser, the Xdebug extension comes in your help by generating a html dump truncated at an arbitrary level of depth. The installation on a unix box is pretty simple:
@ pecl install xdebug
run as root or with sudo. Pecl is the dual repository system of Pear and contains C extensions instead of Php userland packages; it is provided along with the pear binary in most of the installation of php.
Then add the following lines to php.ini:
zend_extension="/usr/local/lib/php/extensions/no-debug-non-zts-20090626/xdebug.so"
xdebug.var_display_max_depth=2
Probably the first has been already placed from the installer. The second directive set the maximum depth of var_dump(), which is overloaded by the extension, to 2 levels.
There are other directives that influences the behavior of var_dump(), and more and more for activation of other xdebug features.
Make also sure that html_errors is on in php.ini, or ini_set() it.

On the command line
The command line environment is more complex to use, but it is the ideal for debugging, given its speed and automation capability. The var_dump() usage must be tweaked because the var_dump() overloading, as of Xdebug 2.0, works only with html_errors active, producing an html dump that is ugly to view as plain text.
Assuming you have done the same setup of the browser section above, here's a workaround method to use:
function dump($var)
{
ini_set('html_errors', 'On');
ob_start();
var_dump($var);
$dump = ob_get_contents();
ob_end_clean();
echo strip_tags(html_entity_decode($dump));
}
It will get the html output of var_dump() even in a Cli environment that has the html_errors directive not set, and clean it to display as plain text.
Here's what I get dumping a PersistentCollection of Doctrine 2 now:
[16:54:23][giorgio@Marty:~/svn/doctrine2/tests]$ phpunit Doctrine/Tests/ORM/Functional/DetachedEntityTest.php
PHPUnit 3.3.17 by Sebastian Bergmann.
object(Doctrine\ORM\PersistentCollection)[180]
private '_type' => null
private '_snapshot' =>
array
empty
private '_owner' => null
private '_association' => null
private '_keyField' => null
private '_em' => null
private '_backRefFieldName' => null
private '_typeClass' => null
private '_isDirty' => boolean true
protected '_initialized' => boolean true
protected '_elements' =>
array
0 =>
object(Doctrine\Tests\Models\CMS\CmsPhonenumber)[181]
...
1 =>
object(Doctrine\Tests\Models\CMS\CmsPhonenumber)[182]
The '...' ellipsis are added by Xdebug instead of showing thousands of objects and properties, because the PersistentCollection is provided with a reference to EntityManager for lazy-loading itself.
With the old var_dump() instead:
[16:54:23][giorgio@Marty:~/svn/doctrine2/tests]$ phpunit Doctrine/Tests/ORM/Functional/DetachedEntityTest.php > test.txt
I redirect the output to a text file because it is impossible to navigate from a terminal, but you have to expect some minutes because it takes forever to generate a full dump of the EntityManager and all other objects involved. Without redirecting lines are sent on terminal for a unspecified long time, and are also duplicated because var_dump() is not so smart in detecting recursion and it let happen for a while before stopping to output the same objects over and over. It was very frustrating but now it is easy to view even the most complex and coupled objects.
I know that the more an object is coupled, the less it is well written; but even if it only depends on an interface (a parameter in the constructor), at runtime that interface could be implemented by a very heavy object. Decoupling limits this process, but object must communicate and so they have to keep references to other collaborators: the Publish/Subscribe paradigm is very loose coupled, but dumping a publisher will output it, the blackboard and all the subscribers on Earth.
Summing up, Xdebug can boost your php productivity, and has many other features that will make easy to see what happens under the hood of your php application. Profiling and tracing are easily provided with other xdebug.* directives. If you are a php developer, install it as soon as possible.

Thursday, July 23, 2009

Php 5.3 without screwing up apt-get

Php 5.3 is stable and if you want to experience improved performance and lessened memory usage, and also play with nice tools like Doctrine 2 that are built for this version, you have to install on your box. But a .deb is better than 'make install': it does not sends binaries and configuration files all over your system, without a mean to trace where they end up.

Php 5.3 is a new minor version of Php, so it does not break the strict compatibility of your application. Though, it deprecates some old features and practices and it could cause problems, so you shoud cautious about using it in a production environment. That's what staging exists for.
However, if you choose to install it, your better choice is to use a .deb package that could be easily removed when the distributors catch up and provide a php5 package: 'make install' command issued after compiling will spread files all over the filesystem, without let know you what is being overwritten and created. A .deb will also help upgrading with its simple removal procedure.
This example is based on Ubuntu Jaunty (9.04), but probably will work on other versions and Debian-derivated distros.

Step 0: downloading the source
To build a package, the C source code is needed. A tarball for the release is provided from the php team:
wget http://www.php.net/get/php-5.3.0.tar.bz2/from/a/mirror
tar xvjf php-5.3.0.tar.bz2
cd php-5.3.0
Now we have source files at hand.

Step 1: compiling
Compiling is the fragile and longest part, as the compile time can be very long, especially if you use many bundled extensions and your machine is performing other tasks at the same time.
First, the build configuration has to be created.
./configure --disable-short-tags --with-zlib --enable-bcmath --enable-exif --enable-ftp --with-gd --with-jpeg-dir --with-png-dir --enable-mbstring --with-pdo-mysql --with-sqlite --enable-sqlite-utf8 --enable-zip --with-pear
"with" and "enable" commands are listed using --configure --help and will tell you what bundled extensions are available in this release. The more extension you pull in the compilation, the more time it will take, but you do not want not be surprised with undefined function: mysql_connect. With this configuration, it is not included because PDO is used instead.
The ./configure command will fail often, and it probably means that you lack some source files or libraries needed for the extension to compile and to be linked to. They are normally not installed in the average system, so is something is needed you will probably run commands such as:
sudo apt-get install libjpeg
sudo apt-get install libbz2
depending on the extension choosed. To find the name of the library, see the Requirements section on php.net/manual for the extension in question.
When ./configure does not fail anymore, we can start the compilation:
make
This will take time, so you should consider running when you're not at the pc.

Step 2: building a package
When the compiling is finished, a .deb has to be built from the produced binaries. checkinstall is the command line tool that will do the job for us. Of course if you do not have it, sudo apt-get install checkinstall.
sudo checkinstall -D --install=no --fstrans=no --maintainer=piccoloprincipeazzurro@gmail.com --reset-uids=yes --nodoc --pkgname=php5 --pkgversion=5.3 --pkgrelease=200907011400 --arch=x86
We are telling checkinstall to create a Debian package (-D), to not install it for now, do not use a fake filesystem since this is not necessary, to not include the documentation since we aren't going to distribute this package but only to use it at home.
To be useful, checkinstall must be run as root, so we use sudo.
After this command, checkinstall asks you to confirm the options and by pressing Enter your (probably if you're still reading this simple guide) first deb is created.

Note: use php with apache
If you included the directive --with-apxs, to build a mod_php instance, checkinstall (but also make install) will tell you that almost one LoadModule directive has to exist. This happens because the installation process reads /etc/apache2/httpd.conf, that is not used in Ubuntu, so let's fake it. Add the following line:
LoadModule php5_module /usr/lib/apache2/modules/libphp5.so
to /etc/apache2/httpd.conf; create it if it not exists. You will need sudo to write such a file.
After generating the package, you could clean this file and leave it empty as Ubuntu uses the /etc/apache2/mods-enabled/ folder to maintain the LoadModule directives.

Step 3: avoid conflicts
The compilation process has not touched your system yet, but probably there is an old installation of php hanging around that will get in the way. Let's remove all package and extensions: if you need a particular extension you should have included it in Step 1; if you need a PECL or PEAR package you will grab it later, in the new installation.
This will remove any package whose name contains php:
sudo apt-get remove --purge `dpkg -l | grep php | awk '{print $2}';`
You could also delete /usr/share/php, the PEAR folder. A new pear will be installed if you enable it in Step 1 and old files will point the old php binary and it will be a mess. Take them out:
sudo rm /usr/bin/php
sudo rm /usr/bin/pear
sudo rm /usr/share/php
If you have any PEAR packages, the folder was not removed by apt because it was not empty.

Step 4: install your brand new, fine-tuned package
Assuming that your package is named php5_5.3.0-200907181600_i386.deb, install it:
sudo dpkg -i php5_5.3.0-200907181600_i386.deb
You will find it in the source folder.
If you're using php from the command line you have finished. You have the possibility to run pear on php 5.3 and install what you want.
If you use php with apache, you need to set up the loading of mod_php. Put in /etc/apache2/mods-available two files named php5.conf

AddType application/x-httpd-php .php .phtml .php3
AddType application/x-httpd-php-source .phps
and php5.load:
LoadModule php5_module /usr/lib/apache2/modules/libphp5.so
The content could slightly differ, and the files may already be present (from your previous installation).
Then Apache could use php compiled by you:
sudo a2enmod php5
sudo /etc/init.d/apache2 restart
Enabled the module, and restarted the webserver. Have fun with your shiny new php!

Tuesday, July 21, 2009

Naked objects in Php

The validity of Naked Objects pattern, if implemented successfully, can add value to the php scene and help to answer the "Is Php ready for the enterprise?" question. Currently there is no framework to support this approach in the php world.

Php in the enterprise
The enterprise world has several architectural choices to build complex applications: Model-View-Controller frameworks are currently in vogue, especially in the php world, where Zend Framework, Symfony, Code Igniter, CakePhp and many others all implement this paradigm. But there are also examples in different languages: Ruby On Rails, Django for Python, Spring and Stripes for Java.
There is also a niche where developers are tired of bloated controllers and views that contains logic; they're also tired of dumping their own objects and get some megabytes of data because they have dependencies on all the instantiated objects of the chosen framework: here comes in NakedObjects.
As I wrote last week, the Naked Objects pattern let the framework take care of 3 of the 4 layers of an enterprise application: infrastructure, controllers and views are provided as generic or generated objects. The developer has only to write a Domain Model layer that follows some conventions.
Two frameworks that are named Naked Objects exist: one is written in Java and it is open source, while the other runs on the .NET platform; they are provided by the same people behind nakedobjects.org. Domain-Driven Design is really possible when using this tools.
I couldn't find a similar possibility for the average php programmer: it's a pity because php has the potential to introduce more and more cloud computing in the enterprise applications, let you use only a browser as a client.
There is also JMatter available, for Java.

Why wait?
So I decided to write a new one, a port of the Naked Objects for Java framework. It will have only a web interface anyway, since it is the best fit for php (no local GUI as it does not make sense).
Since I don't want to reinvent the wheel, it will incorporate Doctrine 2 (which I am contributing to) in the persistence part of the infrastructure layer and Zend Framework with its MVC implementation in the upper ones. Since the Naked Objects pattern has to be followed, the Views and Controllers will be provided from this framework, which I named NakedPhp. Obviously I chose an Open Source license, the bullet proof LGPL version 2; supporting DDD is also a key feature which I want to include.
Here are some links that points to the main resources activated on SourceForge to support the project:
Main page
Naked Php wiki
In-browser view of the Subversion repository
I will blog often about the architectural decisions of NakedPhp and its improvements, and when a alpha downloadable package will be available. Of course the repository is open to anyone who wants to take a look at the source code.
If you're tired to write controllers and views, consider the choice of a Naked Objects approach. And if you are a php developer and you want to participate, contact me!

Thursday, July 16, 2009

Lazy loading of objects from database

What is lazy loading? A practice in object/relational mapping which simulate the presence of the whole object graph in memory. There is some techniques for produce this illusion that I explain here.

An example
Suppose we have the classic User and Group objects in a php application. The same process is valid for any language that uses a relational database as a backend, like the Java/Hibernate example, but I will include php code snippets.
Tipically User and Group has a many-to-many relation: every user can subscribe to many groups and every groups has a bunch of users as its members. This means that if all objects are loaded from the database you can navigate like this:

$user = find(42); // find the user with id == 42
echo $user->groups[3]->users[2]->groups[4]->name;

Having a potentially infinite navigability in an object graph is not a great practice, but sometimes many-to-many relationships are needed and the simplest approach is to incur in additional overhead (why there is overhead will be explained later) and provide this simple Api.
The main problem is that we cannot load all the object graph, because it will not fit in the memory of the server and it will take much time to build, depending on the size of the database. Nor we can load an arbitrary subset of it, because the user has the freedom to navigate groups and users to the depth he need: if he arrives at the edge of the graph will see null values/null pointers where objects should be.

Solution: Lazy loading
The Proxy pattern comes in our help:
A proxy, in its most general form, is a class functioning as an interface to something else. The proxy could interface to anything: a network connection, a large object in memory, a file, or some other resource that is expensive or impossible to duplicate.

In the first navigation the proxy will be a subclass of Group. The Data Mapper, without further instructions, will provide this type of object graph:

var_dump($user); // User
var_dump($user->groups[3]); // Group_SomeOrmToolNameProxy
var_dump($user->groups[3] instanceof Group); // true

As said previously, an Orm that provides lazy loading will produce a proxy class to substitute the original one. The code for this class is generated on the fly and will look like this:

class Group_SomeOrmToolNameProxy
{
public function __construct(DataMapper $mapper, $identifier)
{
// saves as field references the arguments
}

private function _load()
{
$this->loader->load($this, $id);
}

public function sendMessageToAllUsers($text)
{
$this->_load();
parent::sendMessageToAllUsers($text);
}
}

The new class proxies to the original methods but calls _load() before, giving the object a usable state. Before a call to _load(), or a call to one of the proxied methods, the domain object has only identifiers field in its internal data structure.
Since it is a subclass of Group, it provides the same interface to the user, that will not even notice that it is not its clean, infrastructure-free Group class.

What does it mean?
It means that the first level objects are fully loaded, while second level ones are placeholders that contains only the information to load themselves. Only if you access them they will go to the database to fetch all their fields:

$user = $em->find(42); // a query on the user table
echo $user->groups[3]->name; // another query is executed on the groups and user_groups tables

We can complicate this pattern as far as we want:
  • We can specify with join() commands on the query objects or 'join' options for the methods of the Data Mapper how far it should go with the initial loading. This way if we know that we need to access the second level of the graph starting from user, only one query is executed. Still if we go to the third level ($user->groups[3]->users[2]->role) without specifying that at the reconstitution of $user, additional queries will be sent to the database and performance will suffer.
  • We can activate or disactivate lazy loading, or logging it to view where it is executed and impacts the performance
Hibernate for Java uses this approach to feature lazy loading of object properties and relations. Doctrine 1.x use a simpler approach because it is based on Active Record and the code is put in the models base class Doctrine_Record.

Today I contributed to the ORM\Proxy namespace of Doctrine 2, the component that generates the proxy classes and objects basing on metadata about the original classes, and non-invasive lazy loading will soon became a reality.

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