14

I've been delving into more "organized" programming recently and I've been learning that I should be programming to an interface, not an implementation. With that in mind, would it be better to "sketch" out a project in interfaces before writing the implementation for it where possible?

And if this is the case, in the case of using 3rd party libraries (ie Lidgren), should I be wrapping those in interfaces as well and resolve them through IOC containers, or is it OK to expose them to the interfaces?

  • In my personal experience - it's good to design the architecture first - the responsibility of each class. You don't have to write it down, just think about it or sketch it on a paper. Then it's about personal preference but I recommend to write doc comments first for every method you start to implement. Writing docs really makes you to think about the functionality before you start writing code. – Sulthan Dec 6 '13 at 10:41
  • Yes, and program to the interfaces (or abstract classes for that matter) before you implement them. It helps getting the message flow from client to server and vice versa "right" before being bogged down (and invested in) implementations. Very good slide show on the matter: How to Design a Good API & Why it Matters – Marjan Venema Dec 6 '13 at 11:08
8

Unfortunately, you'll find this often boils down to personal preference.

What you've described so far, though, seems good. In fact, if you wanted to (and I recommend it) you could use the following approach:

  1. Write your application skeleton as Interfaces, abstract classes (stubbed), and classes (also stubbed)
  2. Write your tests against those interfaces and stubs (they will fail for now)
  3. Write your implementations (your tests will start passing as you finish your implementation)

You're focusing on trying to write more "organized" code. Following TDD will help you with this.

Some extra points:

  • IoC containers are convenient. Use them and DI as much as you can.
  • Do wrap 3rd party libraries. This will loosen the coupling between your code (code you control) and 3rd party code (code you don't control)
  • 1
    This was what I had originally thought but I was told it would violate the YAGNI principle. The problem that I find with a lot of my projects that never get finished is that they rapidly become un-maintainable with the amount of blob code I've written, because I don't organize it properly or plan out my plan of attack. – Dan Pantry Dec 6 '13 at 9:58
  • which part would violate YAGNI? – MetaFight Dec 6 '13 at 9:58
  • Wrapping 3rd party libraries. – Dan Pantry Dec 6 '13 at 9:59
  • 2
    I guess it boils down to: What are the odds of the 3rd party library changing? If there is a 0% chance of this, then sure YAGNI. But, that's rarely the case. Also, wrapping your 3rd party libs may make your other code more easy to unit test (if, for example, you couldn't mock out the 3rd party library) – MetaFight Dec 6 '13 at 10:01
  • 1
    @DanPantry: Wrapping third party libraries isn't a YAGNI violation, but a much needed protection against "third party library infestation of your own code". It is not just about being able to swap out a library, but as MetaFight also says a defense against changes in newer versions of the library which would otherwise require changes throughout your own code. By wrapping the library (and especially its specific types: classes, enums, structs etc), you insulate your own code and have a single point to change when the library changes (for whatever reason). – Marjan Venema Dec 6 '13 at 11:13
13

Yes, you should code against interfaces rather than known implementations, and yes, you should construct interfaces first rather than having them emerge from your own code.

The reasons for both recommendations are largely the same: computer programming is largely about human factors. Many find this surprising, but consider: there are a near-infinite number of different ways to solve the same computing problem that work equally well. Nearly all of them are completely impossible to make sense of for anyone who didn't write them (or in fact to the author a short time later).

It follows that good software engineering is largely about how to achieve the desired effect (correct computation with reasonable efficiency) in a way that allows the source code to be worked with later on. Interfaces and APIs are a crucial part of that discipline: they allow you to think about a problem at one level of description at a time. This is far easier than thinking about business consistency rules and about linked list implementations at the same time, and therefore imposing such a separation of concerns forcibly is better than allowing the client programmer to use your code any way he likes.

This is hard to believe for many cowboy programmers, who are convinced that they understand everything they write, are much better than average thinkers, and can handle all the complexity that gives "lesser" programmers trouble. Not being aware of one's own cognitive limits is an extremely common phenomenon - this is why best practices in code organization are so hugely important (and so often ignored).

To repeat, interfaces and API barriers are largely good, even when you only cooperate with yourself. As for external libraries, if they bring a well-thought-out API with them, I see no problem in using it as it is as long as you don't anticipate having to swap out that library for another one. Otherwise, a wrapper or anti-corruption layer can be a very good idea.

  • I like your point about SE being largely about achieving the desired effect in a way that allows the source code to be worked with later. I wish I had been able to phrase it that well at my last job, where I was always fighting for clean code! – MetaFight Dec 6 '13 at 10:06
  • Is there a naming convention for APIs that are just interfaces that I will end up using all over the place? Like, if I am doing a command pattern, do I call it "commandables"? – Snoop Apr 14 '16 at 13:38
  • @StevieV There are various, e.g. IBlah implemented by Blah, or Blah implemented by BlahImpl. I dislike both, and tend to use Blah implemented by OralBlah, WrittenBlah or ASLBlah. But as usual, it's more important to conform to your existing code base and expectations than to any general standard. – Kilian Foth Apr 14 '16 at 14:21
4

Rather than slavishly just programming to interfaces, why not look into Test Driven Development/Design (TDD)?

Many people think of TDD as a testing practice, but actually it's a design approach where you let tests expose how your code will be used via tests (initially via unit tests, but can also be via integration tests).

Programming to interfaces is an important weapon in your toolset, but like most things, it's not always the appropriate solution/technique/practice, as it's not always needed. You should program to interfaces where you need to.

Using TDD will force you to explore where such interfaces are important and where it, frankly, doesn't matter. And at the end of it you should have a pretty good set of unit tests across your code base.

As for using 3rd party libraries I would highly recommend wrapping them in your own abstractions where appropriate; and not let clients of your API "know" about them.

Good Luck!

[edit: saw megaflight's answer - completely agree]

  • 2
    TDD implicitly has you think in terms of interface rather than implmenetation, although it may not be a formal "interface" declaration. – DougM Dec 6 '13 at 16:36
  • 1
    This is a great answer. +1 for suggesting TDD, which I think is the solution to the OP's real problem of where to start when working on a new project, and I'd +1 again if I could for "Using TDD will force you to explore where such interfaces are important and where it, frankly, doesn't matter." – Benjamin Hodgson Dec 7 '13 at 0:10
2

I think it is overkill. If the user of your API does not need to be forced to implement/use something a certain way then I would leave it out. Interfaces are contracts, if I don't need it then why give me one?

I think people overuse interfaces. You are adding a layer of complexity that is not needed in most cases.

  • I think, people under-use interfaces. If you want to create reusable pieces, the interface is not only a "nice to have" addition, but the main thing to take care of. Besides the actual implementation of course. – JensG Dec 6 '13 at 18:39
1

Programming against a contract is almost always a good idea. That contract need not be an interface, it can be fulfilled by a class instead. In my opinion, interfaces have become somewhat overused along with DI due to unit testing concerns and mocking frameworks.

I personally prefer to only bring in interfaces when I very likely could have or do have more than 1 implementation of a contract. Interfaces are great for repositories where I wish to abstract away data access, but probably less so for my standard business logic which is likely to be relatively inflexible.

Now not having an interface can cause problems with unit testing, especially for purists. But I'm interested in mocking the external dependencies of my programs, not its internal dependencies. I want my tests to perform validation of the code, not echo the code structure.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.