Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Is it common to have an interface on everything? I would have thought you'd just have interfaces where you can have multiple parts fitting the same socket. That's how I do it, and I thought that was common and common sense?


I feel like I see this all the time at work. Honestly only a couple years into working as a software engineer I'm burnt out on people way over engineering stuff, future proofing and seemingly having a need to make as many comments as possible on CRs to improve their craft/defend from the horrors of 'bad code'.


I'm with you. I think partly it comes from education — Java programming books (I can't speak to C#) concentrate on teaching ways to deal with complexity and evolution, but they don't teach you that it's okay to handle simple situations simply. There's an exaggerated fear of what happens if you need to change code that isn't already future-proofed. It's an unbalanced approach. There's no YAGNI, no appraisal of the cost in obfuscation and mental overhead, no discussion of how to accommodate change in code without preemptively engineering for it. It's just, here are all the horrible unexpected things that will happen to your code, and you should have all this design pattern apparatus in place to anticipate every possible change.

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.


Another use case where you might just have one implementor is to break circular dependency chains. You can have your module foo that depends on some core, and a module foo-api that depends only on what is needed to represent your interfaces, and now a module bar can depend on the core and foo-api and make use of services provided by foo. Similarly foo could depend on bar-api and make use of bar services, no issues now...


And testing as well. But I think the main idea is the contrast of thinking as interfaces as a asset or a cost. I think of interfaces as a cost you pay to get something better, like testability or circular dependency removal, back. But many developers and tech leads see interfaces as a good in and of itself, an asset that that pays dividends over the course of the project.


I generally fall into the latter group, but if the documentation on the interface says "See FooImpl for more details" then that's surely a red flag :p


I'm super interested in hearing what you think are the advantages to that approach.

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'm not sure I understand your example; Does MailCampaign implement IClickable? Surely all the places you're seeing IClickable are places where the important activity somehow involves generalized clicking?

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>."


Perhaps you could contribute to this open source project? https://github.com/EnterpriseQualityCoding/FizzBuzzEnterpris...


I had hoped for constructive or thoughtful replies, but yours is just trolling.


True, that was not very constructive, apologies. However, I was comparing your criticism of the previous posters slight exaggeration of the name IClickable with the beauty that is FizzBuzzEnterprise.

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).


Indeed, this is the main example of the Dependency Inversion Principle.


> Is it common to have an interface on everything? I would have thought you'd just have interfaces where you can have multiple parts fitting the same socket. That's how I do it, and I thought that was common and common sense?

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.


I sometimes have multiple interfaces and one common implementor, when the same object needs to be passed to different places that need to know about different aspects of its functionality. I.e. one part fitting multiple sockets.

Having 1:1 mapping between an interface and a concrete class seems kind of pointless to me.


I've known people who took the "interfaces are good" to the cargo-cult where they would have a POCO and make an interface for it with getters and setters. No functionality and basically only one possible implementation because it's assumed to be backed by a POCO everywhere. But they "coded to the interface" so it's all good.


In C#, it's just about the only way to unit test aside from making abstract/virtual or using something like TypeMock (paid).

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.


You don't need to mock a POCO at all, it's just a collection of values with no functionality. I'm not part of the anti-mocking brigade, but for POCO's you should always just use the real thing.


POCOs and functionality are orthogonal to one another.

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.


Unless you use a pattern like SimpleMock! http://deliberate-software.com/simplemock-unit-test-mocking/


If your code is a library that will be used by other people, using interfaces allows them to provide their own part for any socket even if your library only has one implementation.

It is often used by test code, for example, that wants to use a fake version of something the library provides.


> 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 is something that people people who hear about unit testing and discover dependency injection often do. Much test advice is around testing small units of code, and with dependency injection you inject a mocked interface which must be good, right?


I hardly think you can blame inexperience when people have been treating "program to an interface, not an implementation" as axiomatic for years.


I can blame inexperience for people not understanding the interface in the sentence is nothing to do with the interface keyword in their programming language.


Unfortunately in C# you can only Mock Abstract/Virtual methods and Interfaces.

It's pretty annoying TBQH.


I agree fully from a purists PoV: pure OO means I get to redefine anything I want when I inherit, a la Smalltalk.

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.


TypeMock Isolator[0] and JustMock[1] can mock nonvirtual methods and static methods. Fody Ionad[2] is a free tool that can replace static methods. The reason that most mocking framework don't support this is that the implementation is complex[3].

[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-...


I can't see anything changing until the OSS frameworks have similar support. For that matter, MS should take the lead for something that could provide across the board performance improvements on their ecosystem. They don't seem to care about tooling to improve their own platforms.


I don't know C#, but I know in C++ I have been burned because I mocked a real class - but I didn't override some function and so my test ended up using a mix between the real class and the mocks leading to code that wasn't testing what I wanted it to. Often the tests pass, but there is a lurking bug.


SimpleMock is a pattern for unit test mocking that uses no interfaces or libraries! It's simple and works very well. http://deliberate-software.com/simplemock-unit-test-mocking/


Sometimes "where you can have multiple parts fitting the same socket" isn't quite as you initially imagined it.


It is common sense, but it's not as common as you think. I've had multiple tech leads ask me to wrap a class in an interface to "abstract" it.


It is not hard, in this field, to find people who take it as axiomatic that if X is a good idea, then only X all the time is the only sensible way to go.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: