Ryan Tablada

Christian, UX Tycoon, Instructor at The Iron Yard

Checkout my screencasts at EmberGrep

Checkout my newest book on Leanpub

Two Design Patterns That Will Make Your Applications Better

Getting into design patterns can be a bit of a tricky subject. An analogy would be like having a kid interested in engineering go from playing with box cars to telling them to design and build an entire car manufacturing plant (or at least that's the way I felt when not so gently introduced to design patterns). But, this doesn't have to be our reaction, and this should be a guide for two patterns which will significantly improve your application structure while allowing you to learn a bit of a slow pace.

1. The Repository Pattern

The repository mediates between the data source layer and the business layers of the application. It queries the data source for the data, maps the data from the data source to a business entity, and persists changes in the business entity to the data source. A repository separates the business logic from the interactions with the underlying data source or Web service.

Well, that gem of CTO technobable is a bit cryptic, so thank you MS for that awesome definition. It is confusing because many people will say: "Well, Eloquent breaks down my data from my business logic and gives me a nice API and some abstraction."

But, ORMs don't actually fall into a repository pattern. In reality the only layer of abstraction you get is a driver instantiation to some variant of PDO (yes you could hypothetically write flat file drivers that don't rely on PDO [or even Mongo drivers if you like talking about "big data", "Series A Rounds", or anything obnoxious along those lines]).

A great design pattern for Laravel projects is to add a repository abstraction layer in front of your models to perform functions such as creation, searching, deleting, etc. By example, think about making a tag basd CRM. At first you may have the tags set in a CSV list in a user model. So, using traditional Eloquent techniques you would always have to have:

$users = User::where('tags', 'like', $tag)->get();

But quickly moving over to a many to many relationship means that everywhere you had the above query, you would have to change over to:

$tags = Tags::with('users')->where('tag', $tag)->get();
$users = $tags->users;

Then think again of having to move this over to raw SQL queries or file storage.

Instead, creating a repository gives the abstraction of making so that your controller looks like this:

$users = $this->userRepository->getWhereTag($tag);

And your repository could look like:

public function getWhereTag($tag)
{
    // Queries here
}

Plus, in a future post, we will look at the huge benefits of the repository pattern in terms of TDD and Interface Driven Design.

2. The Gateway Pattern

A gateway encapsulates the semantic gap between the object-oriented domain layer and the relation-oriented persistence layer.

Once again: definitions fail us. This seems straightforward, so you are likely nodding your head at your CTO, smiling, and comparing the usefulness of this with the knowledge of why hash tables have a prime number length.

One of the messiest parts of any MVC applications is creating all the related models required from a single form. Even with Laravel's Eloquent syntax your controller would have a bit of awkward syntax.

$input = Input::all();

$comment = new Comment(array('message' => $input['message']));

$post = Post::create(array('title' => $input['title']));

$comment = $post->comments()->save($comment);

Things get even worse when you consider adding validation and other factors. This really isn't very semantic is it? What if we could replace the above with:

$post = $this->postGateway->createPostAndCommentWithInput(Input::all());

Now your controller is nice and slim while staying semantic and only worrying about grabbing the input!

One thing to note is that some architects will call these Services, but I stray away from this terminology given that many developers are using Services to do things such as just validation, mailing, etc. Instead we limit gateways to giving a more semantic shorthand for working with persistence relationships. As an added advantage, we won't revert to using our API controllers in an HMVC pattern (Taylor will like that).

Next week, we will look at testing gateways and adding validation and exceptions into gateways.

comments powered by Disqus