## Table of Contents - [MVCS Antipatterns](#mvcs-antipatterns) - [Creating entities for association tables](#creating-entities-for-association-tables) # MVCS Antipatterns In simple terms, Model-View-Controller-Services add a few more layers to the MVC pattern. The main one is the service, which owns all the core business logic and manipulate the repository layer. ## Creating entities for association tables You'll often need association tables, for instance to set up a many to many relationships between users and their toasters. Let's assume that a toaster can be owned by multiple users. It might be tempting to create a `UserToaster` entity for this relationship, especially if this relationship has some complex attributes associated with (for instance, since when the toaster is owned by the user). Let me pull a few quotes from the [Domain Driven Design](http://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215) by Eric Evans: > Design a portion of the software system to reflect the domain model in a very > literal way, so that mapping is obvious. > Object-oriented programming is powerful because it is based on a modeling > paradigm, and it provides implementations of the model constructs. As far as > the programmer is concerned, objects really exist in memory, they have > associations with other objects, they are organized into classes, and they > provide behavior available by messaging. > Does an object represent something with continuity and identity— something > that is tracked through different states or even across different > implementations? Or is it an attribute that describes the state of something > else? This is the basic distinction between an ENTITY and a VALUE OBJECT. > Defining objects that clearly follow one pattern or the other makes the > objects less ambiguous and lays out the path toward specific choices for > robust design. Evans, Eric (2003-08-22). Domain-Driven Design: Tackling Complexity in the Heart of Software. Pearson Education. Kindle Edition. Entities should model business processes, not persistence details ([source](http://blog.sapiensworks.com/post/2013/05/13/7-Biggest-Pitfalls-When-Doing-Domain-Driven-Design.aspx/)). - In that case, `UserToaster` does not map to anything the business is using. Using plain English, somebody might ask about "what toasters does user A owns?" or "who owns toaster B and since when?" Nobody would ask "give me the UserToaster for user A". - The association table can be considered an implementation detail that should not (in most cases) leak in the domain layer. All the code should be dealing with the simpler logic of "user having toasters", not UserToaster objects being an association between a user and a toaster. This makes the code more intuitive and natural. - It will be easier to handle serializing a "user having toasters" than serializing UserToaster association. - This will make it very easy to force the calling site to take care of some business logic. For instance, you might be able to get all `UserToaster`, and then filter on whether they were bought. You might be tempted to do that by going through the `UserToaster` object and filtering those that have `were_bought` to be True. At some point, you might be doing the same thing in multiple places, which will decrease maintainability. If you were hiding that logic in the repository, you wouldn't have that issue `find_bought_toasters`. So in that case, I would recommend doing the following: - Create a `User` and `Toaster` entity. - Put the association properties on the entity that makes sense, for instance `owned_since` would be on `Toaster`, even though in the database it's stored on the association table. - If filtering on association properties is required, put this logic in repositories. In plain English, you would for instance ask "give all the toasters user A owned in December?", you wouldn't ask "give be all the UserToaster for owned by user A in December". Note that Domain Driver Design recommends avoiding many-to-many relationships altogether: > In real life, there are lots of many-to-many associations, and a great number > are naturally bidirectional. The same tends to be true of early forms of > a model as we brainstorm and explore the domain. But these general > associations complicate implementation and maintenance. Furthermore, they > communicate very little about the nature of the relationship. > There are at least three ways of making associations more tractable. > 1. Imposing a traversal direction > 2. Adding a qualifier, effectively reducing multiplicity > 3. Eliminating nonessential associations Evans, Eric (2003-08-22). Domain-Driven Design: Tackling Complexity in the Heart of Software (Kindle Locations 1642-1647). Pearson Education. Kindle Edition. Imposing a traversal direction is probably the best solution. In our example, it's not immediately evident which direction is the right one (a toaster being owned by a user, or a user owning a toasters), because that depends on what this application is doing. If we're working on an app that lets a connected user see their toasters, then we would force the relationship to be unidirectional user->toasters. Sources: - [7 Biggest Pitfalls When Doing Domain Driven Design](http://blog.sapiensworks.com/post/2013/05/13/7-Biggest-Pitfalls-When-Doing-Domain-Driven-Design.aspx/) - [Domain-Driven Design: Tackling Complexity in the Heart of Software](http://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215)