Factory Pattern: It is All About the Clients

How Factories make you focus on your business rules

Lucas Vargas Noronha
3 min readJul 3, 2022

When you develop an Enterprise Application, your code must describe the business. Every code line must convey a meaningful step of your business model. Yet, we still have to deal with non-functional aspects like databases, logs, and message brokers.

A Factory promotes clean code with a Domain Model by assisting clients (e.g., application layer or even other domain models) to instantiate domain objects without leaking their internal structure (repositories, gateways, strategies, etc.).

The following sections will describe a Use Case and how we can use a Factory to improve the code quality.

Use Case: Create a Tweet

For this article, we will implement a simplified version of Twitter core's functionality, creating a tweet with some tweaks. Our functional requirements are:

  1. Only registered users can create tweets
  2. A tweet is text-only
  3. Default Users' tweets can have up to 140 characters.
  4. Famous Users’ tweets can have up to 280 characters

Technical Solution

Note: our goal is to describe the Factory pattern. Therefore, the solution is not applicable for production

We will implement it using Domain Models. However, we will do it incrementally; everything starts with a single function.

Creating a Tweet in Golang

The problem with this approach: crucial business rules are exposed in a single function. If we add more rules or even non-functional requirements, it will become a mess:

This is hard to read, difficult to change, and ugly. As Software Engineers, our code must be beautiful. If we do not strive for it, how can we become better?

How can we improve this code?

Domain Models

Our Domain says: Users create Tweets. So we should code it.

Is this not the same? For now, we will tune this domain yet. But now our Application Layer is readable:

However, our User model is doing a lot of things. Why do we not delegate some responsibilities to the Tweet Model?

Tweet Model

We want our Tweet model to:

  1. Validate itself
  2. Persist itself
I am omitting some functions, but you can check the complete code here.

A Tweet only exists if a User creates it, so the User is responsible for instantiating a Tweet object and passing its dependencies. Otherwise, a Tweet model would never be able to save itself. If a Tweet needs a Domain Event Publisher, we would need to inject in the User object before. This is a problem. We are leaking object internals to another one.

Also, the User is still defining the max characters a Tweet should have. What if we want to add more validations to our Tweets? We do not want the User to know all these things. We want some decoupling between Users and Tweets.

For now, our code is no better than the first version presented in this article. We just moved code to other functions and different namespaces. This is not encapsulation.

If a User already has all dependencies of a Tweet, it would not make sense to delegate responsibilities to the Tweet model. Therefore, how can we respect our Domain and keep our code beautiful?

Factory Pattern

We want to separate responsibilities between User and Tweet. Users will create Tweets, but Users objects should not know how Tweets objects work internally.

Factories hide object creation details (Tweet) from their clients (User).

Therefore, we will use a Factory to hide how Tweet validations are made and its dependencies (repository in this case)

I changed our Tweet model. Check this commit

Now that we have a Factory specializing in creating Tweet objects, our User Model is more elegant:

Since TweetFactory holds all dependencies for creating a Tweet, we do not need to inject it into our User.

Do we need more external dependencies? Inject in the TweetFactory
Do we need more validations? Append into validators

Now our code is clean, therefore, beautiful.

Code

Check https://github.com/vargasmesh/tweet-factory for the complete code

References

  1. Domain-Driven Design by Eric Evans
  2. Patterns of Enterprise Application Architecture by Martin Fowler

--

--