As a result, beginning programmers start their careers thinking that good code is filled with inheritance hierarchies and layers of indirection, and they think that getting better as a coder means getting better at adding more and more of those protective layers to ensure their code is prepared for every possible eventuality. Which is insane. It's like sending your kid to school dressed in a raincoat and rubber boots every day when you live in Arizona, instead of looking at the weather forecast (or just guessing) like the other parents. One day every year you'll be right and they'll be wrong, and if can convince people that makes you smart, you have a promising career as an enterprise Java consultant.
I think it all goes back to the overstated fear of change. I think the fear of adapting straightforward code to new requirements must come from another time when code was harder to change, because nothing in my professional experience supports it. According to this fear, the only way to survive is to guess correctly at how your code will need to evolve in the future and preemptively design for it. All of the inheritance hierarchies and layers of indirection must already be in place before you discover that you need them, or else something very bad happens. Therefore the implementation costs and the overhead in maintenance and confusion are gladly paid. How does this make sense? I've never suffered greatly from code that was too simple, too straightforward, not built out enough. I've suffered many times from code built out in a slightly wrong direction that was the best possible guess at the time. The feeling of safety and prudence that people get from preemptively complexifying their code seems like delusion to me.
The cons I see are there are now two places where documentation needs to be kept in sync.
And reduced readability because of abstraction. For instances if I'm going through the mail chimp code base it's easier to understand how a mailcampaign interacts with the surrounding code base than something like iclickable. If I see a mailcampaign in code I instantly know what domain object it's represents, and have some idea a out what logic to expect in it. Iclickable I have no idea.
Im anxiously awaiting a thoughtful discussion of interfaces.
I would say that the subset of "good in and of itself" from interfaces -- ignoring those other benefits like multiple-implementations and extendable/reusable/mockable code -- usually relate to separating the mental task of defining what you wanted to exist versus what you were able to achieve so far.
In some ways an interface is similar to test-driven development, since it allows developers to create a scaffold of requirements and goals (interface methods and comments) before getting bogged down in the implementation details, and iteratively cycle between those two viewpoints.
In contrast, classes without an interface are at a higher risk for following a sort of least-effort evolution, such that someday a developer answers: "Why does it work that way? I dunno, that's just how we got it working."
> The cons I see are there are now two places where documentation needs to be kept in sync.
Ideally the in-file documentation is different though: The interface says "this method will take an X and create a new Y based on it", whereas the implementation communicates "I fulfill the interface's requirements by <stuff that makes me interesting and unique>."
Interfaces have many good uses in many situations, but by themselves, with one implementation, is not one of them. (note by themselves. Unit testing, multiple implementations, and so on are reasons beyond in and of themselves). And you can very well do the mental separation by coding without adding an unnecessary interface (unless it has other uses of course).
Combine zealotry with the internet, blog-posts about how you "should always" and you can have yourself a cargo-cult programming-practice of your own choosing.
Having 1:1 mapping between an interface and a concrete class seems kind of pointless to me.
The author suggests using virtual, but if your intent is not to allow child classes to override the implementation, this is certainly not "pure".
Visual Studio & ReSharper makes the code generation (Refactor > Extract Interface) and maintenance upkeep trivial anyway.
Plain Old Class Object means no special inheritance chains or attributes, just a "plain old" class.
By way of example: this contrasts with old Entity Framework or other ORMs that made you inherit from a certain kind of class, breaking the objects original intent, and hurting you when it came time to port to another framework, or serialize, or maintain your own class hierarchy.
Even what DDDers would call a Value Object could and should still have relevant business logic attached to them. For test-ability and portability you don't want your classes married to any particular framework, but your objects are still responsible for hiding relevant information.
It is often used by test code, for example, that wants to use a fake version of something the library provides.
Which, by the way, is generally preferable to mocking.
It's pretty annoying TBQH.
[0] https://www.typemock.com/isolator
[1] http://www.telerik.com/products/mocking.aspx
[2] https://github.com/Fody/Ionad
[3] http://mattwarren.org/2014/08/14/how-to-mock-sealed-classes-...
In practice though I like to think that the re-use of my objects and class hierarchies is a critical part of their design. Just about anything I'm gonna have to override to make a simple mock will also be an issue for other implementers. So why not use the opportunity to abstract and refine the objects internal logic to make mocking the relevant functionality cleaner and more obvious? Create an internal "OnProcessComplete" method which can be overridden easily instead of mocking the whole "Process" command.
Over-mocking is a major code smell and productivity thief. I find that having to manually set it up keeps me honest about cost/benefit, while also looking at an important design aspect that otherwise could be ignored.