Here I will describe my devthinkings, doing a little experiment and developing a minimal CMS from a BDD way in PHP with PHPSpec. While we will be using BDD and TDD techniques, the metaprogramming paradigm, DDD software development approach, and ORM tools, we’ll also defining and explainig the process from the start.
Thanks to David García Chavez and his BDD faith ;)
I’ve discovered DDD some time ago, and had been trying to apply it in my daily work with good results. Well, I had success with pure TDD in C# .NET, developing components for a greater .NET IT system, but now i’m immersed in PHP world so i’d been seeking some solutions to do the tests. First, I tried PHPUnit, but then I decided to auto-approach the BDD paradigm (instead pure tests, or perhaps using the TDD way), defining Given-When-Then (GWT) User Stories.
But in a conversation with David he said me that he tried Cucumber in Ruby, but he detected fragile test design, making difficult the traduction from English literal text to code, and he told me that he prefers When/ItShould specifications.
A point he remarks: is very costly to design all the step definitions. Unless you need at all costs to define GWT step definitions to communicate with the final client, do not use Given-When-Then.
He said that GWT was a great idea, and finally, and I agree totally with the sentence, that the breach between the User Story and the Context/Specification is what it makes you THINK about the problem to be solved.
It mades me thinking of search about another PHP BDD system, so I googled and PHPSpec appeared to me, I readed a bit about Cucumber ,that understands Gherkin, another like YAML or Python describing languages and is used in behat for php also. I will try that later ;)
Typycal Cucumber looks like this screenshots:
PHPUnit is Cucumber/Gherkin DSL based. PHPSpec is RSpec based. PHPUnit, based on GWT, looks like this:
Rspec is another ruby BDD too, using When/ItShould DSL, andd looks like:
And with PHPSpec we have:
So I installed PHPSpec and begin to play with BDD in PHP. I will describe the process from the start, to build a minimal PHP CMS with cutting-edge characteristics like MVC Pattern support, ORM and code-first approach, DDD Design and BDD implementation.
So I needed to develop a BDD / TDD approach to define the behaviour of a new web based Content Management System, (well, the CMS really exists and i have the code for myself, but i want to rewrite it bdd way …) and I wanted to define too some test to check the system integrity (behaviour and classic tests). This is what I will write about in this article series. The building of a minimal PHP CMS.
I assume that the reader have a basic knowledge of OOP, DDD and software design patterns. The TDD will be our guide to code.
We want to develop the specifications for the project, so it can be also the documentation of the code itself. The specs must translate to plain English and viceversa. The chosen library and language is PHPSpec with Mockery.
Well,’ll start for a really simple CMS. Basically we’ll need a series of components, an ORM, a Template Engine, Controller Engine and so on … I’will explain more in the followind posts.
We want a template system to server as the “VIEW” part of the MVC Pattern. I choosed RainTPL for speed and simplicity, only one class. We’ll need more com
The Good Approach to Software Development
The BAD way:
If you are an experienced developer, i’m sure that you had encountered this typical sequence:
- A project is assigned to you
- You start coding, or designing immediatly. Your experience dictates you’r coding quality,speed and features, of course.
Well, this is a NO-NO-NO, as we all kno. In its multiple representations, types of software development techniques, and all the mess … at the end, we all start coding this way most of the time. Sometimes pressed by deadlines, spare resources or similar.
The GOOD way:
We’ll use a top-down general method to complete the project (we start defining the main core object), but ocasionally we will encounter with some bottom-up code. Imagine, after a refactor cycle we have to develop a new class with some subclasses, and we start with one subclass, so the traditional top-down bottom-up design its very dependant on the development cycle.
The process of coding itself is based in a typical loop following the red-green-refactor mantra. We’ll call this the SpecLoop, and it will be defined by the following actions sequence:
I call a Spec/Test to a Specification within a Context (that can act as a base for a Test on the Behaviour of the System, or a base for a “unit-test”). Perhaps i’ll had to change this in the future, but keep moving:
- Start coding only one Spec/Test
- Run Spec/Test
- If Spec/Test fails, go to code and resolve the issue, goto step 2 and repeat the Spec/Test run until it passes.
- When the Spec/Test pass, repeat the Spec Loop with the next Spec/Test, IF THERE ARE ANY
David called red-gren+refactor+check-in-dance a microiteration in the develop process at their paper. That’s similar.
Remember, I call a Spec/Test to the specification to be implemented, or the test to be passed. The context is the environment in wich our SUT (System Under Test) is being tested.
PART 1: BDD The Start
Defining the first specification
In plain English, we have our first specification:
BDDCMS Should be an Behaviour Driven Design Content Management System.
I started with a basic specification defining the basic CMSCore Object and its Context (the before funtion is called before running all Spec/Tests, so it can be used to stablish the base context). As you can see, the context is defined by the $_SERVER array, because effectively defines the context within the application runs (a web server reveiving a URL and dispatching it into our CMS) , and the core object $BDDCMS is instantiated. I used the autoloading PHP feature to organize the classes into namespaces, as you can see. So, we create DescribeNewBDDCMS.php as:
The specification says that the new \BDDCMS\Core Object must be an instance of a \BDDCMS\CoreCMS Object. This is pretty obvious, but we are starting from the begginning of the project and this will help us to start defining the \BDDCMS\CoreCMS Class.
Then the phpspec.php script was executed and the BDD fails after execution, as the next screenshot shows.
So, now, the spec give us a RED FAIL because we do not have a $CoreCMS Object, so we start coding it in /BDDCMS/Core/CoreCMS.class.php
So, if we run again the Spec/Test, it passes, so we obtain:
We have GREEN PASS, so …
… it is time to choose, we will call this the SpecDecision. The question is … ¿ Have we finished the project ?
- Refactor code: We must ensure that our code meets our expectations in terms of quality. It we feel that it is not OK in “sexy” terms, we must refactor. We must make use from sotware patterns when possible, and write quality code.
- Or we can add new Specs/Tests, one by one, and repeat the SpecLoop and the SpecDecision.
- If we do not neet to refactor, neither add new specs, the project is DONE, congratulations.
This definition is approximate and I have a problem in the refactor phase definition, as David remarked me. We must avoid to create new specs in this refactoring phase, according to the BDD Church. When we refactor, the behaviour doesn’t change, but the internal structure yes. We introduce patterns as possible, do code modificacion, renaming variables, functions, and changing it scope, etc, things like that. That way we’ll not forced to introduce new specs.
But I Think that, if you are an experiended programmer, perhaps you already knows what you’l need, and this can be an advantage in the process, because the refactor-dont-create-new-specs rule can be broken. If we introduce a concretefactory, perhaps we need to extrapolate and create and abstract factory too and then we are forced to introduce inheritante and new Spec/Tests to define the new classes, but, as I said, more the experience, more the speed and depth of the refactoring phase.
At this point, the project is far from being finished, and we do not have to refactor, so it is time to write new Specifications.
So my personalized BDD approach to software development can be resumed in the following minimal algorithm to be followed while coding:
- Define the first Spec and start the first SpecLoop.
- Take a SpecDecision and repeat, until project fihishes.
See you in Part II.