Backend Knowledge Sharing #23

MySQL Indexing, Refactoring Business Logic into Actions , and State Pattern in Laravel

Kushal Raj Shrestha
YoungInnovations' Blog

--

Indexing MySQL database

Indexing is a way to optimize the performance of a database by minimizing the number of disk accesses required when a query is processed. It is a data structure technique that is used to quickly locate and access the data in a database.

How does DB indexing works? This week Ashish Shakya provided us an insight on this.

Indexing is a way of sorting a number of records in multiple fields. Creating an index on a field in a table creates another data structure which holds the field value, and a pointer to the record it relates to. This index structure is then sorted, allowing Binary Searches to be performed on it.

Following syntax can be used for an index:

// Add an index to existing table:
CREATE INDEX index_name ON table_name ( column1, column2,...);// Update for an index:
ALTER TABLE table_name ADD INDEX (column_name);// drop an index:
DROP INDEX index_name ON table_name;

Refactoring Business Logic to Actions in Laravel

Laravel is a flexible PHP framework, where we can structure our architecture as per our needs in the project. Based on the project size, we define core components such as Controllers and Models following the MVC architecture. But, for a medium to a large-scale project, considering scalability and maintainability on the mind, it is not good to write our business logic, a critical part of our project, in controllers and models. Writing such business logic in a single file like controllers and models, making them a God Object, results in a spaghetti code which makes more harder to cope with the future changes. There are so many ways to resolve this issue by extracting business logic into different single responsible classes in OOP, and Actions class is the one among them.

Action classes are simple classes without any abstractions (inheritance) or interfaces. It is a class that takes input, does something and may/may not gives output. That’s why an action class usually has only one public method, and sometimes a constructor (for dependency injection). For the convention, we will name this class with suffix “Action”, eg, CreateUserAction. Here are some points to be considered while working on Action classes, though these points are recommended not bind to follow strictly.

  • Ac action class should have a name which is self-explanatory, such as CreateUserAction.
  • Action classes are responsible for only one action, hence it should have only one public method, usually named as execute() or handle().
  • It should be request and response agnostic because usually Http request and response are generally responsible to controller classes, and Action classes could be called from controllers as well as other classes like CLI commands, etc.
  • Though it should not be dependable with any external dependencies, it can have its own internal dependencies. It can also have other Actions classes as dependencies.
  • Since action classes follow the “Single Responsibility Principle”, it should return only one type of data. In case of errors or other response, it is best to throw an exception.

Let’s see an example of implementing a class. Consider we have a module, which is supposed to save a blog post in the database and then tweet the post’s title on Twitter.

The controller would look like this.

class PostController 
{
public function create(Request $request, TwitterService $twitterService)
{
$post = new Post();
$post->title = $request->input('title');
$post->content = $request->input('content');
$post->is_published = true;
$post->save();
$twitterService->tweet($post->title);

return back()->with(
['message' => 'Post has been submitted and published.']
);
}
}

Here, the business logic is defined in the controller’s method. It is not a good idea to write these in the controller’s method because we might need to do the same from another place (let’s say a CLI command) in the future or might need to change this with some other logic.

Let’s extract that logic into an Action class.

class CreatePostAction
{
public function __construct(TwitterService $twitterService)
{
$this->twitterService = $twittterService
}

public function execute(array $data):Post
{
$post = $this->savePost($data);
$this->tweet($post->title);
return $post;
}

public function savePost(array $data): Post
{
$post = new Post();
$post->title = $data['title'];
$post->content = $data['content'];
$post->is_published = true;
$post->save();
return $post;
}

public function tweet(string $text): void
{
$this->twitterService($text);
}
}

and refactor controller action as follows.

class PostController 
{
public function create(Request $request, CreatePostAction $action)
{
$post = $action->execute($request->all());

return back()->with([
'message' => 'Post has been submitted and published.']
);
}
}

The complete code of implementing Action class is in the Github repo.

References:

The State Pattern in Laravel Eloquent

The state pattern is a design pattern where a class behavior changes based on its state. Generally, this kind of pattern is called a behavioral software design pattern. The more in-detail example of implementing this pattern can be read from the following blog post.

--

--