Causes of Decay

August 29, 2008

In order to flesh out another aspect of the presentation I gave on “Remodularization”, I’ll be writing a series of posts discussing the reasons that the quality of software “decays” over its lifetime. This will by no means attempt to be a definitive guide on the subject, since I’m not an academic, but just some reflections on my personal experience and the experience of others in the field.

To me, one of the most interesting aspects of this discussion is the taken-as-fact assumption that software naturally decays over time. This is essentially driven by the second law of thermodynamics: entropy increases over time. It seems a stretch to apply this to the evolution of a code base, but I’m sure we have all felt this to be true in one way or another.

Inevitable Decay

Inevitable Decay

Scott Bain in his book “Emergent Design” makes the argument that this doesn’t have to be the case. He argues that by using design practices that permit entension in the future while minimizing the number of places you’ll have to change the code (the Open-Closed principle), a developer is able to add functionality without adding significantly to the complexity of the application. He says that, like doctors, developers should take something akin to the Hippocratic Oath (“First, do no harm”), committing themselves to always improving the code even as they add new functionality. He also proposes some simple design principles that can make this an almost natural occurrence.

"Emergent Design", Scott Bain, with slight modifications)

Rejecting Decay

He’s not alone in this assertion. Folks from the agile camps often talk about “technical debt” and the need to be courageous to refactor your code as you work. This philosophy recognizes that there is a cost associated with maintaining the quality of the software in the face of changes, but it reflects Bain’s ideal that developers should fight the good fight constantly, rather than leave it for later (when a complete rewrite may be necessary).

Personally, I have to agree that code decay is inevitable. As Neal Ford points out in his axiom “Simplify essential complexity; diminish accidental complexity”, there is such a thing as essential complexity. Even as you work to continuously improve the overall quality of the code, you will be adding essential complexity to the application. I don’t mean to imply that Bain would disagree with this; he is referring to a measure of quality, as opposed to the overall complexity of a growing system. Perhaps there is such a thing as a “maximum quality”, when all complexity is essential.

Whether or not you and your team have chosen to be keyboard medics, the fact is that software decay happens. In the following weeks, I’ll discuss some of the reasons that software complexity increases over time. Hopefully this discussion will provide you with the medicine you need to fight this cancer.


Legacy Patterns Decision Tree

August 27, 2008

Way back when I first read the Michael Feathers book on “Working Effectively with Legacy Code”, I decided to write up a quick description of the patterns in the book for my coworkers to look up whenever they need them (basically, when trying to write unit tests for big, monolithic “legacy” classes).

These patterns are extremely intuitive once you’ve gone over them a few times. They’re really just obvious techniques for working around some constraints with as little risk and impact as possible. However, to reduce the learning curve, I created the decision tree below. I actually don’t think it’s very useful in practice, but creating it was a great way for ME to fully understand these patterns and their relationships. Now, I pass it on to you. My hope is that any of you developers out there may learn something from having a look at it. And, who knows, maybe there’s some insight here that can be used in my quixotic quest for the Legaciness metric.

Legacy Code Patterns Decision Tree

Legacy Code Patterns Decision Tree

Note that some of the leaf nodes recommend the use of mock objects, which are not part of the legacy code patterns themselves. I recommend the use of EasyMock, which is the library I’m using, but you can use whatever you prefer. If you can use fake objects, I find that to be generally easier than, and thus preferable to using mock objects.


97 Things #66: Get a second opinion

August 27, 2008

The other day, I wrote up my fourth axiom to get accepted into the “97 Things” book: “If there is only one solution, get a second opinion”. In my opinion, it’s not the best of the four, but it might be worth a quick read (as are all the others on the site!).


Enterprise 2.0

August 27, 2008

It looks like I’ve been a little behind the curve on this “Enterprise 2.0″ thing. I thought the term was just something Josh Street had made up as a whimsical way to tie his presentation together. It turns out it’s a term that is not only tossed about in tech discussions – there’s already a Wikipedia entry, a “movement”, and people grumbling about how everyone’s missing the whole point.

Well, I promise from now on to be more on top of things (“Be at the forefront”, after all). I finally got my “unread RSS entries” count down from 2000+ to a mere 50 or so.

I am glad to see that I wasn’t “missing the point” on this, since we have been using a lot of these technologies for some time. My “Architecture 2.0″ series will continue (as my adaptation of Enterprise 2.0 to the practice of software architecture), and so will my efforts to find new ways to improve our collaboration and efficiency via tools. Stay tuned!


Documenting Architecture Decisions

August 25, 2008

Record Your Rationale

I just posted another axiom to the “97 Things” project called “Record your rationale”. The basic idea is that you should keep a record of why architectural decisions were made so that when someone asks, or when you’re thinking of changing your mind, it’s all there to remind you. This is a common problem, especially for architects who inherit someone else’s system: why this heck did they do THAT? Without a record of the rationale, inobvious solutions can seem like pure lunacy (or stupidity). I have actually caught myself voicing that sort of negative opinion out loud, right in the company of the very person that had done the implementation. Oops.

But I digress. I don’t want to spend this post rehashing what I wrote in the other site (if you’re interested, by all means go read it). I’d like to discuss how we’re recording our rationale at Sakonnet. First, let me post here a part of the original axiom that I cut out to reduce the number of details:

More formal approaches to this type of documentation involve using a standard template that includes the following information:

  • The name (or brief description) of the decision
  • A brief summary of the issue that the solution attempts to resolve
  • A description of the final solution that was selected
  • Factors that influenced the final decision (functional and non-functional requirements, technical, legal and other constraints, political factors (e.g. partnerships with software vendors), or just about anything else that was considered in the decision making process)
  • A prioritized list of quality attributes (is performance, security, cost or maintainability more important in this case?)
  • The final rationale behind the decision
  • A description of alternate solutions that were considered, and why they were rejected

Architecture Decisions

At Sakonnet, we are using a template, but not quite so formal as the one presented above. This is partly because I started out simple just to try out the concept, and partly because I didn’t want to create roadblocks or intimidate people from creating and using them.

I created something called “Architecture Decisions” (very original, right?), which consist basically of a summary (a title, often framed as a question: “How can we improve the monitorability of our message-driven processes?”), a more in-depth description of the problem (often accompanied by some alternatives that are being considered), and a “resolution” that gets filled out when the decision has been made and the issue is being closed. There are also fields for explaining “impacts on Quality of Service” as a consequence of the decision made. This is divided into four main categories (Performance, Scalability, Reliability, Maintainability), plus an “Others” field for anything else. These fields are all plain text.

Architecture 2.0

By now you’re probably picturing a stale templated Word document two pages long or so that gets lost in the file system, never gets properly filled out, and no one ever sees it or can ever find it again, right? This is where it gets interesting. Architecture Decisions are a key component of what I’m (unfortunately) calling (in this blog only) “Architecture 2.0″: an approach to the architecture process which leverages web 2.0-style application features and community to improve communication, participation and agility (especially with regards to documentation) (note that this isn’t my idea – I’m just borrowing it, including more or less the name, from a presentation called “Enterprise 2.0″ recently given by Josh Street).

I created Architecture Decisions (ADs) as a new type of element in the web-based process tracking software that we’re using at Sakonnet. Think of it as a type of Jira or Bugzilla, only more generic and flexible (and less oriented towards software development…). In this system, I was able to define all the fields for these decisions, and more.

Lifecycle

Thanks to the web-based medium, I was able to define both a workflow and a lifecycle for these decisions. The workflow entails the following steps (statuses):

  1. Not started – the decision was created, but isn’t being actively looked at yet
  2. Being investigated - someone (or some group) is looking into the issues surrounding the decision. There is an “assigned to” field for ADs so that everyone can see who specifically is responsible for seeing it through to the end. There is also a “due date” for tracking and reminders.
  3. Decision made - the final solution has been chosen. At this point, the owner needs to fill out the Resolution and the Impacts on Quality of Service fields. People also get notified (more on this below).
  4. Work scheduled - you’ve made the decision, but you’re not done yet! The solution still needs to get implemented. So the AD only reaches this status when the owner has created any specs or tasks required to actually make the decision happen.
  5. Implemented – if the decision has been carried out and implemented in the system, you are now done. But the decision hasn’t reached the end of its lifecycle…
  • Others:
  • Cancelled - if the decision was created by mistake, or someone decided it wasn’t worth going through the motions
  • Deprecated - NOW the decision has really died. More on this below.

The life of an AD is something like the life of a bill (queue Schoolhouse Rock), but without the politics. Someone has a brilliant idea (or a problem), and they write it up in the web site. Then it stays open until someone finally gets around to making up their mind about it. Work gets scheduled, and if it’s important it gets assigned to someone and completed (otherwise, it may linger forever in the limbo known as the “pipeline”).

However, at any point after the decision is made, it may get replaced by a new decision. This may be due to a change in the context (performance suddenly got priority over maintainability), or because new information came to light (something like reopening a case due to “new evidence”). For example, if a decision was made because the middleware doesn’t provide a feature out-of-the-box, you may have to rethink things if a new version of the middleware is released. When the decision changes, a new AD is opened, and the old one is marked as “Deprecated”, meaning it’s no longer valid. A link should be provided to the new decision, but for now this isn’t automatic.

I’ve found from practice that there are a lot of times you want to make just a small change that doesn’t affect the spirit of the decision (e.g. in the solution, you mention an XML tag you want to call <foo>, but you later decide it should be called <Foo> – presumably that change isn’t going to make a big difference). We could just go and alter the text, but people might not notice the change, and it might get overlooked. In this case, I want to have a workflow called “Amendment”, where the AD can be altered slightly, and the change recorded in the history. We haven’t implemented that yet, but I’m working on it.

Collaboration

Documentation of rationale is an important historical artifact. However, for Architecture Decisions, I wanted more than this. Actually, the idea came about for two reasons:

  1. I realized that developers were placing technical discussions in the forum for the specs they were working on
  2. I realized that developers didn’t always know how or when to raise technical issues to the architects

So I created the ADs. They have a number of features which resolve these problems, and more. Like the specs, bugs, and so on, there is a discussion forum for each one. This ends up being type of “living documentation” of the discussion. The back and forth between people ends up looking something like the Federalist Papers (ok, I exaggerate), where you can actually see the proposals and reasoning behind them.

ADs can be associated with “deliverables” (something like a project, or a group of specs), specs and bugs. In fact, they can be CREATED from within any of these. This means that a developer can be given a spec, have questions about the best way to implement it, and with the hit of the button, they can ask the architects. Remember, the “summary” field is often phrased as a question: “Is it ok to use messaging to generate the Foo Report?”

Equally important, the ADs are hooked up to send email notifications at the right times:

  1. Whenever an AD is created, people are notified. This used to be just the architects, but since I want more contribution from the developers (“Empower developers!”), I recently added all developers to the mailing list. So far, no ones complained about the spam.
  2. Whever an AD is marked “Decision Made”, all develoepers receive the notification. This is a way to automatically communicate important decisions regarding the architecture. Since there are 35 developers on the team, it can be hard to make sure everyone got the message.
  3. Anyone working on the related item will get notified whenever someone posts a comment to the forum. Also, anyone that contributes an opinion of their own gets notified.

So far, all of this is working out remarkably well!

Finding Decisions

Another concern I mentioned in my “axiom” is that this information should all be searchable. If you have to spend more than 5 minutes looking for a past decision, you probably won’t do it. Fortunately, for ADs, all their text is searchable via the web interface!

I also went to the effort to provide some other methods to facilitate their use. First, I added the following fields:

  • Category - this is just a free-form plain text field where the architect can fill in a quick description of the “component” or piece of the system to which the decision relates. This was also my way to track exactly what kinds of components this would entail. We’ve got about 250 ADs in the system now, and a set of de facto categorizations have naturally evolved.
  • Functional component – it can be important to track exactly which sets of functionality are being affected by a decision (is this about credit notes replication? Trade saving?). If it affects everything (our Exception Handling Framework), this field is left blank. This field is a drop-down box of pre-defined options.
  • Non-functional component – this is another drop-down of options. It was nearly impossible to pick out a set of non-functional components and stick with it. I started with the “Categories” that people had created on their own. I tossed in some formal components, layers and other elements I’d defined in our official architecture documentation, and so on. The fact is that decisions can affect the software at just about any granularity, hierarchical or not. I’ll write up a separate post some time about categorization of ADs, because it’s a toughy.

So, you can search and sort based on any of the above fields. This can be really useful to answer questions like, “what were all the decisions we made regarding our JMS messaging framework?”

Our web application also lets you define and store reports for repeated use. So I have created a number of views (including things like “which decisions are still open, but due in the next week?”), but there is one that I find very fascinating: The Reigning Decisions Report. This report will show you all the decisions that are in the status “Decision Made”, “Work Scheduled” or “Implemented”. In other words, all the decisions that a developer needs to know at any time about the current system. What’s really cool about this one is that if a decision ever gets “deprecated”, it drops out of the view. If its replacement decision gets made, it shows up instead. This report is ordered and grouped by the Category field.

Parting Thoughts

I must admit that I had delusions about everyone being able to look at my reports and see the WHOLE ARCHITECTURE with a glance. Its one of those things that sounds fantastic in theory, but will never happen in practice. Not every decision made is recorded as an AD, even when they should be. I do my best to keep my eye out for changes that should be recorded this way, and people are generally good about doing so themselves, but sometimes things slip through the cracks. Also, the system was already 8 years old when we started doing this. It would be absurd to think that there is value in going back and documenting every old decision in this system.

Also, there are times when creating an AD for every decision made is too much of a burden to make sense. For big projects, there is usually some up-front design and analysis, during which a whole set of features may be discusssed. It would be impractical to separate each and every “decision” into its own AD, but I still want to record the rationale behind the design. For these cases, we instead create a brief “design document” that gets saved to our version control, and create a single AD which summarizes the design, and links to the actual document. In this way, history is preserved, the decisions are somewhat searchable, and we don’t waste a lot of time unnecessarily.

Architecture Decisions were simple to create, and are a fantastically easy way to “record our rationale”. More importantly, they enhance our ability to collaborate and to communicate architectural changes, standards and principles that would otherwise be discussed (and remain) behind closed doors. They turn out to be a great way to get developers (those that are interested) involved in the design process before these decisions are force-fed to them. In my opinion, they are a critical part of a successful “Archtecture 2.0″ environment, and from now on they’re something I’ll never do without.


97 Things Every Software Architect Should Know

August 22, 2008

It looks like the Architect Commandments have shown their face again – and this time, they’re in good company! I caught wind today of a really interesting project that is the brainchild of Richard Monson-Haefel called “97 Things Every Software Architect Should Know”. He’s gathering a list of the top 97 “axioms” that software architects should take to heart. So far, he’s only picked out about half that, and he’s asking for more. I had a look at the axioms, and realized immediately that the Architect Commandments would be right at home on that list. So far, I’ve registered two of my favorites (“Challenge assumptions” and “Empower developers”), and they were accepted for his book!

Now’s you’re chance to contribute, too. Click on the link above, and get involved, or just check out what people have contributed so far.


Dave Packard’s take on the Architecture Commandments

August 18, 2008

I just ran across this classic set of rules to management by Dave Packard, of HP fame: Dave Packard’s 11 Simple Rules. Succinct and well-written, I think they relate well to two of my Architect Commandments: “Empower developers” and “Show the way”. I guess the underlying message is that, no matter who you are, you are part of a team. Negativity hurts you as much as it hurts the other person. To grow tomatoes, you need to give them water and sunlight. Or something like that.


Legacy Code Bad Practices

August 15, 2008

In response to a recent comment from Kalinowski regarding my idea for a “Legaciness” metric, I have decided try and boil down Michael Feathers’ legacy code patterns into a small list of bad programming practices that can make Java (and other) classes hard to unit test.

Patterns

First, a quick rundown of the patterns:

Adapt Parameter

If you have a method that takes a parameter that is hard to simulate, like HttpServletRequest in Java web apps, one solution (other than using mock libraries) would be to extract only the necessary part into a wrapper class. For example, if you only need to know a single querystring parameter, you can create a decorator class that only returns the single parameter. This would then be much easier to mock or fake than to have to override 30 or so methods that are doing things that are irrelevant to your test.

public void before(HttpServletRequest request) {
  //get params from request
}

public void after(MyParamsSource params) {
  //get params from wrapper class
}

Another reason you may want to implement this pattern is if the parameter simply CAN’T be mocked or faked. This would be true in the case of a concrete final class, for instance.

Break Out Method Object

Move a method that you want to test into a new, separate class. Local method variables can become instance variables of the new class, making it easier to substitute and break dependencies. This approach can be used when it’s nearly impossible to instantiate the class for testing, and refactoring all the dependencies would be too risky. While “Expose Static Method” (see below) is preferred for small methods which don’t have dependencies, “Break Out Method Object” can be used for the tougher cases.

public class UntestableClass {
  private BreakOutObject boo;
  public void untestableMethod() {
    boo.testableMethod();
  }
}

public class BreakOutObject {
  public void testableMethod() {
    //Do stuff we can test
  }
}

The key here, in terms of bad practices, is that the class you want to test for some reason is “impossible to instantiate” in a unit test.

Expose Static Method

Turn a method that doesn’t depend on instance variables or methods into a static method. This will allow you to test the method without having to instantiate the class. You can use this when you are unable to instantiate a class for testing, but the method you want to test doesn’t depend on any of the instance variables in the class.

public class UninstantiableClass {
  public void untestableMethod() {
    UninstantiableClass.testableStaticMethod();
  }
  public static void testableStaticMethod() {
    //Do stuff we can test
  }
}

Again, this pattern is a workaround for classes that are difficult or impossible to instantiate in a unit test. See the discussion in “Break Out Method Object” for practices that may necessitate this.

Extract and Override Call

Extract calls to a static method to a protected internal method, then override the method in a subclass. The unit test may then test the subclass instead of the original class. This pattern may need to be used when a static method call has dependencies that cannot be resolved in a unit test.

public class Foo {
  public void methodToTest() {
    //Do stuff
    extractedCall();
    //Do more stuff
  }
  /** Override me in tests */
  protected void extractedCall() {
    UtilClass.evilStaticMethod();
  }
}

As I have mentioned before, not all static method calls are necessarily problematic for unit testing. For example, a StringUtils-type method for converting a String to all caps, or a method for accessing an attribute via reflection wouldn’t prevent one from setting up an appropriate test case and executing the method. The key here is that the static method has dependencies that are hard to satisfy in a unit test, or does things that violate certain principles of unit testing.

Extract and Override Factory Method

Extract the instantiation of objects to a protected internal method, then override the method in a subclass. Test the subclass instead of the original class. This is related to “Extract and Override Call”, but is specifically for code related to the instantiation of objects.

public class Foo {
  public void methodToTest() {
    //Do stuff
    bar = extractedCall();
    //Do more stuff
  }
  /** Override me in tests to return subclass */
  protected TypeToMock extractedCall() {
    return new TypeToMock();
  }
}

Calls to “new” and calls to static factory methods (which don’t let you substitute your own implementation), including the getInstance() method common in Singleton classes, all prevent the unit tester from substituting the real class a mock or fake implementation. So the bad practice here would be to avoid instantiating objects directly in a method, or via a static factory method call that doesn’t permit substitutes. The alternative would seem to be to use a Dependency Injection approach, which generally leads to more testable classes, but there are other solutions as well.

However, to say that one should NEVER use “new” is a lot like saying you should ALWAYS use interfaces for your classes. We need to be practical about this. There’s nothing wrong with instantiating an object directly in your code (from a testing perspective) if the object doesn’t have any of those unwanted dependencies we’ve been talking about. It would be pure dogma to penalize someone for making a call to new Integer(myIntVal), for instance.

Extract Implementer

Turn an implementation class into an interface and move the implementation into a new, separate class. You can use this on any class that is passed as a parameter or used as a member attribute in your testing class in order to permit the substitution of different implementations. Note that if you are using a mock object proxy via a testing framework such as EasyMock, you don’t actually have to do this. The concrete class extension to EasyMock lets you create proxies of any concrete class. Note that you should use this pattern only when you think it would be a good idea to create an interface for your class regardless of testing…

public class WantToMock {} --> public interface WantToMock{}, public class WantToMockImpl implements WantToMock {}

The lesson here is that even objects with simple interfaces passed as a method parameter can be a problem for testing if they are hard to set up, or if they do unwanted things to your test environment. If the class is in your code base, then you have the option of extracting the nasty implementation details out into a separate implementation class. For testing, you can then slip in a mock or a fake object which only mimics the parts that are important to your test.

There is a second lesson here as well, which could complicate the calculation of a Legaciness metric (should it attempt to take this into account): the technology available may influence exactly how hard it is to write your unit tests. Early versions of EasyMock, for example, did not come with an extension that made it possible to mock concrete classes; only interfaces could be simulated. Nowadays, this is no longer a problem, although in my experience, the use of a mock library such as this is already more difficult than being able to write my own simple test classes (note that there’s a big difference between mock objects and fake objects). More recently, JUnit and other test frameworks have begun to allow the use of aspects for testing. I haven’t personally used these capabilities, and I’m not sure what all can be done with these new tools, but the point is that testing technologies are a moving target.

Extract Interface

Create an interface for your implementation class and change all parameters and attributes that reference the old class to use the interface. You can use this on any class that is passed as a parameter or used as a member attribute in your testing class in order to permit the substitution of different implementations. The difference between this method and “Extract Implementer” is that the interface itself will have a different name from the old class. Use this when you prefer to create a new generic name for the interface.

public class WantToMock {} --> public interface Mockable{}, public class WantToMock implements Mockable {}

Note that this is purely an application design decision, unrelated to unit testing. Otherwise, the implications of this pattern are the same as for its sister pattern.

Introduce Instance Delegator

If the method you want to test makes static method calls, you can define an instance version of the method on the external class which delegates the call to its static method. The idea here is that your class can then call the instance method on the class instead, which can then be mocked or overridden. This assumes, of course, that you also find a way to access an instance of the object without having to call “new”. This seems like a pretty radical change to the main application design to resolve what is a testing problem. Michael Feathers apparently prefers instance objects over static utility classes as a general practice.

public class InstantiableUtil {
  public static void staticFoo() {
    //Do something bad
  }
  /** Call me instead. Override in test class. */
  public void overridableFoo() {
    InstantiableUtil.staticFoo();
  }
}

At any rate, there’s nothing new we can learn from this pattern. The idea is that at least some static method calls are bad.

Introduce Static Setter

Add a static setter method to a singleton class that allows you to replace the unique instance. This can be used when your classes depend on a singleton class and you wish to alter its behavior for testing purposes. This method can also be used by “Global Factories”. If you have a factory class that returns objects via a static method, you can let your tests configure a mock or fake implementation via a Static Setter.

public class SingletonClass {
  private static SingletonClass instance = new SingletonClass();
  private SingletonClass() {}
  public static SingletonClass getInstance() {
    return instance;
  }
  /** This method should only be called by unit tests */
  public static void setInstanceForTesting(SingletonClass testInstance) {
    instance = testInstance;
  }
}

This is a pretty good alternative to the “Extract and Override Factory Method” pattern. However, it can be quite dangerous to use, as it gives any class access to the inner workings of your factory classes. At any rate, it’s the same old story here: not being able to substitute your dependencies with a mock or fake is a Bad Thing for unit testing.

Parameterize Constructor

Define a constructor for your class that allows tests to supply their own implementations of instance attributes. This is a good candidate to use when your class instantiates its attributes in the constructor.

public class ExternalDependencies {
  private BadDependency badDep1;
  private BadDependency badDep2;
  public ExternalDependencies() {
    badDep1 = new BadDependency();
    badDep2 = DoSomethingBadFactory.create();
  }
  /** Use me for tests */
  public ExternalDependencies(BadDependency badDep1, BadDependency badDep2) {
    this.badDep1 = badDep1;
    this.badDep2 = badDep2;
  }
}

As with many of these other patterns, this technique breaks encapsulation in the name of unit testing, so it can be dangerous. This pattern can be used to attack two different bad practices: unwanted dependencies caused by the use of “new”, and classes that can’t be instantiated for testing because they do bad things in the constructor.

Parameterize Method

Create a version (or change the existing version) of the method you are testing which accepts internal dependencies as parameters. If you create a second version, you can rewrite the original version to instantiate is variables as before, and then delegate the rest of the work to the new parameterized version.

public class NowCanMock {
  private Foo foo;
  public void doSomething() {
    doSomething(foo);
  }
  /** Call this version in tests, and send it a mock Foo */
  public void doSomething(Foo foo) {
    //Do something
  }
}

Pull Up Feature

Move dependency-free methods into an abstract superclass, then create a subclass of this abstract class that can be used in testing these methods. This is especially useful when you have a group of methods that can be tested and you’d prefer not to make them static or put them in a separate (unrelated) class. It is especially appropriate when the methods are seemingly unrelated, since related methods might better be refactored into a separate class vis-à-vis “Break Out Method Object”.

public class UninstantiableClass extends AbstractParentClass {
  //Other methods
}
/** Subclass me with concrete class for testing */
public class AbstractParentClass {
  public void testableMethod() {
    //Do stuff we want to test
  }
}

Replace Global Reference with Getter

Extract references to global objects (singletons and objects provided by static calls) into a protected method. Then use “Subclass and Override Method” to replace the object with another in tests. You can use this with any call to retrieve a global object. If the object is used in many places, you might want to consider a more general solution such as “Introduce Static Setter” or refactoring the object so it is no longer global.

public class Foo {
  public void methodToTest() {
    //Do stuff
    ref = getGlobalReference();
    //Do more stuff
  }
  /** Override me in tests to return subclass */
  protected TypeToMock getGlobalReference() {
    return GlobalClass.getReference();
  }
}

Subclass and Override Method

Extract bad dependencies or code into separate isolated methods (if they aren’t already). Create a subclass for testing and override these methods to remove the problem. This technique can be used on any internal method of the class which is not an essential part of the logic being tested. In cases where only a part of the method should be overridden, that part can be extracted into its own protected method.

public class Foo {
  public void methodToTest() {
    //Do stuff
    methodToOverride();
    //Do more stuff
  }
  /** Override me in tests to return subclass */
  protected void methodToOverride() {
    //This is too long to wait in a unit test!
    Thread.sleep(60000);
  }
}

From the example, you can see that there are times when the code does something untestable even without there being an unwanted dependency.

Supersede Instance Variable

Add a method (i.e. a “setter”) to your class that allows you to replace the standard value of an attribute with one of your own choosing. This is a very easy way to insert fake and mock objects into your class for testing. However, it is also very intrusive, so it should be used with care. If you are using Spring or another IoC framework, it is very common to offer setters for all dependencies (with the alternative approach being “Parameterize Constructor”). When this approach is used, it doesn’t prevent the original dependency from being instantiated. The test waits until after it has been initialized to replace the original value. If the dependency prevents you from instantiating your class from testing, an alternative approach must be used.

public class Foo {
  private Attribute bar;
  private Attribute baz;
  public Foo() {
    bar = new Attribute(1);
    baz = new Attribute(2);
  }
  public void setBarForUnitTesting(Attribute bar) {
    this.bar = bar;
  }
  public void setBazForUnitTesting(Attribute baz) {
    this.baz = baz;
  }
}

Once again, this solution breaks encapsulation and “best practices” for OO. Another approach to this problem would be to use reflection to set the value of a private attribute (yes, in Java, it’s possible to do this). It may require a little more work, but at least it wouldn’t impact the design of your class.

Bad Practices

These patterns are aimed at surmounting the following problems:

  1. The class can’t be instantiated in a unit test environment
    • Break Out Method Object
    • Expose Static Method
    • Parameterize Constructor
    • Pull Up Feature
  2. A bad dependency is hard to mock or fake (because it is final, or because creating a subclass or mock is an unusual burden)
    • Adapt Parameter
    • Extract Implementer
    • Extract Interface
  3. There is no “cut point” at which a bad dependency can be substituted by a mock or fake
    • Extract and Override Call
    • Extract and Override Factory Method
    • Introduce Instance Delegator
    • Introduce Static Setter
    • Parameterize Constructor
    • Parameterize Method
    • Replace Global Reference with Getter
    • Supersede Instance Variable
  4. There is a section of code that is untestable for some reason (it violates one of the principles of good unit tests)
    • Subclass and Override Method

In other words:

  1. Creating classes that can’t be instantiated outside their “Integration” environment is a Bad Thing.
  2. Creating classes that are hard to mock or fake is a Bad Thing.
  3. Instantiating or using objects or static methods without any way to substitute them is a Bad Thing
  4. Doing things in your code which violate the basic principles of unit tests, and can’t be overridden in unit tests is a Bad Thing

As far as definitions of bad practices go, this list is pretty wishy-washy and hard to use as a litmus test for your code, especially if you’re trying to do it automatically, like I’d like to for the Legaciness metric. It looks like some more analysis and definition is in order. I’ll start with Bad Practice #4 by talking about something easy and well-known:

Principles of Unit Testing

Ok, there are tons of articles on this subject, so I won’t go into details. Tests are supposed to be maintainable, easy to run and trustworthy. Some consequences of this that relate to our Bad Practices:

  • They shouldn’t affect state of system (tests should be self-contained, and be run in any order)
  • The test should rely on as little code as possible (preferably only the single class/method that concerns you
  • The outcome should be determinate (it shouldn’t depend on environment conditions, race conditions, etc.)
  • It should run as fast as possible (over a second is considered too long, I think Michael Feathers sets 100ms as a ceiling)

So, for BP#4, we get the notion that we shouldn’t do things in our code like:

  • Set global variables (e.g. change default Locale or Timezone, put things on the JNDI or the ApplicationContext, change environment variables, etc.)
  • Have big ol’ honkin’ methods, or call methods like that without having a “cut point” (place to substitute and fake it)
  • Use random numbers, spawn competing threads, base our results on the current time, etc.
  • Call Thread.sleep() for long periods (as in the example I gave for “Subclass and Override Method”)

That’s a pretty huge constraint, so what the legacy patterns really tell us is that we shouldn’t do those things UNLESS WE HAVE A CUT POINT for them.

Bad Dependencies

Many of the other patterns related to having a bad dependency somewhere. “Bad” in this case doesn’t just mean “not mockable”. It also means that the dependency would violate one of the principles of unit testing. What sorts of dependencies are those? As I mentioned before, a instantiating a simple data class with only getters and setters using an explicit “new” isn’t going to do you any harm. Nor will a static call to Integer.valueOf(). But others aren’t so innocent. Examples might include:

  • Database calls
  • File system I/O
  • JNDI dependencies
  • EJB Container dependencies
  • Global variables

… and so on. Note that there are some things that make it IMPOSSIBLE to test, and others that just add work.

Conclusion

This isn’t actually a conclusion… more like a beginning. The real question here is how this can be turned into a “Legaciness” metric. As I mentioned, I think It would be a useful compliment to code coverage and complexity reports. For the code that doesn’t have unit tests, how hard would it be to wedge some in there? But it appears that it won’t be trivial to turn this into a useful metric. I’ll explore these “Bad Practices” some more in future posts.


Wiki with Version

August 14, 2008

I’m looking for a wiki that has all the standard features, plus one more: integration with Subversion. By that, I don’t just mean it can spew calls to a command-line “svn” whenever you update a page. Sure, that’s a good start, and I hear rumors that TWiki has plugins that can be hacked to do that. What I really want is a full awareness of the branching features of Subversion… I want a Wiki with Version.

The idea here is to be able to use a wiki as the location of record for my application’s documentation. The problem is that my application is constantly being branched and versioned. A single set of documentation (architectural or otherwise) would have no way of capturing all the nuances and changes between versions, so we need to have a separate set of documentation for each. We already have a user guide up in a wiki for our customers, and I can assure you that it can be a nightmare to maintain the documentation for all releases. It basically comes down to a separate document tree for each release, with a lot of copy-paste between them. And with no automatic “merge” feature to speak of. At least with user docs, we only care about releases; for internal documentation, every branch could have unique information.

So, I’d like my wiki to actually store its data in Subversion. I’d like it to know what my project root is, and what branches are available. I’d like it to automatically produce a new “document tree” whenever a new branch is created. I’d also like to be able to merge pages across branches. If I can’t do it via the web interface, at least I’d like to be able to do it in Subversion and have it show up in the wiki.

This doesn’t sound like rocket science, but I haven’t found anyone that’s done it yet. There’s a project called SubWiki that looks inspired by the same idea, but it apparently never got off the ground. Maybe I’m looking for the wrong thing – is there a content management system that would do this better? If I don’t find something soon, I may have to start my own “WikiVN” project so that I don’t have to copy-paste things by hand. But I also don’t want to have to rewrite all the wiki functionality out there from scratch. How about a TWiki plugin?

Oh, one other must-have feature: in the name of canonicality, I’d like to be able to autogenerate official-looking Word Documents or PDFs from these pages. I suppose if they are in HTML files, I could hack it, but wouldn’t it be great just to get a list of the wiki pages, select the ones you want, order them, and *poof!* out comes the doc! I’ve had enough experience with this to know that web docs != PDFs without a lot of conscious thought and work, but if there’s user-friendly way to design different stylesheets, it could just work.


Varying levels of quality

August 12, 2008

I recently gave a presentation to our development team about Emergent Design, based on the presentation given by Scott Bain at the Dr. Dobbs conference in Chicago. The presentation goes way beyond the use of design patterns to talk about the underlying “principles” (defined more or less as a particular “wisdom” about development) upon which design patterns are based, and specific “practices” (defined as things you should always do because they don’t cost much, and generally embody one of the principles in some concrete way).

Examples of principles include the Open-Closed Principle, and the DRY Principle. Programming by Intention is classified as a practice. He also defines TDD and “Pattern-Oriented Development” as “disciplines”, because they embody principles, but require some level of effort to implement. In the case of disciplines, he says, you should carefully consider the value they provide in your specific situation to see if they make sense for you.

As an architect, it is commonly my responsibility to define standards and best practices, and then make sure one way or another that they are followed. I am often confronted with “special case” scenarios, where for some reason (it’s throwaway code, it’s for a different application, it’s “just a demo”) the developer feels that it would be overkill to follow all our usual standards. This usually goes beyond what Scott Bain defined as disciplines to just about anything: Javadoc, Programming by Intention, writing unit tests, worrying about proper design, using System.out.println(), whatever.

In essence, the question is: is it OK to have different levels of quality for different types of code? Over the years, I’ve found myself waffling on this issue of whether or not it’s necessary follow the standards in these special cases. Recently, I’ve been pretty flexible on the issue. In part it’s because I was introducing some new standards that I felt would be an extra burden, initially, to developers, and I wanted to let them get used to them slowly without them feeling I was being unreasonable about it. In part it’s because I don’t think any practice (or discipline or whatever) should be used blindly without a little thought as to whether or not it’s practical. Allowing for varying levels of quality is one way I could give developers that type of flexibility to decide for themselves.

Giving this presentation has provided me an opportunity to reflect once again on this subject. And once again, I feel I’m swinging back to the other side on this one. There are two reasons for this: the so-called disciplines, and the “killer demo” syndrome.

There’s a reason why “disciplines” are called what they are. It’s because to do them right, to do them efficiently to the point that they really pay off, they require some practice. They also require a conscious decision on the part of the developer to use them. If you’ve ever written code using TDD, you know what that feels like. You’re all ready to start spouting out a brilliant gobs of code that will revolutionize the lives of millions, mow your lawn and pick up the kids from school, get rid of unwanted facial hair, get rid of embarrassing age spots… but then you remember that before all that, you have to write a TEST! Bummer. But for those who have gone through this process, you know that in the end, it’s well worth it, and even enjoyable once you get over that first hump.

Practices aren’t necessarily any easier, at least not until you’ve ingrained them into the way you do your work in general. But these days, I find it hard NOT to write my code using a Programming by Intention approach. It’s just the way I think.

Now, if following disciplines and using best practices takes some practice to get used to, and if in the end you are more productive and produce better quality code, why on earth would you look for opportunities NOT to to get in some good practice? It reminds me of the day I learned how to really type (and not just hunt-and-peck). I knew all about the “home” positions and all that, but had always put off doing it. Then one day, I had a paper to write, and decided that “this is it”. I wasted about two hours worth of productivity struggling to feel out the keys. 17 years later, I’ve never regretted it, and never gone back. My hope would be that programmers would try to follow best practices of their own volition. But when you’ve got deadlines, or when you’re working on a piece of code that you know is heading straight for the recycle bin, perhaps you feel like “cheating” just this once.

As the one who maybe has to play the role of the enforcer now and then, that’s really not a strong enough reason for me to stick my nose where it doesn’t belong. I have enough things to worry about already. The thing is that it can become my problem when that code that was heading straight for the garbage compactor makes a sudden left turn towards the big production onramp, and merges with the flow of traffic right into trunk. This is what Joe Yoder calls the “Killer Demo”, or “Throwaway Code” problem in his Big Ball of Mud article. It happens all the time. I just recently oversaw two or three “demos” that were merged into our application. Some were given the proper time for a complete rewrite, but some were just kinda tidied up, and that’s all. I am also working with some “throwaway” scripts that we’ve been maintaining for about 18 months now. That’s a pretty long time to work with something that was written on the sly.

So, what to do? Should I make an about face and start enforcing standards on all code at all times? I still think developers should be allowed to think for themselves. If they are coming to a different conclusion than I would, it could be a matter of opinion. I also think it’s a matter of culture. If developers aren’t being inspired to do these things for themselves, then maybe there’s more I could do to change that. What was that commandment again? Oh, right. “Show the way”.


Follow

Get every new post delivered to your Inbox.