Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions _rules/1002.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
rule_id: 1002
rule_category: class-design
title: Only pass things to a constructor that most or all members need
Comment thread
dennisdoomen marked this conversation as resolved.
Outdated
severity: 3
---
A constructor exists to put the object in a valid, usable state. If a dependency or value is only used by one or two members out of many, passing it through the constructor forces every caller to provide something that is barely relevant to the object as a whole. This is a strong signal that those members belong in a separate, more focused class (see [AV1000](#{{ site.default_rule_prefix }}1000)).

**Exception:** Cross-cutting concerns such as logging or clock abstractions are often needed broadly and may reasonably be injected through the constructor even if not every member uses them directly.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a bit vague regarding injected dependencies.

  • "If a dependency is only used by one or two members out of many..." -> don't
  • "Cross-cutting concerns may reasonably be injected even if not every member uses them directly." -> do

So, suppose we define a class with 5 members, and only one needs the IClock abstraction. What should I do? If it's a method, I can take a parameter (placing the burden on the caller to explicitly pull it from the service container). But if the member concerns a property (for example: CacheEntry.IsStale), I need to change it into a method first.

I think it would help to distinguish between the kinds of parameters: values and dependencies. Then the rule definition can be about values, while the exception is about dependencies.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, you're right, and I don't think we can define this rule in such a way it is comprehensive enough to provide clear guidance. Unless you know a better way.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another issue with this rule is that API breaking changes are required if the implementation changes. For example, in the current version, the parameter X is omitted from the constructor because it's used by only two members. In the next version, a new member that also depends on X is added, so X must now be added as a constructor parameter and removed from the existing members.

I think we should drop this rule.