In general, cycles in package diagrams should be avoided:
Cycles like the one above can cause problems at build time. Which package should be built first?
Sometimes we can eliminate the cycle by extracting the elements of p3 that are used by p1 and putting them in a separate package:
In a layered architecture packages are layers.
In some cases the layers represent different levels of abstraction. A dependency from a lower layer, like p1, to a higher layer, like p3, indicates that lower levels of abstraction paradoxically depend on higher levels.
Often lower layers of a layered architecture contain more reusable components than higher layers.
Recall the Reusability Hierarchy presented in the discussion of the Reusability Principle:
For example, in the following design assume the utils package contains foundation components such as Person, Date, and Money; the framework package contains architectural components such as EventManager or MessageDispatcher; the business package contains domain specific classes such as Customer and Transaction; and the ui package contains application-specific components such as CustomerView and TransactionView:
We can view this design as a layered architecture. The utils package is layer 0, the framework package is layer 1, the business package is layer 2, and the ui package is layer 3. In this case higher layers can directly depend on any of the lower layers. Also, the lower layers contain more reusable classes. Currently, there are no cycles in the design.
Suppose a class in a lower layer depends on a class in a higher layer. For example, suppose the Transaction class in the business package (layer 2) depended on the CustomerView class in the ui package (layer 3). Notice that this degrades the reusability of the Transaction class. A programmer wishing to import the Transaction class into a new application will also have to import the CustomerView class. But this class probably has dependencies on other classes in the ui package. In an extreme case the entire ui package might need to be imported into the new application. While it's reasonable to expect two business applications to use the same Customer and Transaction classes, it's unreasonable to expect them to use the same user interfaces.
This is a violation of the Mixed Domain Coupling Avoidance Principle:
Component in a more reusable layer shouldn't depend on components in less reusable layers.
A special case of this principle is the Presentation-Business Logic Separation Principle:
Business logic should be independent of presentation logic
Our example violates this principle, too, because CustomerView is concerned with presentation logic—how to display a customer object—while Transaction is concerned with business logic—how to process a sale.