Is using one-to-one interfaces with domain entities a good or bad practice? Why?

后端 未结 6 1138
梦谈多话
梦谈多话 2021-02-01 17:16

One thing I see in some DDD enterprise apps that I work on, is the use of interfaces that are identical to the domain entities, with a one-to-one mapping of properties and funct

相关标签:
6条回答
  • 2021-02-01 17:26

    The biggest reason for always specifying the domain objects as interfaces instead of directly as classes is to give you a degree of freedom on the implementation. In your example you only have one kind of IAccount, so it's a little redunant.

    But what if you had, for example:

    public class Account : IAccount { ... }       // Usual account, persistent
    public class MockAccount : IAccount { ... }   // Test mock object
    public class TransAccount : IAccount { ... }  // Account, not persistent
    public class SimAccount : IAccount { ... }    // Account in a performance sim
    

    and so on?

    By defining the domain objects as interfaces, you can replace the implementations without disturbing your domain definition.

    0 讨论(0)
  • 2021-02-01 17:31

    One-to-One Interfaces on entities are an anti-pattern

    James Gregory put it better than me here.

    0 讨论(0)
  • 2021-02-01 17:34

    In general, if my classes are not going to be part of a design pattern like Strategy or Visitor I don't add interfaces.

    Adding interfaces is really useful for design patterns like Strategy and Visitor, but in those cases I don't carbon copy the getters and setters of the domain classes. Instead, I create interfaces that are specific for the design pattern interfaces I create.

    interface SomeStrategy {
       void doSomething(StrategyData data);
    }
    
    interface StrategyData {
       String getProperty1();
    
       String getProperty2();
    } 
    

    That allows me to let the domain classes implement those interfaces, or to use the Adaptor pattern. I find this is a much cleaner approach that just creating interfaces for the sake of it.

    Design should always reduce uncertainty. Creating interfaces for the sake of it doesn't reduce uncertainty, in fact it probably increases confusion since it doesn't make any sense.

    0 讨论(0)
  • 2021-02-01 17:37

    I agree with you. Interfaces should act as a contract, so there is no value from having one-to-one interfaces with domain entities. It may be useful if you would like to abstract a certain behaviour. But, this will work in certain cases.

    0 讨论(0)
  • 2021-02-01 17:49

    It's a bad practice as described, but...

    There's no specific reason that your interfaces need to be different than your domain entities; sometimes it really is the right mapping. But it's suspicious that it's always the case. The point of concern there is a question of whether or not the interfaces were truly designed, or whether they were just thrown into place out of lack of time / laziness.

    To use your example, the IAccount interface you describe exposes getters and setters on the Account object; it seems a little odd and unlikely that everything that uses an Account will have a need to set the balance on the account, and that that implied permission is specified at that level of interface. Is there no place in your system where you want to merely check but not set the Account balance?

    0 讨论(0)
  • 2021-02-01 17:50

    Why has this one fizzled out?

    I find having an interface for a domain object, as Charlie Martin said, allows me to choose my implementation.

    A fundamental example is the identifier (object.Id) for an object, this will be different depending on where you store that object and the responsibility for creating it may or may not rest in the implementation of the data later. In SQL Server you might go for an autonumber, but in Azure table storage you might go for a Guid, but you don't want to have to change the business logic of you app because you change where you store your data.

    I may or may not choose to have my domain object persisted, or even use it in the presentation layer - it depends on the scope of my app which is best. But adding a set of common domain interfaces in a common layer allows me to write services against them and reuse them again and again.

    We would go over the same argument about what should be an address if we hadn't got IAddress, new programmers would be rewriting stuff for credit cards if it weren't for ICreditCard.

    The anti-pattern label is a bad use of language, it's an over simplification for describing the worth of solutions to complex and varied tasks.

    There is a place for most patterns even the maligned Singleton, which means its not an "anti-pattern", at least as far as the term suggests.

    0 讨论(0)
提交回复
热议问题