One thing that really helps development is code reuse. If we can buy a library
that solves some problem for us (and figure out how to use it), we can often cut
substantial time off a project. The only problem is that it is very easy to become
over-reliant on a library. If you use it promiscuously throughout your code, you
are pretty much stuck with it. Some teams I’ve worked with have been severely
burned by their over-reliance on libraries. In one case, a vendor raised royalties
so high that the application couldn’t make money in the marketplace. The team
couldn’t easily use another vendor’s library because separating out the calls to
the original vendor’s code would’ve amounted to a rewrite.
At the time of this writing, much of the development world is polarized
around Java and .NET. Both Microsoft and Sun have tried to make their platforms as broad as possible, creating many libraries so that people will continue
to use their products. In a way, it is a win for many projects, but you can still
over rely on particular libraries. Every hard-coded use of a library class is a
place where you could have had a seam. Some libraries are very good about
defining interfaces for all of their concrete classes. In other cases, classes are
concrete and declared final or sealed, or they have key functions that are nonvirtual, leaving no way to fake them out under test. In these cases, sometimes
the best thing you can do is write a thin wrapper over the classes that you need
to separate out. Make sure that you write your vendor and give them grief
about making your development work difficult.
Avoid littering direct calls to library classes in your code. You might think that you’ll
never change them, but that can become a self-fulfilling prophecy.
Library designers who use language features to enforce design constraints are often
making a mistake. They forget that good code runs in production and test environments. Constraints for the former can make working in the latter nearly impossible.
From the Library of Brian Watterson198 DEPENDENCIES ON LIBRARIES ARE KILLING ME
Are Killing Me
A fundamental tension exists between language features that try to enforce
good design and things you have to do to test code. One of the most prevalent
tensions is the once dilemma. If library assumes that there is going to be only
one instance of a class in a system, it can make the use of fake objects difficult.
There might not be any way to use Introduce Static Setter (372) or many of the
other dependency-breaking techniques that you can use to deal with singletons.
Sometimes wrapping the singleton is the only choice available to you.
A related problem is the restricted override dilemma. In some OO languages,
all methods are virtual. In others, they are virtual by default, but they can be
made non-virtual. In others, you have to explicitly make them virtual. From a
design perspective, there is some value in making some methods non-virtual. At
times, various people in the industry have recommended making as many methods non-virtual as possible. Sometimes the reasons they give are good, but it is
hard to deny that this practice makes it hard to introduce sensing and separation in code bases. It is also hard to deny that people often write very good code
in Smalltalk, where that practice is impossible; in Java, where people generally
don’t do it; and even in C++, where plenty of code has been written without it.
You can do very well just pretending that a public method is non-virtual in production code. If you do that,