Promoting open/close principle and loose coupling between components

Intro

I’m a big fun of event-driven architecture and how different components in a system react to different state changes in a domain. Mostly because it promotes loose coupling between components and services. Sometimes it's also a good paradigm to pipe and filter architecture since, for instance, the consumer of an event might just have the responsibility to filter, transform and forward the event to another component of the system. Moreover coming from distributed environments and architectures, an event-driven approach extends horizontal scalability making them more resilient to failures promoting high availability and eventual consistency [6, 7].

Motivation

The initial scope of the article was to avoid ActiveRecord Callbacks mostly because of its unwanted side effects [4] and hard to remove afterward. Other drawbacks would be violating the single responsibility principle and slowing down our test suite. Leaving AR callbacks on the side the next thought would be to decouple a service object from directly calling other services to fulfill a use case as we will see below. The advantage of the last point is that we promote the open-close principle and have a better view of the purpose of a given use case and what are its side-effects. …


When to check when business rules apply?

The question is quite common in software development. Given an instance of a class, you want to know when to check if a class is valid or not. Do you skip validations before executing an action or do you first check if the instance is valid before executing an action?

Let’s see a simple example. Image an entity called FlightReservation and some validation or better business invariant rules that require a flight reservation to be valid when it contains no more than max_passenger passengers.

class FlightReservation < AggregateRoot
MaxPassengersReachedError = Class.new(StandardError)
attr_reader :passengers
attr_reader :max_passengers
def initialize(max_passenger)
@max_passengers = max_passengers
@passengers = Set.new
end

add_passenger(passenger)
if (passengers.size …

Reduce coupling and dependencies between communicating objects. An event-driven approach.

Design patterns are reusable solutions to a commonly occurring problem within a given context in software design [1]. Having design patterns in mind is a good habit in general, but it should be avoided to apply them from the beginning. Thinking about good design is a good thing but applying it all the time can hurt your software, maintenance and the effort that someone needs to put in order to understand what a single class does. …


Intro

The Repository pattern is a way of working with a data source. In the book Patterns of Enterprise Application Architecture, Martin Fowler describes a repository as follows:

A repository performs the tasks of an intermediary between the domain model layers and data mapping, acting in a similar way to a set of domain objects in memory. Client objects declaratively build queries and send them to the repositories for answers. Conceptually, a repository encapsulates a set of objects stored in the database and operations that can be performed on them, providing a way that is closer to the persistence layer. …


Motivation

As developers we always try to find the chance to apply new ideas. Normally I tend to keep things simple and rarely plan ahead on good design and abstractions. Having the big picture upfront and plan your code ahead needs experience and a lot of passed failures to learn from.

Recently I came across a codebase where we had to add a new feature on top of an existing implementation. It was implemented a couple of months ago and still, it kept growing an growing. …

Laerti Papa

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store