30
Avoid Repository pattern for operations not related to persistence
Versão em Portugês disponível aqui.
Today I want to share a bit about the Repository and Facade pattern. I will attempt to explain their differences, as there seems to be a few common misconceptions about them.
Let's try to define a repository, from the dictionary: a place, room or container where something is deposited or stored. Interms of programming, the concept can be defined as a class responsible for handling CRUD (create, read, update and delete) operations for a specific domain model through the usage of one or more data sources.
By the definition above, we can see that we should use repositories for CRUD operations only, which means we can have a UserRepository
and never a AuthenticationRepository
, simply because authentication does not describe a set of CRUD operations (assuming we're talking about login/registration operations).
A common mistake I have seen is that some people define repositories for system access operations for example:
abstract class AuthenticationRepository {
Future login(String username, String password);
Future register(String name, String email, String password);
}
Clearly those are not operations for storing/retrieving data and so we should never declare them in a repository. Then what? Facades!
From Wikipedia, we can define a facade as an object that serves as a front-facing interface masking more complex underlying code.
Now let's move on to defining a repository: a Repository is a type of facade that specializes in masking/abstract complex CRUD operations specifically between data source(s).
To compare and constrast, facades are more general than repositories -- they can be used for anything other than persistence. You can use facades to abstract complex interactions within multiple bank APIs. For example:
// Or BankOperationsFacade.
abstract class BankOperations {
Future payTelecomService(double amount, String cardId, String serviceId);
Future transfer(double amount, String senderId, String recipientId);
}
// Custom implementation for XBank interaction goes here.
class XBankOperations extends BankOperations { }
// Custom implementation for YBank interaction goes here.
class YBankBOperations extends BankOperations { }
Let's review the first piece of code featured in our article, but this time, we'll refactor the name of the class to be something more meaningful.
// Or any other meaningful name.
abstract class AuthenticationFacade {
Future login(String username, String password);
Future register(String name, String email, String password);
}
- Facades can be applied to anything that's not persistence based
- Repositories are for wrapping the communication with one or more data sources and abstracting this away from the user of the repository
- Facades are more generic than repositories.
It is important to make use of those concepts properly to avoid writing code that is hard to understand and to maintain a healthy code base.
That's it, I hope this helps you somehow; please let me know your thoughts in the comments section.
30