Showing posts with label nakedphp. Show all posts
Showing posts with label nakedphp. Show all posts

Friday, March 26, 2010

The rest of the NakedPhp walktrough

This post's title is a parody of The Rest of the Robots.

In the previous post we have seen how to manipulate PHP objects directly, and calling methods on them, thanks to NakedPhp's user interface. Today we will see how to interact with the database, essentially how to store object in it and retrieve them via Repositories.
The situation we left the example application into was the following:
There are two Example_Model_City objects in memory (London and Paris), and a Example_Model_Place (Eiffel Tower) which references, with a many-to-one directional association, Paris.
We are ready to save our session. Generally, a subset of the application's object graph is instantiated in memory, modified and put back in the storage. We are not assuming that the storage is a relational database: it is simply a component that take an object graph and persist it someway. In PHP, one of the few library that can do this is Doctrine 2, which will map our objects on a set of relational tables.
We check that there are no objects to remove, and then click Save:
Note that after saving the session, the objects' color changed. In the example application I associated via CSS rules green to transient objects and orange to managed ones. The difference between the two is that a transient object will vanish if we let the session expire, while a managed one is already present in the storage (so it should be actively removed if we want it to vanish.) The save action response tells us three new entities have been persisted, and no managed ones. Moreover, no objects have been removed.
Let's close this session and click Clear.
The session is now empty, and in the last screen we are already gone to the PlaceFactory object. We notice a new findAllCities action available. It has appeared now because there is a hideFindAllCities() method on Example_Model_PlaceFactory, which returns true until there are no cities in the database (Services has access to external infrastructure like storage and whatever we want them to use, while Entities usually have no external references since they have to be serialized.)
The findAllCities action brings us back all the cities stored in the database. This is an "object" - really an array, but every variable saved in the session is wrapped in a NakedObject instance.
The difference between a normal object and an array is that a wrapped array has a Collection Facet, and the views recognize this Facet and treat it differently. Particularly, they list the contained objects and provide access to them.
Finally, note that this Entity is managed and not transient, because it has been retrieved from the storage.
By clicking on the row of an item of the collection, the object is extracted in the session (it is considered transient because the semantic for the extracted objects has not been written yet. This will be fixed in the future.) It still refers to the same instance in the collection, so if we modify one we'll see the changes in the other.
We now see an example of method call with object parameters. The createPlaceFromCity action will take a City and create for us a new Place object with the city property already set. But we don't like the current cities: we want another one.
As it was the case of Entities editing, the context is conserved between different method calls. We have clicked on createCity and we are now creating Rome.
The new object is available for the original method call now.
And finally, the action returns a new Place object which is stored in the session. The city has been set correctly.

That's all for now. I have exposed a practical example of NakedPhp features and of direct manipulation of objects, which has been persisted, retrieved, and moved around.
Now I can go back to add other features, such as semantics for removal and extraction of objects, and a complete method merging feature. What do I mean? It will be useful to have the createPlaceFromCity method also on every City object, so that, given a city, it will present to the user a Factory Method for Places. In this case, we could have put the method on the Example_Model_City class, but such a method may require collaborators which we should not inject on City: imagine a sendByMail(City) or searchSimilar(City) methods which access mailers or the database. With method merging, any service method which has in its parameters an object of class A will be callable from A objects as well, with the particular A parameter automatically passed and hidden.

The method merging feature was already present in NakedPhp but is currently broken (if I had acceptance-TDDed it, it wouldn't have been.)
See you in April for NakedPhp 0.2 and some news!

Thursday, March 25, 2010

A NakedPhp walktrough

Today I'll present a walktrough in the NakedPhp example application, to show the direct manipulation of objects it provides, with features like calling methods and editing of Entity objects.
The example application manages a Domain Model that contains places (shops, sightseeings, and so on) and cities. Places have a directional many-to-one relationships with cities.
I will upload a screenshot for every step.The graphic is very basic, but it is not a responsibility of the framework. Every application can write its own layout, complete with style sheets, and assemble the content pieces differently.

Supposing we had set up correctly the example application, to start working we have to load the naked-php controller default action. In my Apache configuration I set up the public/ directory as the DocumentRoot of the example virtual host. There are really no differences with others Zend Framework applications.
The starting page shows in the header the two declared services (managed as singleton-like instances), an empty session and a context bar, which we can ignore for now. Classes of a Domain Model are divided in two parts: Services (always available and never serialized) and Entities (managed in the session bar and passed around). Factories and Repositories go under the Services umbrella, while ValueObjects for now are not supported because the underlying object-relational mapper does not support them yet.
Clicking on the PlaceFactory service in the header will send us to the object Example_Model_PlaceFactory, with a list of the available actions (exposed methods, not filtered for now):
If we click on createPlace, a new Example_Model_Place object will be created by this factory method. This methods has no parameters and creates an instance with default values. We are redirected to that instance, which now is in the session bar:
If we click again on PlaceFactory and choose the createCity action, a form will be shown since this method requires one parameter (the name of the city):
We insert London as the name and submit the form. A new object is put in the session bar and we are redirected to it as it is the result returned by the method. The session bar keeps object in the PHP session: we are not touching the database. This means that entities should be serializable, and this leaves us free to use Plain Old PHP Objects that do not extend any framework class. The only requirement is that the phpdoc annotations and a few other ones are present to determine the type of parameters and method return values.
After the creation and the redirect, a list of the properties of the Example_Model_City object is shown:
Note that the object different specifications (classes) are distinguished by different icons.
If we go back to the Default Name Place by clicking on it and follow the link on the pencil, an editing form is generated basing on the setters available on the object.
Note that the context bar now contains one more link (other than Index). When a form for selecting method parameters or objects fields is shown, the context is conserved. If we don't like the objects we have in the session, we can go around looking for better ones, or create them. In the example, we want to create the Eiffel Tower Place and since it is not in London, we need a Paris City object. So even if we are on the form, we simply go on the PlaceFactory service and select the createCity action again:
The context has grown again (it can be reset by going to the index if someone screws up.) Then we submit the form and we are redirected to the last action we were calling, the editing of the entity 1:
 
We can now select Paris for the city field and change the name to Eiffel Tower, then submit the form. Unfortunately collections are not supported and we will get an error, but the process works well until it encounter the events collection (not yet implemented). If we simply reload the index page and click on the newly renamed Eiffel Tower object, we'll see it has been correctly edited.
We have worked only in-memory and not had any interaction with the database yet. This post is getting long so I will show you tomorrow the second part of the walktrough, where we save these entities and retrieve them with a method that is hidden or shown automatically basing on the current state.

Tuesday, March 23, 2010

Introducing NakedPhp 0.1

I dedicated a bit of my time to develop a port of the Naked Objects framework for Java, which I named NakedPhp. Essentially, the Naked Objects pattern is the automatic animation of an object-oriented Domain Model via the generation of the user interface and of the persistence layer, both commonly sources of duplication and kitchen sinks for business logic. Naked Objects is a radical reinterpretation of MVC, where the Model is at the center and the other layers are inferred from it and customized. You will call methods and move objects around in such an application.
This is NOT yet another Php framework: NakedPhp leverages Zend Framework and Doctrine for all the stuff you would expect a normal framework to do.

Previous related posts
Naked objects, DDD and the user interface
A look at technical question on Naked Objects
Naked objects in Php
Where is business logic?

NakedPhp applies the same pattern to Php applications, and I have tagged its 0.1 release today (this is an alpha release.) The Api is borrowed from the original Java Naked Objects framework. This is by no means a complete framework, but it's a good start since its basic CRUD functions are already working.
NakedPhp integrates Zend Framework 1.x for the user interface management and Doctrine 2 for the persistence layer. As for all Doctrine 2 applications, it requires Php 5.3, which is why I don't have an online demo right now.
Links
NakedPhp 0.1 on SourceForge
Bug tracker
Git repository (view it online):
git clone git://nakedphp.git.sourceforge.net/gitroot/nakedphp/nakedphp

A simple example application realized with NakedPhp is provided in the released package, which uses a bundled sqlite database. An application for NakedPhp is just a plain old Zend Framework application with a controller that inherits from NakedPhp\Mvc\Controller, and that inits the Entitymanagerfactory (related to Doctrine 2) and Nakedphp resources with the mandatory options like the path to the model classes's folder. NakedPhp is very liberal about what you do in your application: it only generates the first-step views and leaves you the layout for customization.
I will write related documentation about how to hook NakedPhp in an application in the next days which I will store along with the code in the Git repository on SourceForge.
The behavior of the generated interface (which is not scaffolding: it's intended for actual use and not for being modified) is driven by annotations on the model classes and by methods with special names. For example, properties available on Entity objects are inferred from getters and their modification is possible if correspondent setters are present. Other methods are called when available to determine automatic hiding of properties and methods (hideName(), hideFindAllCities()), validation of data and so on.

The sample application provides a basic workflow for an hypothetical Domain Model for shops, pubs, or similar places. You can create Cities and Places, modify their properties, save them in the database, then clear the session and retrieve them via service classes. This is a direct interface to the Domain Model, without translations.
Intructions are included in the release for the super-simple setup of the example application (essentially running phing build-example).

Let me know if you are interested in a framework that writes the user interface for you. I know that the Naked Objects pattern is not appropriate for all situations, but the goal is to simplify the presentation of the real Domain Model to the user for certain kinds of model-driven applications. It is also providing a prototyping interface for Domain-Driven Design in 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!

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