Design patterns

Classic design patterns

Design patterns are typical solutions to common problems in software design. Each pattern is like a customizable blueprint used to solve a particular design problem in your code. They define a language that efficiently improves team communication.

They can also be used to improve code readability and cleanness, as well as to simplify the design.

Refactoring.guru is a great online place to learn more about them.

Rails patterns

Factory

Class that has one creation method with a large conditional.

Problem

You have a method which instantiates a different type of object depending on a particular parameter.

Solution

Read more here.

Form object

Move form-specific logic away from your ActiveRecord models into a separate class.

Problem

Solution

Read more here. Note: Form objects work great with active_type.

Value object

A small simple object, like a date range or location, whose equality isn’t based on identity.

Problem

The problem can be spotted by finding: * attributes that don't make sense on their own * logic that is tightly coupled with primitives (attributes with behaviour - methods)

Solution

Read more here. dry-rb is a Ruby gem that can be used for value objects.

Null object

Instead of returning null, or some odd value, return a Special Case that has the same interface as what the caller expects.

Problem

You have a lot of conditionals scattered around many classes or view files that check the same thing. It's usually a low-level error handling part that covers calls to nils.

Solution

Read more here.

Query object

Represent a database query or a set of database queries related to the same table.

Problem

Solution

Read more here.

Service object

Concentrate the core logic of a request operation into a separate object.

Problem

You have a complex set of operations that need to be executed in a sequence synchronously or asynchronously.

Solution

Read more here. Note: Service objects can easily become a code smell if not handled properly. If you find yourself with a service object that has too many methods and/or becomes generally unreadable and hard to understand, you might have to find a bounded context or use one of the design patterns mentioned in this chapter.