We’re going to be using Behat to run these features. So let’s start a new project!
mkdir sample-app; cd sample-app
git init
We’ll use composer to install Behat:
1 2 3 4 5 6 7 8 |
|
And let’s install it:
1 2 3 4 |
|
So where do we start? BDD says we should start from the outside and move our way in. So, we’ll start with some Gherkin. I’ll make up some requirements that you might receive from a product manager:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
|
Now let’s run it:
1
|
|
You’ll see a bunch of undefined steps with some snippet code. Let’s paste these into our context file (features/bootstrap/FeatureContext.php) and rerun behat. Now we’ll see some TODOs! Time to actually write code! We’ll start from the top:
1
|
|
This is going to be a no-op. We don’t need to do anything here, so let’s just remove the PendingException in the step defintion:
1 2 3 4 5 6 |
|
Now that step should be green when we re-run the behat steps. We’ll move on to the next step. Here’s where the real meat will start. Since we are writing our business logic, we’ll start with defining the interface we want to work with, and write the code we wish we had.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
This might be something we would want. Instantiate a new use case class (Account_Registration), and call it’s execute() method with our registration data.
Let’s run this in behat:
1
|
|
Now we are blocked, we have an error in our tests. So let’s make this thing pass:
1 2 3 4 5 6 7 8 9 |
|
Also make sure you require this file in your FeatureContext class.
1
|
|
Now if you run behat, we’ll have the next step green in both scenarios.
Let’s move on to the next step. What do we do here? How do we assert the account was created? Simple. We want to use Dependancy Injection, and inject a repository object into the use case class. The use case will then use that repository to persist the data. We will use a mock object to keep track of this. We don’t want to use the real thing because we don’t care about the database right now (we will later, and we’ll replace this code later). We’ll need to modify our last step definition:
1 2 |
|
Now when we run behat, we’ll get a fatal error about this Mock class not existing. So let’s just create it at the end of the file.
1 2 3 4 5 6 7 8 9 10 11 |
|
And we’ll need to define that interface. Let’s do that in our classes folder:
1 2 3 4 |
|
Make sure you require that file right above the Mock_Account_Repository class defined above. Now we need to assert that our class does what we want. So in our next step definition, we’ll inspect that mock object:
1 2 3 4 5 6 7 8 |
|
Now when you run this, it should fail. So let’s make it pass.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
On to the next step! We want to send an email out to the user after they register. We need to abstract out the email handling, so let’s make a mock class for that too.
1 2 3 4 5 6 7 8 9 |
|
And the interface for this class:
1 2 3 4 5 6 |
|
And let’s add this to the step definition:
1 2 3 4 5 6 7 |
|
You’ll need to modify some previous steps for this. When you are done, you should get an error like:
1
|
|
So we just need to make this pass. Easy:
1 2 3 4 5 |
|
Sweet! Our first scenario passes! You should be able to implement the rest of the second scenario fairly easily.
This concludes our tutorial on creating a basic Interactor class. It doesn’t do much right now, but next time we’ll add in some validation, and do some other fun stuff with phpspec.
]]>If you recall from last time, I said that this code should live far, far away from your delivery mechanism (your MVC layer). That’s pretty abstract. Where should it really go? How do you write it?
A lot of people look at me funny when I say “do not write your business logic with a framework”. They think “how on earth will I get anything done?”. It’s actually very easy, and not time consuming at all if you do it right.
I’m going to be using PHP for my code examples here. I prefer Ruby, but it seems that it’s “harder” to do this in PHP, so I want to show that it’s actually not.
First off, put your business logic into it’s own repository. This will make the separtion clear and force you to not muck the separation of concerns together. You’ll also be able to recognize your application’s purpose from it’s file structure, as described in the Uncle Bob talk from last time.
People in the PHP world seem to like the PSR-0 standard for file and class naming so we’ll use that, but not the silly PSR-1 and PSR-2 “standards”.
Below are the components that we’ll be using to design our application.
Back in school you learned about a Use Case, right? Well, they aren’t useless after all. Use cases are the backbone of how your application works. We’ll be using a use case driven architecture from now on.
Why? They let us define our classes in a structured way, and let any reader of our code know exactly where to go when they need to look at some functionality. Need to know about how a user registers? Simply go to the Register_User class, all the code is there.
I prefer to use the DCI pattern for describing my use cases in code. However, it’s not clear how to implement DCI in many languages. Because of this, I’ll just be describing interactors, which are a similar but simpler way to write use cases.
DCI makes a lot more sense overall, but in some languages (especially php), it’s just impossible to implement properly. You basically would need the ability to assign traits to objects at runtime (at the minimum), and php is certainly not capable of that.
An interactor is just a class that describes your use case. It has the following properties:
execute()
So where does your database access come into play in all this? A lot of frameworks make you think about the database entirely too early. The database is just a detail about where/how your data gets persisted. Don’t worry about it too much yet. Just worry about defining your Data Objects first. We’ll use a repository pattern to send those data objects to be persisted, and it doesn’t really matter to anyone but the repository class on how that’s done.
Your data objects classes that model your business objects. They don’t extend anything, they don’t connect to a database. In php, they are just POPOs (Plain old php objects). Here’s a good example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|
Easy.
A repository class is an object that persists and retrieves data objects. That’s all it does. Here’s an example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
|
The repository class should take data objects in, and spit data objects back out. That’s it.
Next time we’ll start building an actual interactor.
]]>If you have feedback for me, please use twitter (on the right over there) to do so.
Before I begin, you should watch this (I’m basically going to be rehashing it and adding my own notes):
So, lets start with MVC. Web-based MVC (yes, not the “real” kind). “What’s wrong with MVC?”, you might ask? Well, nothing, as long as you use it for it’s strengths: as a delivery mechanism pattern. We’ll get into what a delivery mechanism is in a bit. So, how do you use MVC effectively? Well, lets start with the different parts of the acronym:
Your controllers are thin, right? Do they contain only http logic? If they contain any business logic at all, they are not thin. Just because it’s not database calls doesn’t mean you can throw it in the controller. The controller shouldn’t know anything about your domain logic. It should just know:
That’s it! What do you gain from doing this?
When I say “view”, does “class” also come into mind? Are you doing all your presentation logic in your templates? Stop it! You can’t test that. Use something like Mustache. What do you gain by using Mustache?
Logicless templates let you start your views with tests (You do TDD, right?). It keeps your views more maintainable and lets you be more confident that the logic contained in them actually works.
When you write your view classes, they should only accept input from the outside world. They should not be reaching into the database, they should not be instantiating any classes (especially not models!). All they should be doing is accepting input from the controller and formatting that input for display. This display can be anything: html, json, xml, etc. This is another advantage of using mustache: it lets you easily adjust your output template, and not change your logic that parses the data. Reuse people!
Wow, what a big area. Basically anything that isn’t a controller or view goes here. That is A LOT. This is the first problem with using MVC 100% to design your application. If you subscribe to the “thin controller, fat model” approach (as just about all web frameworks out there teach you), you will end up with an unmaintainable mess of an application.
Why? Well, first off, you’ll be combining your domain logic (since your controllers are thin, right?) and your persistance logic (just about every framework tells you to put queries in a model) in the same layer. This is very bad for many reasons:
A lot of the topics in this series will revolve around testing. How can you make your application easier to test? How can you start with tests?
So what can we do? Easy: Don’t use models. Just don’t. Models don’t belong in your MVC delivery mechanism. In this sense, I suppose I should be calling it CVT (Controller-View-Template).
What’s this “delivery mechanism” thing, anyway? A delivery mechanism is:
A framework of classes that easily let you redistribute your business logic (your application) in a format specific way, over a specific medium.
Your application is not made up of controllers and views. That stuff is all part of your delivery mechanism. So from here on out, I’ll be refering to your business logic as your application.
You do need these things. You don’t want to be writing http request and response classes. That crap is already done, and it’s a lot of work.
A delivery mechanism’s sole purpose is to call your application, and send it’s output to a specific format. It could be an html website, a JSON based REST API, or a console based binary. All three of these could be delivering the exact same business logic. All three of these could be different frameworks, because your application is completely decoupled from your delivery mechanism.
Your delivery mechanism should not know anything about your business rules, except how to call the application. It consumes your application, and spits out the data.
Ever cry when your favorite framework released an upgrade, and it broke the old API? Separate your application from your delivery mechanism, and upgrading to a new version (or a completely different) framework becomes much easier. The framework code no longer has it’s slimy tentacles embeded inside your code. That means less code to change.
This brings me to a related topic: You should try like hell to never have your business logic classes extend a third party class. Don’t let someone else taint your class’s API with theirs. You’ll just end up in a similar situation to the framework problem above. I’ll go into more details on this in a future post.
“If we can’t use models, then were the hell does the business logic go?” You might be asking. Easy:
Far, far, far, far away from your MVC layer. We’ll get into the details on this next time.
]]>