Design Guide - Controllers, Services and IOC

Posted: 2014-09-22 10:14:50

Design Guides

  • Controllers - contains application logic and passing user input data to service
  • Services - The middleware between controller and repository. Gather data from controller, performs validation and business logic, and calling repositories for data manipulation.
  • Repositories - layer for interaction with models and performing DB operations
  • Models - common laravel model files with relationships defined

In and Out Burgers

Between the user's request and the response is the application. The above design guide not only gives us a consistent, flexible way to manage a requests and responses from a web user but then leads us into creating applications that can manage consul request as well.

in and out

Starting with the book by the Author of Laravel, Tyler Otwell

book laravel

The great thing about this book is that it is not really about Laravel but about SOLID design principles

  • Single responsibility principle
  • Open/closed principle
  • Liskov substitution principle
  • Interface segregation principle
  • Dependency inversion principle

[wikipedia solid](http://en.wikipedia.org/wiki/SOLID_(object-oriented_design)

Change to scope does not cause bad code, bad design patterns cause bad code.

Scope changes and that is fine. This is key to the success of an application. It must change with the vision of the Product owner as deliverables bring to light what could not be seen on paper, mock ups, whiteboards etc.

If we follow the Solid Design Principles then "change is okay" and easy.

Back to the book "Laravel: from Apprentice to Artisan

So Tyler Otwell goes over each principle showing them in context of Laravel.

Here are some key design patters to grasp

IOC

Inversion of control is fundamental to a flexible application that meets the 5 goals above. By "coding to an interface" we can not only work faster as a team but adapt to change easily.

How to get here?

Other than reading the book consider this common example.

"Build A Contract" Taylor Otwell. Laravel: From Apprentice To Artisan (Kindle Location 75 to 185). leanpub.com.

By hooking an Interface into the Service Provider we can attach any implementation we want to that interface.

This means someone can be working on one part of the app talking to another part that is not even done yet cause they can mock out the responses based on an Interface.

Using

php artisan make:provider BillingInterface

You will easily setup the class to start with in the app/Providers folder

Laravel 5 is taking this to the next level with "Contracts/Interfaces" as a big part of the framework.

laracasts contracts

This also means we can easily swap out classes as needed. The book goes over Billing we have another example Queue. We are using Beanstalkd to work locally and Amazon SQS to work on production. This is all done via such design patters. Interfaces/Contracts around talking to a queue.

Controllers

A request comes in and it sends it to the right service. Finally it delivers the response. Below is an example of what a method in a controller should have and no more.

app/Http/Controllers/ProjectsController.php:31
    public function index()
    {
        try
        {
            $results = $this->service->getAllProjectsForThisUser();
            return Response::json($this->responseServices->respond($results, "Loaded Projects"), 200);
        }
        catch(\Exception $e) {
            return Response::json($this->responseServices->respond($e->getMessage(), "Error Getting Project Failed"), 422);
        }

    }

It traps any errors and responds as needed to that error.

Issues with above?

Yes! Error codes should come from the Service as well. How does the controller know a 422?

Service then does what?

As defined above

"The middleware between controller and repository. Gather data from controller, performs validation and business logic, and calling repositories for data manipulation."

  • Validation
  • Business Logic
  • Calling Repositories
  • Transform Data in and out
  • Lastly returns the results with a know error code.

Since 422 is an HTTP Response

vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/Response.php:64

We should have possible a response transformer class to consider the non HTTP response. Then let the Controller pick from that to find its related HTTP response. See the Build API's You Wont't Hate for more on that. Covered in the other guide shortly too.