DDD + BDD in a YOLO (Symfony2 Components) setup Series: The Renaissance – Part I

I ran into many videos and resources for DDD and have been reading quite a bit. Also doing hands on. I am writing this blog series because I believe we have been incepted. There is chaos, scattered, scant sometimes, and misinformation about DDD and nobody has stepped down to a newbie level yet to explain in a practical way what is going on with the architectures that had been in the works for other languages since the golden era. I am realizing that the PHP world is experiencing this renaissance because the level of many developers have matured in such a way that techniques from the Java world are making renaissance inroads with them in order to cope with PHP enterprise application and smaller applications designed smarter and cleaner.

Let’s begin using a popular tool to illustrate this, then explain what is this, just bear with me:

title DDD Exam Process Interactor
 
participant client
participant http
participant interactor
participant factory
participant repository
participant domain-services
 
client->http: Http Request\n (answer question)
http->interactor: AnswerView
activate interactor
interactor->factory: createFromView(AnswerView)
factory->interactor: Answer
interactor->repository: Answer(s)
repository->interactor: Question(s)\ncreateFromData()
interactor->domain-services: othersMethods()
domain-services->interactor: results
 
interactor->http: QuestionResponse
deactivate interactor
http->client: Http Response

DDD Exam Process Interactor

The Domain
Let’s suppose I am solving an exam questionary problem. My domain is the dealing with exams. From the student point of view is the taking of the exams. From the professor is the creation of those exams. Maybe from the university point of view is grading and administering who to ban or choose for given exams, etc.

The Renaissance
Thanks to several resources and friends I am walking through the learning curve of DDD + BDD now. For me this is a renaissance of the design culture in the PHP world. To describe then what the procedure I am employing is let me focus on the graphic above.

I have grabbed the itent of the student, he or she take an exam and the first thing they know is they are presented with question after question. The question prompts them for an answer and after they have responded then they are given the next question. I writing a behat feature, create a default context from where I use helper class trying to reach a DSL-like helper. Then as I am trying to make pass the feature I create collateral objects thinking always in terms of intent and not in terms of doctrine entities. I don’t want to know anything about doctrine, about a component library or even a framework. Yes I said it right, I hate, I can’t see doctrine and Symfony2 at this point in time. With this pristine mindset then we make the behat feature pass and iterate of course with phpspec on the inner circle to make the phpspec specs pass as well. This is in the spirit of outside-in approach of BDD acceptance and specification. After this is done, things are not there yet. This was a spike and we should relax. Now we need to organize our ideas and rename folders and files and start making sense on the actual model we are creating by giving thought and digging in DDD theory and practice.

What happens here in the diagram above, it explains how the feature goes in terms of transaction like and domain like ideas. Student issues with his or her browser an HTTP request, this is translated to a boundary acceptable request that plugs into the ports/boundary of our domain model. Because it is an answer, the proper DTO/port is an object of type AnswerPort. I have changed the naming here from view to port because I think it makes more sense. All this inputs land on an interactor that bears as collaborators the services, factories and repositories needed to manipulate the domain model and give an application response corresponding to another port. This port gets translated back into an HTTP response and this is sent back to the student, that is another question and some collateral information.

Here is the feature:

Feature: student can take an exam
 
  Scenario: student takes an exam             # features/user_stories.feature:3
    Given student starts an exam              # FeatureContext::student_starts_an_exam()
    And student is presented with a question  # FeatureContext::student_is_presented_with_a_question()
    When student answers to question          # FeatureContext::student_answers_to_question()
    Then student is presented with a question # FeatureContext::student_is_presented_with_a_question()
    When student answers to question          # FeatureContext::student_answers_to_question()
    Then student is presented with a question # FeatureContext::student_is_presented_with_a_question()
    When student answers to question          # FeatureContext::student_answers_to_question()
    Then student ends exam and gets graded    # FeatureContext::student_ends_exam_and_gets_graded()

And this is how I have arranged the project files:

~ tree                                                                                                          
.
└── Domain
    ├── Model
    │   └── Exam
    │       ├── ExamSpec.php
    │       ├── OptionSpec.php
    │       └── QuestionSpec.php
    ├── Port
    │   ├── ExamSpec.php
    │   └── ExamsSpec.php
    ├── Services
    │   ├── ExamRepositorySpec.php
    │   ├── ExamsConverterSpec.php
    │   └── PrototypeManagerSpec.php
    └── UseCase
        ├── ShowsAllExamsSpec.php
        └── ShowsNextQuestionSpec.php

Notice the ports or boundaries (in this case, if we use commands then things change a bit), the domain services (sometimes get confused by application services but should not), and the model entities and value objects. The interactors are also renamed as UseCase’s. I credit here my mentors @igorw, @davedevelopment, and @beau for all the ideas, correction and advice given so far on my first steps.

So I will stop here and leave you a bit hungry for the next series. I appreciate ya’lls support getting the book, donating and just mentoring me along this road. I hope I can give all that I know at the talk in Argentina. If you are interested please contribute with new ideas below in the comments and on the repo I have on github.

I say until next for now. Graciously undeserving all of this.

your friend @cordoval.

5 thoughts on “DDD + BDD in a YOLO (Symfony2 Components) setup Series: The Renaissance – Part I

  1. Interesting read, however a little more context would be nice.

    Presumably, DSL is Domain Specific Logic?

    Also, what is first the code box shown? You said you use a popular tool and would go more into that later but i was unable to find reference to what this was. It looks like a cross-over between PHP and Behat. Perhaps i missed something.

    So if i understand correctly, you are wanting to offload most of the work from Behat/PHPSpec standard logic to your custom tests in your FeatureContext or rather the Spec files where you are wanting to do more comprehensive tests?

    Could you include some minor php code from the spec classes to demonstrate and explain the differences between what your doing here and a typical Behat use case?

    Apologies in advance if i am mixing Behat and PHPSpec specifics, they still seem incredibly similar to me, least feature wise that is.

  2. Presumably, DSL is Domain Specific Logic?

    yes

    explain the differences between what your doing here and a typical Behat use case?

    it is not one or the other, it is how it should be used, or how it is used in the context of a more complete flow, a DDD + BDD flow

    your confusion arises from the fact that you are still understanding how to use the tools individually. The tools are different, they go together, they complement each other. They are not the same, they are used differently.

  3. You wrote:
    “I don’t want to know anything about doctrine, about a component library or even a framework. Yes I said it right, I hate, I can’t see doctrine and Symfony2 at this point in time”.

    You are denying yourself very valuable resources because php frameworks like Symfony and Zend are built using best practices, design patterns and a uniform, modular structure. You can achieve a high level of abstraction with quality code in a relatively short amount of time, compared to programing from scratch. If your point was that you cannot gain all that BDD/DDD has to offer if you use a framework, I disagree. There are symfony2 bundles available to integrate Behat/(b)DDD into full web applications, enabling you to build a feature rich app around your BDD processes. As for myself, I am too just starting out on my BDD/DDD research but I don’t think you should knock frameworks out of the realm of possibility entirely–at least until you’ve given one a shot. Doctrine provides a means to persist real objects directly into the database instead of typing out full queries while trying to maintain a well structured relational schema.. Why re-do work already done/tested/approved/beloved? One of the central goals of object oriented programming is code reuse. It is a big part of the RAD idiom.

    • A few months later, I know…

      Actually, I think that Luis Cordova didn’t mean that you have to forget about those tools and start everything from scratch. When you are working on a DDD approach you don’t have to think about the way you are going to persist your datas/entities because it doesn’t have anything to do in the domain layer. You need to write your entities based on what the domain expert says and anything else.

      The following series is talking about DDD in a Symfony2 application and can help to understand what Luis probably meant when he said that he doesn’t want to know anything about Doctrine, etc… :

      http://williamdurand.fr/2013/08/07/ddd-with-symfony2-folder-structure-and-code-first/

Leave a Reply to Reece Fowell Cancel reply

Your email address will not be published. Required fields are marked *