There’s a common pattern where an object is constructed with a Context object that carries all the dependencies the new object might need. It’s often used, for example, with classes that package up domain behaviour based on lower-level services, something like this:
public class PriceReconciler { private final Context context; public PriceReconciler(Context context) { this.context = context; } public boolean isAvailable(Item item, Price price) { Location location = context.getLocationFinder().findLocationFor(item); SKU sku = location.lookup(item); return context.getCurrencyConverter() .compare(price, sku.cost()) < 0; } // and so on... }

Over time the Context gets used in more and more places, and acquires more and more contents to carry around. It starts to feel like Mary Poppins’ carpet bag (there’s an old cultural reference) that contains a roomful of furniture. When everything is available everywhere then developers will use what they have in scope and, pretty soon, there are implicit dependencies all over the domain layer.
A while ago, I was working with a class that used one of these context objects. The class was quite large so, to help us understand it, my pair and I extracted the services it used into fields:
public class PriceReconciler { private final LocationFinder locationFinder; private final CurrencyConverter currencyConverter; private final LooseChangeCollector looseChangeCollector; public PriceReconciler(Context context) { this.locationFinder = context.getLocationFinder(); this.currencyConverter = context.getCurrencyConverter(); this.looseChangeCollector = context.getLooseChangeCollector(); } // and so on... }
Doing this made clear that the class used only three of the many services available on the context. More interesting, it showed that the looseChangeCollector
was only used once, in a method that turned out to be referenced just once—by a class that also had access to the context. Our extraction highlighted that this behaviour was in the wrong place, it didn’t really have a relationship with the rest of PriceReconciler
, so we moved it to its calling object and simplified the PriceReconciler
. With just two dependencies, our
next step was to set them directly in the constructor
public class PriceReconciler { private final LocationFinder locationFinder; private final CurrencyConverter currencyConverter; public PriceReconciler(LocationFinder locationFinder, CurrencyConverter currencyConverter) { this.locationFinder = locationFinder; this.currencyConverter = currencyConverter; } // and so on... }
which made the PriceReconclier
just a little easier to reuse since we’d narrowed its dependencies.
Kent Beck wrote recently about this tension between being concrete and abstract parameters. There obviously isn’t a single answer, except to note that when two or three objects keep turning up together, there’s probably a missing intermediate concept where some of the behaviour really belongs. The trick, when turning that concept into a type, is to give it a meaningful name so that it’s hard to add features that don’t belong.