Pages

Thursday, August 20, 2015

High Performing Agile Teams: An Introduction

I debated whether I wanted to include Agile in this post's title or not. I'd prefer it to just be "High Performing Teams", but let's be honest, I need the Agile keyword for more people to be interested in the post.

I love Agile. I hate Agile.

I have a love/hate relationship with Agile:

  • I love its fundamental principles. I hate the large industry selling a shell of it.
  • I love the business results it can produce. I hate when it is an end in itself.
  • I love how it empowers people. I hate how it can be a tool for command-and-control.
  • I love how much I've learned from people in its community. I hate the incessant, useless noise that surrounds it.
  • I love when it includes its necessary components (planning, technical, business value, YAGNI, etc). I hate when it's reduced to daily standups, stories, and sprints.

I've sure you could create your own list like this one (I'd love to see it, so leave a comment if you've got one). There's so much surrounding Agile that it's easy to hate parts or even all of it. But its essence is still something to love. Its essence is what got everyone excited about it in the first place.

Agile's Essence: High-Performing Teams

Its essence is a set of values, principles, and practices that help teams flourish (thanks Kent Beck). Its essence is to create high performing teams.

The parts of Agile I hate are the parts that ignore this essence. High performing teams are the goal. Not practices. Not user stories. Not estimation. Not Scrum. Not the manifesto. Not TDD. Too often the practices become the goal while we lose sight of the real goal: high performing teams.

My goal is to recapture this essence with a series of blog posts about high performing (Agile) teams. There will be discussion of practices, but only as they fit into the greater goal to build high performing teams. But before I talk about practices, I will first cover the prerequisites for high performing teams. Stay tuned!

Tuesday, April 14, 2015

Dependency Elimination Example: Primitive Support

Last post, I showed a canonical example for the Dependency Elimination Principle. I want to show another Dependency Elimination example that solves another common pattern I see. I've given this pattern a name: Primitive Support.

Introducing: Primitive Support

Primitive Support is the natural outworking of the Code Smell called Primitive Obsession. Our code suffers from Primitive Support when it has these two parts:

  1. A primitive type (int, string, etc) representing a domain concept (megabytes, phone number, etc).
  2. A helper class that does something meaningful with that primitive (e.g. MegabyteConverter or PhoneNumberParser or FooHelper).

If we have classes named similar to MegabyteConverter or PhoneNumberParser or FooHelper, we might be suffering from Primitive Support. Now let's look at an example.

A Simple Example: E-mail Address Validation

Let's say we're working on a user signup experience. A valid e-mail address is required for new users. We need our API to enforce that the e-mail address is valid. One way we might do this is like the below1:

This is actually pretty good as is. It's relatively easy to test and easy to read. There is, however, a lack of cohesion. First, UserSignup is worrying about validating e-mails when it really should just sign up the user. Second, email validation is off on its own in a general EmailHelper class. We will improve this soon, but first we'll take a detour in the wrong direction.

A Slight Rant

Unfortunately, some of the SOLID and TDD literature will lead you away from this design towards a more complicated design. In the name of separating concerns (good), standard practice will tell you to extract e-mail validation to its own concern and pass it as an interface to UserSignup (less good). Similar to this:

Now we have an IEmailValidator and an EmailValidator to separate the validation concern. To test UserSignup, we'll mock IEmailValidator and make sure it's called with the given emailAddress. Standard unit testing practice.

Testable, But Complicated

Let's evaluate the code. It's testable. We've separated our concerns. But it's more complicated. And we still have a cohesion problem: Email address validation is still a concern of UserSignup, and the validation implementation lives in its own EmailValidator world. We can do better than this.

Address the Root Cause: Kill the Primitive

The fundamental problem is that our system cares about e-mail addresses, but it doesn't represent e-mail addresses as first class citizens. We've split the e-mail address concern across UserSignup and EmailValidator. To fix this cohesion problem, we need to stop using string for e-mail addresses and start using EmailAddress for e-mail addresses. Watch how the complexity melts away:

First, note two important pieces:

  1. EmailAddress is a new type that is now a Whole Value for e-mails.
  2. The EmailAddress constructor throws when it is invalid. This makes it impossible to create an invalid e-mail address.

Now, note the supreme wins we get from this approach:

  1. We've completely separated the concerns. UserSignup has no validation calls or implementations. It just uses an EmailAddress like it should.
  2. We've improved cohesion. E-maily things live on EmailAddress. UserSignupy things live on UserSignup. No overlap.
  3. EmailAddress validation is now a compile-time concern. You can't make a bad one, so type-checking will guarantee that the thing you pass in is valid2.

What We Learned

Code with Primitive Obsession will usually lead to Primitive Support: introducing dependencies to do meaningful things on primitives. We can eliminate these dependencies by replacing the primitive with a Whole Value for the concept it represents. The supporting dependencies go away, the code is more clear, and the compiler catches bugs for us. Wins all around!




Footnotes

1Note: you might do this more simply via your library/framework validation system, but I'm leaving those out of this conversation for educational purposes.

2I know, I know we can still technically pass null. But if null makes it this far into our system we have bigger problems.

Monday, February 9, 2015

The Dependency Elimination Principle: A Canonical Example

There's been quite a bit of discussion so far on the Dependency Elimination Principle. One thing obviously missing from my posts is a code example. This example illustrates a common class of unnecessary dependencies.

I'll use application configuration as the example. I'll uncreatively title the class of unnecessary dependencies: "The thing that gets the thing you need". And I'll uncreatively title the remedy to this problem: "Pass the thing you need, not the thing that gets the thing you need".

The config example


Most applications we write have a configuration defined via some XML or JSON file sitting near the executing code.  We want to keep the system modular and testable so we make sure the application code doesn't depend directly on this configuration file.  A common way we implement this looks similar to this:

Then when one of our application classes needs a value from the application's configuration, we give it a dependency on IConfigurationReader and let it read a config value in one of its methods. For this example, let's make a class that generates invoices. We have multiple environments and don't want to mistake test invoices for real ones. So we decide to put a watermark on invoices generated outside of production. One way to accomplish this would be to create a "invoiceWatermarkText" config setting that is set in test/staging and not set in production. Here's what this might look like:

This is SOLID, decoupled code. InvoiceGenerator rightly doesn't know about the details of how configuration works. And it's testable because you can stub out the configuration reader. However, there are still problems.

Loose coupling is still coupling


Although InvoiceGenerator doesn't know about how configuration works, it still has to know there is such a thing as configuration. This makes things more complicated. When you test, you have to provide a stub. And when you create an InvoiceGenerator in the production code, you have to provide a real configuration. InvoiceGenerator is still coupled to configuration, thus making it impossible to use it without supplying some sort of configuration reader.

Eliminate the coupling


We can improve this with a simple fix: Pass the thing we need (the watermark text), not the thing that gets the thing we need (the IConfigurationReader). It will look something like this:

Now we can painlessly use an InvoiceGenerator literally anywhere in any application. And there's less to think about when reasoning about it.

But...we still need the config part


You're probably wondering, "Ok, so I still need to read that text from config to give it to the InvoiceGenerator. Where does that code go?". You have a couple options here:
  • Just read it from config on the line that is calling GenerateInvoice
  • Create a one-line overload to GenerateInvoice that reads from the real configuration reader.  No need to test that line.

Wrapping it all up


We often introduce a dependency so we can get the thing we need.  However, we usually only need the thing we need.  So we pass the thing we need, not the thing that gets the thing we need.

Tuesday, September 23, 2014

Beyond SOLID: The Dependency Elimination Principle

Last post I explained why I don't teach the SOLID design principles.  Read the post for more detail, but the primary reason is that SOLID encourages heavy use of dependencies.  Applying SOLID to a codebase for even a short time will yield dependencies on abstractions everywhere -- quickly producing a codebase that is unintelligible.

What should we do about these dependencies?  We start applying the Dependency Elimination Principle.

Treat Dependencies As Code Smells


With the Dependency Elimination Principle, we change our default to treat dependencies as code smells.  This doesn't mean we won't have dependencies.  It just means our default is to treat them as code smells.  This new default forces us to examine why we need each dependency and how to eliminate each.

Are we getting something from the dependency?  If so, pass the thing we're getting, not the thing that gives it to us.

Are we sending something to the dependency?  If so, consider a model that uses events + event binding instead of passing in an interface.  Or use a DTO that represents the state of the dependency and respond to changes to it (e.g. MVVM).

Whole Value


Most codebases have way too many dependencies because they don't have their concepts defined as Whole Values.  Here are some simple pointers to create a clean, intelligible codebase that won't use a lot of dependencies on abstractions (lifted from J.B. Rainsberger's take on the 4 Rules of Simple Design):

Kill Primitive Obsession
Name things as Nouns (and not using verb nouns that have an ‘er’ ending)
Remove duplication

Applying these simple pointers will shock you in how quickly your code becomes simple, readable, testable, and extendable but without all of the baggage that comes with littering interfaces everywhere.

Using Testability as the Lens


Let's look at the Dependency Elimination Principle from another lens: testability.  Code with dependencies (even if those dependencies are mockable) is more difficult to test than code without them.  Here are the levels as I think of them from easiest to hardest (I think I got this from another blog post but can't for the life of me find it):

  • Level 0: A pure static function with no side effects
  • Level 1: A class that has immutable state.  Think a Whole Value that replaces a primitive, like EmailAddress or PhoneNumber.
  • Level 2: A class that has mutable state and may operate against behaviorless dependencies like Level 1 Whole Values.
  • Level 3: A class that operates against a dependency with its own behaviors


Level 0 is trivial to test.  Just pass in the different inputs and expect the right outputs.

Level 1 is not much different than level 0, except you have a few more methods to test and a few more configurations to test as well.  Level 1 is nice because you get to encapsulate a concept into a Whole Value.

Level 2 is more difficult than level 1 because you have to manage the internal state and test different cases when the state changes.  But sometimes you’ll want level 2 code because of the benefits it brings in encapsulating a concept into a Whole Value.

Level 3 is the most difficult to test.  You either use mocks or you test more than one thing at once.

I want to make testing as easy as possible, so I strive to choose the lowest level that meets my needs.  This means lots of Level 0 and Level 1 code.  Some Level 2 and rarely any Level 3.  My code becomes mostly functional but takes advantage of OO to create nice Whole Values that keep all related behavior in the same place.

Circling Back to SOLID


Assume we've applied the DEP to a codebase.  Let's analyze how SOLID that codebase is:

Single Responsibility Principle: Heck yes.  Whole Values everywhere.  Extremely high cohesion.
Open-Closed Principle:  Yes, but in a different way.  The openness is in the way we compose all the little Whole Values, not in plugging in new dependencies everywhere.
Liskov Substitution Principle:  Irrelevant.  We're not using inheritance much anymore.
Interface Segregation Principle: Again, irrelevant.  We aren’t using many interfaces
Dependency Inversion Principle: Mostly irrelevant because most dependencies are eliminated.  The dependencies that remain are just Whole Values which you treat as part of your type system and perhaps a tiny handful of interfaces to talk to the outside world.

It's all about the Single Reponsibility Principle


Applying the Dependency Elimination Principle leaves you laser-focusing on the Single Responsibility Principle.  And you get the flexibility of Open-Closed that leads to business agility.  And you lose all the legibility baggage that comes with Liskov, ISP, and DIP.  Wins all around.

For more reading on Dependency Elimination, check out Arlo Belshee's posts about No Mocks.  He's the one who introduced all of these ideas to me.

(UPDATE: It's possible the unknown source of the levels described above is from John Sonmez's blog here and in related posts)

(UPDATE 2: Check out an example that shows a common class of unnecessary dependencies here)

(UPDATE 3: Another example that shows how Primitive Obsession leads to unnecessary dependencies

Friday, August 22, 2014

Why I Don't Teach SOLID

If you talk about software design with anyone who cares about code quality, you won't spend much time before you hear SOLID.  SOLID is a mnemonic device that helps developers remember five important principles of object oriented design:

  • Single Responsibility Principle
  • Open-Closed Principle
  • Liskov Substitution Principle
  • Interface Segregation Principle
  • Dependency Inversion Principle
SOLID is helpful.  It came from really important people in our field.  It helps people reason about design.  It helps people make systems resilient to change. 

SOLID used to be a cornerstone of my design toolbox.  I used to strive to make my code SOLID.  I used to teach others to do the same.

Today, SOLID remains important, but I don't strive to make my code SOLID.  I rarely mention it when talking about design.  And I definitely don't teach it to developers eager to learn good design techniques.  It doesn't come with me in my toolbox.  It stays in a dusty box up in the attic.  I keep it because it is important, but I access it rarely.

SOLID causes problems.  Problems big enough that warrant stowing it away in the attic.  When I used to champion SOLID, those who resisted would point to these problems.  I would dismiss these people as naysayers, resistant to change, or disinterested in code quality.  But now I've learned that they were right all along. 

If I could use one word to represent these problems, it would be unintelligible.  Developers (myself included) applying SOLID frequently produce codebases that are unintelligible.  These SOLID codebases have low coupling.  And they are testable.  But they are unintelligible.  And often not as adaptable as the developers had hoped.

The main culprit is SOLID's focus on dependencies.  Open/Closed, Interface Segregation, and Dependency Inversion each encourage heavy use of dependencies defined as abstractions (i.e. a C#/Java interface or Abstract Class).  Open/Closed encourages abstractions for easy extensibility.  Interface Segregation encourages more client-defined abstractions.  Dependency Inversion says to depend on abstractions instead of concretions. 

These all lead developers to create interfaces everywhere.  They litter the codebase with interfaces like IFooer, IDoer, IMooer, and IPooer.  Navigating it becomes a nightmare.  You rarely know by inspection what piece of code is actually going to run.  But it's ok.  Because it's SOLID.  It's great design!

To help manage the madness, we then introduce an IoC container.  And a mocking framework for our tests.  If it was intelligible before, now it's really not intelligible.  You now literally can't find a call to 'new' anywhere in the code.  Good luck reasoning about any piece of code now.  But it's ok.  Because it's SOLID.  It's great design!

Is it great design if it's unintelligible?  Is it great design if a developer can't easily reason about it?  I don't think so.  SOLID is helpful and important.  But I don't think developers handle it well.  Which is why I don't teach SOLID anymore. 

Stay tuned for how to achieve what you're trying to gain with SOLID without the legibility baggage.

UPDATE: You can find the next part here.

Thursday, August 21, 2014

Here we go!

I decided to start a coding blog.  I've titled it Quality Is Speed because I don't believe the common anecdote that you have a tradeoff between quality and speed.  I believe the opposite is true: high quality is what enables speed.

Who knows if I'll consistently post here, but we'll give it a shot!