Skip to content

Instantly share code, notes, and snippets.

@richmolj
Last active December 18, 2015 19:19
Show Gist options
  • Save richmolj/5832296 to your computer and use it in GitHub Desktop.
Save richmolj/5832296 to your computer and use it in GitHub Desktop.
Lee and Lou's DI Guidelines
1. If something is simple and <30%* likely it will be changed, don't DI for DI's sake:
  • This is probably a sliding scale depending on the scenario. 30% is obviously a loose guideline and serves as a jumping-off point. Just know it's not 90%.

Example 1 (Encrypter)
Example 2 (simple published_at)

2. When something is <30% likely to change, but getting complicated:

Add a class if this is a separate responsibility: Example (Delay)

3. When things are >30% likely to change:

a) If we're only using it in 1-2 places, use Service Locator
Example (Rack::Director)
Example (Carrierwave)

b) It's a smell if you're passing a reference to a class.

Example (post backend)
We probably want to be passing @backend here, because it explicitly calls our our collaborator and it's likely to be used throughout the class in a variety of ways. Something like this just garbles things up.

c) Blocks can often manage modular configuration as well, ie
This NOT This

In the second example, we have all the downsides of Service Locator but no benefits. If we can pass this as a block instead of a heavier-weight Configuration, let's do so.

d) Commonly used, global-ish components that are not specific also work for SL: Example (SearchVersion2)

4. Testing should not be a factor
5. Switching behavior based on context is a hammer, because we're changing the way things work in ways the developer may not be aware of.

This should not be a common pattern, but can be useful for high-level 'framework' setup where we don't necessarily want/need the developer to know of the context switch:

Example 1 (redirect puts for crons)
Example 2 (time zones)

  • Switching a bas service to return stubbed data

A good rule of thumb is: if you are doing something like this it's something you should bring up to Tech Huddle Reps and likely the larger team, since you are dealing with the 'BGov framework', not a specific feature.

6. Use guideline 3a when considering feature toggles.

A one-off toggle that exists mainly for "test before turning it on to users" purposes can be referred to via Feature::Set.toggled_on?(:name) (rails 3) or Bgov::FeatureToggling::FeatureSet.toggled_on?(:name) (rails 2) directly within a class (especially if you remove it shortly thereafter). Longer-running toggles that more substantially change a class's behavior should be passed in or ideally only referenced at controller level.

7. DO use DI when you have collaborators that are >30% likely to change, and important to be called-out when thinking about the class's behavior.

You will likely come away with a better feel for the domain: Example (post backend)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment