Frage

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?

War es hilfreich?

Lösung

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)

Andere Tipps

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.

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]

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.

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.

Lizenziert unter: CC-BY-SA mit Zuschreibung
scroll top