Multiglom HR maintains an internal application to manage its employees (workers).
A couple of use cases require listing all direct and indirect subordinates of an employee. To avoid implementing the iteration logic several times in the application and to ensure that the list order is consistent across the application, the iteration logic shall be implemented only once, close to the aggregate.
The purpose of the subordinate list is to list all direct and indirect subordinates of a worker.
Main Features
- Return all direct and indirect subordinates.
- Return an empty result rather than any exception if a worker has no subordinates.
Table 1. Quality Goals
No. | Quality | Motivation |
---|---|---|
1 | Simplicity | Any arbitrary employee (worker instance) can be queried for its subordinates. |
2 | Consistency | No matter where listing the subordinates of a particular worker, the order should be the same. |
3 | Testability | The design shall encourage testing iteration logic decoupled from the rest of the application. |
In this scenario we want to apply the Iterator Pattern to provide a way to access elements of an aggregate object sequentially without exposing its underlying representation (GoF).
We have identified the Worker as the object that can have subordinates or not. Thus, it is either an aggregate or a leave, and the goal shall be to handle both in the same way.
So, we always return a WorkerIterator instead of null or throwing any exception. The WorkerIterator can transparently handle the case that there is not a single subordinate.
Open IteratorTest.java to start playing with this pattern. By setting the log-level for this pattern to DEBUG in logback.xml you can watch the pattern working step by step.
- As mentioned in the book, while Iterators are quite handy from the usage perspective, they effectively hide potentially important aspects. The client of an Iterator does not (want to) know, how the iteration works, but sometimes this knowledge is crucial. Especially, in conjunction with internal lazy loading or prefetching there can be surprising performance or memory effects.
- The CombinedOrderedItemIterator in the collider package combines multiple iterators. KeyCollisionIterator internally performs an aggregation.
- (GoF) Gamma, E., Helm, R., Johnson, R., Vlissides, J.: Design Patterns – Elements of Reusable Object-Oriented Software. Addison-Wesley (1995).