What I Learned Building a Zend Expressive Application
A few months ago, I was contracted to build a new web-based application, in effect a user portal. In many ways, it was a brilliant project for getting my feet wet with Zend Expressive.
On the whole, I feel that the project’s gone well. It’s been quite an undertaking — especially for a sole developer. But despite that challenge, it’s a robust application, with only minor feedback during the testing phase.
So now that I’ve come out the other side, and learned a lot of valuable lessons about developing applications using Zend Expressive, I want to share three of them with you today.
Specifically, I want to share three ways which I believe, if I’d used them, I could have built the application faster, and with less code and complexity.
My intent in doing so is to show that, while Zend Framework has an enterprise reputation, that doesn’t mean that large development teams are always required to build applications with it.
I’m keen to encourage a more honest understanding of the framework. I hope that if you’ve built one or more applications with it, you’ll share your experiences as well.
The Application - A Quick Overview
It wasn’t a small application; arguably it entered the “enterprise” space. So, to build it correctly, it needed a lot of thought and planning.
It wasn’t going to be something which I could knock out overnight, cross my fingers, and hope for the best. I feel the remit was too complicated for that kind of approach.
Without breaching confidentiality, amongst other things, here’s what it had to do:
- Manage users
- Manage addresses
- Manage documents & directories
- Manage business opportunities
Given that, the domain model was reasonably complex, with a lot of models requiring sophisticated object hydration and extraction, and related business logic.
1. Don’t Go Overboard. Think Simple!
Here was the first turning point in the road, one which I could have navigated better.
I’ll be honest, ever since I became hooked on all things testing, specifically Test Driven Development, Behaviour Driven Development, and most recently Domain Driven Development, I’ve become quite obsessed with ensuring that anything and everything is testable.
In addition to that, I’ve also become rather obsessed with dependency injection, which to me goes hand-in-hand with TDD (and friends).
You may know where I’m going with this. If not, I created classes for everything! From input filters and validators to entities, value objects, forms, entities and more. If a class could be created, I created it.
You might be horrified to hear this. You might not see what the problem is. But bear in mind, I was the sole developer on this project. The development team consisted of me, me, and only me.
So, while this approach may work well for a team of developers, say of 5 or more, it didn’t work well for a team of one. This experience taught me that for a sole developer, or perhaps only a few, this isn’t the right approach.
So if this reflects your situation, my advice is, if you’re in the same position as I was — Don’t Go Overboard. Think Simple!
That’s easy advice to give. But, how can it be tangibly applied? Here’s how; look at the needs of your application, first and foremost.
Do you need to have separate classes for anything and everything? Do you need utmost flexibility and reusability? If not, look at combining responsibilities into fewer classes.
Here’s a specific example; instead of creating an entity object with a separate InputFilter for data validation, consider having the entity class implement the
This interface defines the following two methods:
public function setInputFilter(InputFilterInterface $inputFilter); public function getInputFilter();
If you take this approach, the entity can be self-validating, and the validation logic, along with the accompanying test logic, can all be grouped together.
This results in requiring the creating, testing, and maintenance of fewer classes. Perhaps you’ll have a situation where you need a different InputFilter, such as when validating based on data from a form, versus data from somewhere else.
In that case, you can override the default InputFilter, yet maintain the same class interface. What’s more, regardless of either situation, the class can make use of dependency injection, and can be thoroughly tested.
2. Make Good Use of Available Patterns
This leads me to my next suggestion — make good use of available patterns!
There’s been such a flame war over recent months about both the validity and usefulness, perhaps overuse, of software design patterns.
Depending on which side of the proverbial, fence you sit on, you might see patterns as overly academic, or you might see them as the excellent tool which they are.
Either way, Zend Framework’s built on them — and it doesn’t hide the fact. Even a cursory glance over the framework and the Zend Expressive skeleton project will show you that.
For example, have a look in
dependencies.global.php, and you’ll see a default configuration using terms such as invokables, factories, and abstract_factories.
If you’re going to use Zend Framework to the full, you’re only able to, the more you know what these patterns are, and when they should be applied.
That takes time — granted. Given that, this section doesn’t come with clear-cut advice. I’m not able to say do specifically this, or don’t do that.
What I encourage you to do, however, is to make it a priority to learn about the most common software development patterns, and then see how you can apply them in Zend Framework.
To get started, I recommend the following resources. I’ve used them all and find them to be of great value, and of high quality.
Design Patterns is an excellent book, usually referred to as the definitive guide on the subject. It’s not a light bedtime read, but it’s well worth it, for the level of detail it provides about common software design patterns.
Source Making is an excellent site, which focuses on four key areas of software development; those being:
- Design Patterns
I find that it does an excellent job of effectively distilling information about these areas, without dumbing them down in the process. Definitely check out one, or both.
3. Make Smarter Use of Software Patterns
After you’ve begun familiarising yourself with design patterns and started applying them, actively keep an eye out for how you can apply them in smarter ways.
For example, when creating page action classes look for any commonality amongst them, such as the constructor requiring a
RouterInterface and a
TemplateRendererInterface object, or that they return a
Ask yourself: do you need to have an action class for each and every action in your application? Alternatively, can you combine them?
There’s nothing special about them. They render the contents of a template in an
HtmlResponse object. Given that, you could have one-page action, and based on the request, supply the relevant template. Now you have less code to create, build, test, and maintain.
Then there’s how you instantiate them. Say the use case isn’t so simple; say the constructor signature of one or more is different. Perhaps one takes a repository, or another kind of object.
You might then feel you can’t combine them. You may be right. Perhaps you can’t. But then you should look for another way of simplifying your codebase — how they’re instantiated.
Here, you could implement the
\Zend\ServiceManager\Factory\AbstractFactoryInterface and use the third parameter of the
$options, to supply details to determine which class to invoke.
4. Do You Need a New Class For That?
This is something I’ve been pondering throughout the development of the recent project. Do I need a new class? Take for example a case where I need a form to gather data to create a user, and another to update a user.
Would you create two classes in this case? Would you create a base class for the create user page action, then create another for the update user page action, which extended the first?
Perhaps that’s not necessary. Maybe the original class could be configured slightly differently in a custom service configuration.
For example, you could configure a service called
addUserForm. This instantiates the form object, pre-populating the form elements, such as select lists, and radio buttons, ready to be rendered in the page template.
Say for updating a user; the form then needs a different InputFilter for validation. You could then configure a second service configuration, which retrieves the initialised form from the first service, and does some supplemental configuration, before returning the form object.
This way, you’ve saved yourself from creating and maintaining multiple forms. That’s perhaps a bit of a contrived example; but, I don’t think it would be too much of a stretch.
That’s a Wrap!
That’s three ways in which you can simplify development of Zend Expressive applications. It’s not been an exhaustive look but provides a good jumping off point all the same.
If you’ve been developing using Zend Expressive for a while now, what ways have you found simplify development? What tips, tricks, and strategies do use?
Please share your experience in the comments.
You might also be interested in...
- Unit Testing Zend Expressive Database Classes with Codeception
- How to Begin Migrating From Zend Framework 2 to Zend Expressive
- How To Build a Local Development Environment Using Docker
- How To Use Laravel’s Eloquent ORM with Zend Expressive
- The 3-Step Guide to Downloading Files in Zend Expressive
comments powered by Disqus