{"id":3362,"date":"2021-08-25T19:58:43","date_gmt":"2021-08-25T11:58:43","guid":{"rendered":"https:\/\/tzlee.com\/blog\/?p=3362"},"modified":"2022-02-08T00:57:30","modified_gmt":"2022-02-07T16:57:30","slug":"why-unit-of-work-is-an-anti-pattern-but-not-repository","status":"publish","type":"post","link":"https:\/\/tzlee.com\/blog\/2021\/08\/why-unit-of-work-is-an-anti-pattern-but-not-repository\/","title":{"rendered":"Why Unit of Work is an anti-pattern but not Repository"},"content":{"rendered":"\n<p>Is Repository and Unit of Work (UoW) an anti-pattern? In the .NET\/C# world, it is often said that Repository\/UoW is an anti-pattern and one should probably <a href=\"https:\/\/www.thereformedprogrammer.net\/is-the-repository-pattern-useful-with-entity-framework-core\/\">use Entity Framework Core directly<\/a>.<\/p>\n\n\n\n<p>But if it is an anti-pattern, why are people still using it? Even Mosh Hamedani &#8211; a respected YouTube coding trainer whom I follow &#8211; <a href=\"https:\/\/programmingwithmosh.com\/net\/common-mistakes-with-the-repository-pattern\/\">wrote about common mistakes when applying this pattern<\/a>. Surely it must be popular.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"purpose-of-the-repository-uow-pattern\">Purpose of the Repository\/UoW Pattern<\/h3>\n\n\n\n<p>Let&#8217;s talk about why this design pattern exists. It is actually a type of <a href=\"https:\/\/refactoring.guru\/design-patterns\/adapter\">Adapter pattern<\/a> and the primary use case is for separation of concerns between domain (or &#8220;business logic&#8221;) and infrastructure (or &#8220;data access&#8221;).<\/p>\n\n\n\n<p>The other motivation for using this pattern is to allow mocking repositories for unit testing.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"must-repository-go-together-with-unit-of-work\">Must Repository go together with Unit of Work?<\/h3>\n\n\n\n<p>It is also very common to see the Repository pattern used together with the Unit of Work (UoW) pattern. The UoW pattern is added to manage transactions &#8211; a feature of relational databases to perform <a href=\"https:\/\/en.wikipedia.org\/wiki\/ACID\">ACID<\/a> operations.<\/p>\n\n\n\n<p>However, there is increasing tolerance for eventual consistency and less atomicity; fully ACID operations are starting to matter less these days as software adopts the <a href=\"https:\/\/en.wikipedia.org\/wiki\/Microservices\">microservice architecture<\/a>.<\/p>\n\n\n\n<p>So unless you are a bank, or dealing with critical financial data, maybe building your software with transactions management &#8211; a feature that is specific to RDBMSes &#8211; might not be the kind of <em>dependency<\/em> you want.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"why-is-uow-an-anti-pattern-sometimes\">Why is UoW an anti-pattern <em>sometimes<\/em><\/h3>\n\n\n\n<p>I&#8217;ll start by saying that <strong>everything depends on your use case<\/strong>, but for me &#8211; I tend to feel that Unit of Work (but not repository) is an anti-pattern.<\/p>\n\n\n\n<p>Let me explain why.<\/p>\n\n\n\n<p>You see, the repository interface can be described in its simplest form as an interface for read\/write operations.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ What a typical repository looks like\npublic interface IMyRepository\n{\n  MyObject GetById(int id); \/\/ Read\n  IEnumerable&lt;MyObject&gt; SearchByName(string name); \/\/ Read\n  void Update(MyObject object); \/\/ Write\n  void DeleteById(int id); \/\/ Write\n}<\/code><\/pre>\n\n\n\n<p>I&#8217;ll use an analogy here: In good old C, the <a href=\"https:\/\/en.wikipedia.org\/wiki\/C_file_input\/output\">standard input\/output header<\/a> defines basic read\/write operations. The interface &lt;<code>stdio.h<\/code>&gt; is an abstraction of the underlying data access implementation and is a close example of the repository pattern &#8211; the interface doesn&#8217;t care if you are writing to the console, to a filesystem, or to a serial port &#8211; just like a repository interface shouldn&#8217;t care if it was an RDBMS, or a CSV file, or even a remote API call.<\/p>\n\n\n\n<p>Does <code>&lt;stdio.h&gt;<\/code> expose specific features of a particular filesystem or a serial port? No. So why should a specific feature of an RDBMS (transaction management) be depended upon outside of a repository interface?<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><meta charset=\"utf-8\"\/>userRepository.Update(user);\nunitOfWork.Save(); \/\/ If this was not done, the record will not be updated!<\/code><\/pre>\n\n\n\n<p>Using the C example from earlier: Imagine having to <em>always<\/em> call <code>fsync()<\/code> (from <code>&lt;unistd.h&gt;<\/code>) after calling <code>fwrite()<\/code> in order to commit changes &#8211; does it make sense? Sure &#8211; you may call <code>fsync()<\/code> if you wanted to <em>force<\/em> your changes to disk immediately, but you do not and should not have to explicitly call it.<\/p>\n\n\n\n<p>(In .NET there is <a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/framework\/data\/transactions\/implementing-an-implicit-transaction-using-transaction-scope\">Transaction Scope<\/a>, but that is a topic for another day.)<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"how-much-to-depend-on-the-rdbms\">How much to depend on the RDBMS?<\/h3>\n\n\n\n<p>RDBMSes are great tools with important features, but as an application architect, I often ask myself if it really matters to the application I am building.<\/p>\n\n\n\n<p>Sure, almost 99% of the time the RDBMS is unlikely to be switched for anything else. Heck, in some <meta charset=\"utf-8\"\/>applications it may even be the same version of MySQL for the rest of the application&#8217;s life &#8211; that&#8217;s probably because many applications were designed with a database-first approach (and I have another blog article coming up about why a <a href=\"https:\/\/tzlee.com\/blog\/2021\/09\/avoiding-database-first-approach-to-application-design\/\" data-type=\"URL\" data-id=\"https:\/\/tzlee.com\/blog\/2021\/09\/avoiding-database-first-approach-to-application-design\/\">database-first approach should probably be avoided<\/a>.)<\/p>\n\n\n\n<p>So you may think, <meta charset=\"utf-8\"\/><a href=\"https:\/\/en.wikipedia.org\/wiki\/You_aren%27t_gonna_need_it\">YAGNI<\/a> &#8211; let&#8217;s not over-design the application. Maybe in such a case, you <em>may<\/em> be better off without the Repository\/UoW pattern entirely, but&#8230; this is 2021, and you are unit testing your code, <em>rightttt?<\/em><\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"unit-tests-and-mocks\">Unit tests and mocks<\/h3>\n\n\n\n<p>If you have ever attempted to mock an ORM framework, you&#8217;ll know it is pretty impossible. Sure, EF Core has an <a href=\"https:\/\/docs.microsoft.com\/en-us\/ef\/core\/providers\/in-memory\/\">In-Memory Provider<\/a> that can be used for testing, but that has a lot of <a href=\"https:\/\/github.com\/dotnet\/efcore\/issues\/18457\">caveats<\/a>.<\/p>\n\n\n\n<p>As a result, it would be easier to apply the repository pattern instead of attempting to mock the ORM framework.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"mocking-the-test-or-testing-the-mock\">Mocking the test, or testing the mock?<\/h3>\n\n\n\n<p>Ever had unit tests pass but integration tests fail because of database constraints? Ever tried testing code that relied on a transaction rollback? Mocking the behavior of an RDBMS is extremely difficult, and spending half our lives trying to mock how an RDBMS works shouldn&#8217;t be the case because we do not want to end up testing our mocks instead.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ Typical use of UoW\ntry\n{\n  userRepository.Update(user);\n  unitOfWork.Save(); \/\/ This commits the transaction\n}\ncatch (Exception ex)\n{\n  unitOfWork.Rollback();\n}<\/code><\/pre>\n\n\n\n<p><em>Example: How would you mock and test the rollback?<\/em><\/p>\n\n\n\n<p>Instead, we should implement repositories as if we were writing data to regular storage &#8211; think of it as writing to a CSV file, memory, Redis cache, or something else.<\/p>\n\n\n\n<p>Do CSV files have transactions? No.<\/p>\n\n\n\n<p>Then, maybe we should not use Unit of Work:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>try\n{\n  userRepository.Update(user);\n}\ncatch (Exception ex)\n{\n  <meta charset=\"utf-8\"\/>\/\/ Log an error and fix it manually, retry the operation, place\n  \/\/ the update in a queue to be processed later if you really HAVE \n  \/\/ to make this update, otherwise just throw the exception!\n}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"the-generics-phenomenon\">The generics phenomenon<\/h3>\n\n\n\n<p>The typical Repository\/UoW pattern is to make each repository represent a single domain entity, e.g.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>public interface IUserRepository\n{\n<meta charset=\"utf-8\"\/>  public void GetById(int id);\n  public void Create(User user);\n<meta charset=\"utf-8\"\/>  public void Update(User <meta charset=\"utf-8\"\/>user);\n<meta charset=\"utf-8\"\/>  public void Delete(int id);\n}\n\npublic interface IGroupRepository\n{\n<meta charset=\"utf-8\"\/>  public void GetById(int id);\n  public void Create(Group group);\n<meta charset=\"utf-8\"\/>  public void Update(<meta charset=\"utf-8\"\/>Group <meta charset=\"utf-8\"\/>group);\n<meta charset=\"utf-8\"\/>  public void Delete(int id);\n} <\/code><\/pre>\n\n\n\n<p>And as a result, it is common to have these further reduced to a generic interface to reduce the repetition on CRUD methods, e.g.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>public interface IRepository&lt;TEntity&gt;\n{\n  public void GetById(int id);\n  public void Create(TEntity entity);\n<meta charset=\"utf-8\"\/>  public void Update(TEntity entity);\n<meta charset=\"utf-8\"\/>  public void Delete(int id);\n}\n\npublic interface <meta charset=\"utf-8\"\/>IUserRepository : <meta charset=\"utf-8\"\/>IRepository&lt;User&gt; { ... }\n<meta charset=\"utf-8\"\/>public interface <meta charset=\"utf-8\"\/>IGroupRepository : <meta charset=\"utf-8\"\/>IRepository&lt;Group&gt; { ... }<\/code><\/pre>\n\n\n\n<p>However, quite a large number of applications I have written do not use the full CRUD operations on every single repository. Some tables are read-only, some never require an update, some never get deleted.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"the-n-n-relationship\">The N-N relationship<\/h3>\n\n\n\n<p>Next, how do I add a user to a group, or assign a group to a user?<\/p>\n\n\n\n<p>Create yet another repository for the intermediary N-N relationship table and insert a record!<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>public interface IUserGroupRepository : IRepository&lt;UserGroup&gt; { ... }\n\n\/\/ Usage\nvar userGroup = new UserGroup(userId, groupId);\nuserGroupRepository.Create(userGroup);\n<meta charset=\"utf-8\"\/>unitOfWork.Save(); \/\/ Always remember to save!<\/code><\/pre>\n\n\n\n<p>This is why implementations of the Repository\/UoW often end up with a crazy list of interfaces and classes, and it&#8217;s probably not easy for a developer to figure out <em>which repository to use<\/em>. Is it called UserGroup or GroupUser? @#$%^&amp;<\/p>\n\n\n\n<p>It is also extremely counter-intuitive to be actually creating a new object. In a regular object-oriented code, it would probably be written like this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>group.AddUser(user);<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"why-aren-t-repositories-written-more-expressively\">Why aren&#8217;t repositories written more expressively?<\/h3>\n\n\n\n<p>Unlike <code>&lt;stdio.h&gt;<\/code> in C that I used as an analogy earlier, repository interfaces are not doing byte-level I\/O operations &#8211; it handles more complex data types, so methods should therefore be written more expressively.<\/p>\n\n\n\n<p>For example, why not write the User-Group relationship methods in such a manner?<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>public interface IUserRepository \n{\n  public void AddGroup(int userId, int groupId); \/\/ Inserts into UserGroup\n  ...\n}\n\npublic interface IGroupRepository\n{\n  public void AddUser(int groupId, int userId); <meta charset=\"utf-8\"\/>\/\/ Inserts into UserGroup\n  ...\n}<\/code><\/pre>\n\n\n\n<p>Even better &#8211; if your application will never ever see the need to store Users and Groups in different data stores, why not simply combine them into one repository interface?<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>public interface IAccountServiceRepository\n{\n  public void CreateUser(User user);\n  public void CreateGroup(Group group);\n  public void CreateUserWithNewGroup(User user, Group group); \/\/ Can use a transaction\n  public void AddUserToGroup(int userId, int groupId); \/\/ Inserts into UserGroup\n  ...\n}<\/code><\/pre>\n\n\n\n<p>(Imagine you were writing to the UNIX <code>\/etc\/passwd<\/code> and <code>\/etc\/group<\/code> &#8211; how would you implement it?)<\/p>\n\n\n\n<p>One may argue that I&#8217;ve come full circle and am replicating a UoW but at the same time also violating the <meta charset=\"utf-8\"\/><a href=\"https:\/\/en.wikipedia.org\/wiki\/Single-responsibility_principle\">single-responsibility principle<\/a>. Then again, what is the &#8220;<meta charset=\"utf-8\"\/>single responsibility&#8221; of a repository? Often the term &#8220;single responsibility&#8221; is being taken out of context from what the originator (Robert C. Martin) had expressed it to be: &#8220;A class should have only one reason to change&#8221;. What external or structural influences may cause the interface above to change?<\/p>\n\n\n\n<p>Lastly, if <code><meta charset=\"utf-8\"\/>CreateUserWithNewGroup()<\/code> required a transaction for an atomic operation, shouldn&#8217;t the transaction be managed at the repository rather than by the domain? Should the onus of transaction management be placed on the domain layer or the repository layer? Is handling transactions in the domain logic also<meta charset=\"utf-8\"\/> violating the <meta charset=\"utf-8\"\/><a href=\"https:\/\/en.wikipedia.org\/wiki\/Single-responsibility_principle\">single-responsibility principle<\/a>? <\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"conclusion\">Conclusion<\/h3>\n\n\n\n<p>Once again, if your software or company really, really, really depended its life on having consistent data in an RDBMS, by all means, continue to use the Repository\/UoW pattern (or simply use the ORM directly since it is a hard dependency.)<\/p>\n\n\n\n<p>But for a large majority of cases, <a href=\"https:\/\/en.wikipedia.org\/wiki\/You_aren%27t_gonna_need_it\">YAGNI<\/a>. A single repository interface alone is probably good enough.<\/p>\n\n\n\n<p><em>This blog article was more of me thinking out aloud than trying to encourage or influence a change in how people implement repository\/UoW, and comments are most certainly welcome.<\/em><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Is Repository and Unit of Work (UoW) an anti-pattern? In the .NET\/C# world, it is often said that Repository\/UoW is an anti-pattern and one should probably use Entity Framework Core directly. But if it is an anti-pattern, why are people&#8230; <a class=\"more-link\" href=\"https:\/\/tzlee.com\/blog\/2021\/08\/why-unit-of-work-is-an-anti-pattern-but-not-repository\/\">Continue Reading &rarr;<\/a><\/p>\n","protected":false},"author":2,"featured_media":3594,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[8],"tags":[595,594,461,621,547,623],"class_list":["post-3362","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-tech","tag-net","tag-c","tag-database","tag-design-patterns","tag-programming","tag-software-engineering"],"jetpack_featured_media_url":"https:\/\/tzlee.com\/blog\/wp-content\/uploads\/2021\/08\/pexels-photo-169573.jpeg","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/tzlee.com\/blog\/wp-json\/wp\/v2\/posts\/3362","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/tzlee.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/tzlee.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/tzlee.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/tzlee.com\/blog\/wp-json\/wp\/v2\/comments?post=3362"}],"version-history":[{"count":168,"href":"https:\/\/tzlee.com\/blog\/wp-json\/wp\/v2\/posts\/3362\/revisions"}],"predecessor-version":[{"id":3659,"href":"https:\/\/tzlee.com\/blog\/wp-json\/wp\/v2\/posts\/3362\/revisions\/3659"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/tzlee.com\/blog\/wp-json\/wp\/v2\/media\/3594"}],"wp:attachment":[{"href":"https:\/\/tzlee.com\/blog\/wp-json\/wp\/v2\/media?parent=3362"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/tzlee.com\/blog\/wp-json\/wp\/v2\/categories?post=3362"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/tzlee.com\/blog\/wp-json\/wp\/v2\/tags?post=3362"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}