20

I'm reading "Dependency Injection in .NET" by Mark Seemann (it's fantastic, and must have) and the author often uses the word "seam". But I can't understand what it means. Here is an example of using this word:

Chapter 7 explains how to compose objects in various concrete frameworks such as ASP.NET MVC, WPF, WCF, and so on. Not all frameworks support DI equally well, and even among those that do, the ways they do it differ a lot. For each framework, it can be difficult to identify the SEAM that enables DI in that framework. However, once that SEAM is found, you have a solution for all applica- tions that use this particular framework. In chapter 7, I have done this work for the most common .NET application frameworks. Think of it as a catalog of framework SEAMS.

I would be gratefull for helping me with understanding this word.

entpnerd
  • 241
  • 3
  • 9
user278618
  • 565
  • 1
  • 5
  • 9
  • 4
    There are hints to what the word means on the [author's blog](http://blog.ploeh.dk/2011/06/07/SOLIDCodeIsnt.aspx). And since he's a [member here](http://programmers.stackexchange.com/users/19115/mark-seemann): @MarkSeemann this one is for you :) – yannis Jan 30 '12 at 20:19

2 Answers2

28

I think the term originates from Michael Feathers Working Effectively with Legacy Code in which he explains a seam in software as a place where two parts of the software meet and where something else can be injected. The analogy is a seam in clothing: The place where two parts are stitched together. The piece on each side only touches the other right at the seam. Back to software: If you identify the seam you have identified the place where there is a well defined interface. That is what you can leverage in DI, since such an interface allows you to replace implementation without the rest of the software being able to tell (without cheating, anyway).

Matthieu
  • 4,559
  • 2
  • 35
  • 37
Christian Horsdal
  • 1,499
  • 10
  • 10
14

Building on Christian's answer, to the best of my knowledge, the term seam does originate from Feathers' book, Working Effectively with Legacy Code. The definition is on page 31:

A seam is a place where you can alter behavior in your program without editing in that place.

To give examples of what a seam is and what it isn't, consider the following Java code:

public class MyClass {
  private final Foo foo;

  public MyClass(Foo foo) {
    this.foo = foo;
  }

  public void doBunchOfStuff(BarFactory barFactory) {
    // foo.doStuff() is a seam because I can inject a mock instance of Foo
    this.foo.doStuff();

    // barFactory.makeBars() is a seam because I can replace the default
    // BarFactory instance with something else during testing
    List<Bar> bars = barFactory.makeBars();
    for(Bar bar : bars) {
      // bar.cut() is also a seam because if I can mock out BarFactory, then
      // I can get the mocked BarFactory to return mocked Bars.
      bar.cut();
    }

    // MyStaticClass.staticCall() is not a seam because I cannot replace
    // staticCall() with different behavior without calling a class besides
    // MyStaticClass, or changing the code in MyStaticClass.
    MyStaticClass.staticCall();

    // This is not a seam either because I can't change the behavior of what
    // happens when instanceCall() occurs with out changing this method or
    // the code in instanceCall().
    (new MyInstanceClass()).instanceCall();
  }
}

The seams exemplified above would be seams unless:

  1. The class being injected is final.
  2. The method being called is final.

Basically, seams facilitate unit testing. I can't write a unit test for MyClass because of the calls to MyStaticClass.staticCall() and (new MyInstanceClass()).instanceCall(). Any unit test for MyClass's doBunchOfStuff() method would have to test MyStaticClass.staticCall() and (new MyInstanceClass()).instanceCall() and all of their dependencies that get called. Conversely, by using non-final classes with non-final methods (or better yet - interfaces), the injected instances of Foo and BarFactory make unit tests for MyClass possible to write by facilitating mocking.

entpnerd
  • 241
  • 3
  • 9