Working with Dapper (Part 1)

In the previous series, I talked about how I was able to put together database context and "repository" classes for what the team calls the new "core architecture". In Part 4 of that series, I mentioned about the CRUDS interfaces, but I did not expand on them. This new series covers the CRUDS interfaces themselves, and how they can be used to complete the repositories.

CRUDS stands for Create, Read, Update, Delete and Search. I used this as basis for naming the CRUDS interfaces: IDbDataCreatable, IDbDataReadable, IDbDataUpdatable, IDbDataDeletable and IDbDataSearchable. These interfaces define only one method signature each to Create(), Read(), Update(), Delete() and Search(), respectively. As separate interfaces, developers can create a repository that inherits only the interfaces the model needs to implement.

This design goes against common repository implementations by other developers, where they seem to require their repositories to implement all CRUDS for the model, even if the method is not needed (except to throw a NotImplementedException perhaps). Such designs are restrictive and not realistic in the types of applications the team works on. While most models may require all CRUDS operations, there are some models that can represent, for example, audit data (creatable, readable and searchable only), immutable data (creatable, readable, deletable and searchable only) or read-only data (readable and/or searchable only). Consider also the possibilities that there may be variations of creating, reading, updating, deleting and/or searching the same model.

The CRUDS interfaces are provided to the team as guides. In the "core architecture", there is nothing that would prevent a developer from defining their own methods in the repositories. The developer guidelines given to the team, however, do ask the team to always try implementing with the CRUDS interfaces first. Even when creating a variation of the methods, the guidelines ask the team to copy the same signature and change only the method's name -- for example, creating DeleteByParentID() should have the same signature as the IDbDataDeletable.Delete() version.

The team wants productivity without compromising flexibility and creativity. However, it is just as important to avoid becoming a big ball of mud. The success of the "core architecture" down the line would depend on the discipline of the team, but more so on how well requirements can be supported and be fitted in to the core architecture's design.

Comments