Start decoupled

Suppose you’re writing some code that needs to list a user’s subscriptions. Your first instinct is to add a user.get_subscriptions() method.

But wait. Why is this user‘s responsibility? What if you start with something like this instead: Subscription.list(user_id)

In the original example, you jumped straight to coupling User and Subscription. Wherever you want to list subscriptions, you must have or create a full user object. In the second example, you only need to know the user’s id.

As you continue writing code, if you find yourself with many calls to list subscriptions for a user, and they are always in the context of having a full user object, now it’s time to couple them. But since you already have code to get a list of subscriptions for a user id, it’s a simple refactoring to add a user.get_subscriptions() method that calls Subscription.list( internally, which is probably a lot cleaner than whatever the method would have contained if it was created at the start.

Coupling has drawbacks and benefits. Be mindful of defaulting to coupling. Maybe it would be better to start decoupled and wait until your code makes it obvious that the trade off will be worth it.