SearchWiki
Heuristics.RecentChanges
Edit Page
Page Revisions
Home
Design Patterns
Heuristics
Software Development
Software Process


Patterns
TheIntroduction LogicalDesign PhysicalDesign PatternFoundations GuidelinesAndMyths ReferenceImplementation DependencyPatterns UsabilityPatterns ExtensibilityPatterns MaintenancePatterns AntiPatterns UtilitiesAndTools

AllPatterns

Name

AcyclicAssociations

Statement

Design uni-directional associations.

Sketch

Description

A cyclic relationship exists when two classes hold references to each other. The worst case scenario for a cyclic relationship is when two classes are contained in two different components. The result is a violation of AcyclicRelationships for the two components.

Even if two classes are in the same component, or some package, a cyclic relationship between classes creates a higher maintenance cost, and increases complexity. Often times, AbstractCoupling can be applied to eliminate cyclic dependencies.

A bi-directional relationship between two concrete classes is undoubtedly the strongest form of coupling. A bi-directional relationship exists between two classes when each class references the other. Figure 8.4.1 illustrates a bi-directional relationship between classes Client1 and Client2. Three way bi-directional when A --> B --> C --> A

There are three manifestations of a bi-directional association:

  • A 1:1 relationship where each reference contains only one instance of the other (Bill – Router). Usually, the primary reason for this separation in the first place is to ensure a SingleChangePurpose.
  • A 1:M relationship where one of the references contains multiple instances of the other (Bill -- Patient).
  • A M:M relationships where each reference contains multiple instances of the other (Student -- Course) Student has a grade Array. Student has method returning list of courses. Course has a method returning list of grades.

Implementation Variations

Solutions:
  • Refactor to uni-directional when one end of the association isn't needed. (P. 200 Refactoring). You can usually rocognize that one end of the association may not be needed by closely examining the application. Typically you'll find that when you want to obtain a reference to one of instances, you'll already have a reference to the other. For instance, if a Bill and Patient class initially have a bi-directional association, and you find that you rarely have a Patient without first having a Bill, then you can remove the dependency of Patient on Bill.
  • Couple the less often used side abstractly.
  • Break out the reason for the bi-directional association into a separate class.
  • Reduce the association to a dependency by passing one of the references as a parameter to the method requiring it. While this is the approach taken by Fower in Refactoring, it's usually my last resort since a dependency still exists between the two classes, and I especially avoid it if the classes are in separate components to ensure I avoid AcyclicRelationships.

Consequences

Sample Code

Related Pattern(s)

Edit Page - Page Revisions - WikiHelp - SearchWiki - RecentChanges
Page last modified on October 25, 2004, at 09:30 PM