Deep class composition and the Law of Demeter - oop

Evening. I'm having trouble finding an appropriate design pattern for some situations of deep composition. Let me present an example.
Let's say we have a class of type Corporation that has many classes of type Subsidiary that have many classes of type Department that in type contain many classes of type Unit that in turn contain many classes of type Employee.
Now, suppose the use case is to count the number of employees for each corporation. I could loop through each corpration, loop again for each subsidiary, and so on and so forth, in something that would result in a nested loop, 4 levels deep. Plus, I would be breaking the Law of Demeter by referencing my class chain several levels below, something that is so tightly couped it would break the very moment I modified my chain.
Another thing I could do is add tons (ok maybe not tons, but a few) of shortcut references. For example, a corporation could itself ALSO contain a list of Employees resulting in never having to walk through the chain to count them. This way, classes are less tightly coupled (but are they?) and the issue now becomes how to keep the Employee list synced for both the Corporation and the Unit. I could use the Observer pattern to keep them updated I suppose but I really feel something's horribly wrong with this idea or, at the very least, I'm not really using the best solution out there.
As I'm pretty sure this is an extremely common domain, could anyone be kind enough as to point me to an appropriate design pattern?
Thanks.

I don't exactly get the second question but I am answering the first question.
As the Law of Demeter states that each entity should have least
knowledge about other units
So using that principle in your design
class Corporation{
//All the stuff about corporation
//Don't ask for what's inside corporation
public int countEmployees(){
//will apply the logic needed to calculate
}
}
Better Client code with Law of Demeter:
corporationInstance.countEmployees(); //let the corporation handle how to count and not expose inner details
Without Law of Demeter
corporationInstace.getSubsidiaries().getSomethingElse()..... //exposing the inner details of class which creates a chain that is bad.
UPDATE:
Using the above stated solution you can go in as many depths as you want by creating the countEmployees() method inside Subsidiaries and in Unit as required. There is no point in breaking the encapsulation or using Observer pattern here.
Apply the Tell Don't ask principle as you have pointed in the comment yourself and delegate the responsibility of calculating the actual employees on the class that contains employees.
Department - > uses count method on subsidiaries to add their count
Subsidiaries - > uses Units to count
Unit - > Uses employees to count

Say you want to email the customer from a link or button. You might write it like customer.getSomeParticularContactInfo(addressType).sendEmail() or customer.sendEmail() which then (inside Customer) calls getSomeParticularContactInfo("primary").sendEmail().
You are on the wrong way. This breaks Single Responsibility, I mean, Customer Object doesn't need to know, how can send E-mail, Customer object is responsible only for how to provide the e-mail address belongs to the customer. So for this functionality, you need to create another Interface like Notifier and an EmailNotifier what implements Notifier. Thereafter you will call EmailNotifier.notify(customer)

Related

How to model a non member aggregate in UML class diagram

In the below UML diagram, Account has an aggregation of Orders. Based on most online resources, this would typically mean Account class has something similar to a List as an instance.
But in reality, for a real world web app with persistent storage, that is not usually how the Account Class would be. It won't have a list of orders as instance. Instead some other controller class will just query a datastore asking for all Orders belonging to an Account. So in a UML class diagram for such an app, is this still the right way to represent relations? The cardinality and maybe the concept of aggregation looks right from a database entity perspective. Just that the diamond makes no sense from a Class perspective.
Or should it show a DataStore/DataManager with a getOrdersForAccount() method and connect it to Account class and Orders class through a dependency relation (dotted line with arrow) ?
This depends on what you want to represent.
The class model you have already would be sufficient as a logical domain model, expressing the logical relationships between entities in your domain. This might not be how you implement your software in code precisely, but it will guide you (and others) in understanding the entities and their relationships without getting bogged down in that implementation detail. At this level, your diagram may have a few design choices (strong aggregation for example is arguably a design choice, but it may not be, as is the use of enumerations and keys) but not that many and nothing that really detracts from the underlying logic. If anything, you could loose some design choices here and improve the expression of logic.
What you may also want is to provide a representation of how the OO code is implemented physically as well. This would be an additional class diagram that shows more precisely the implementation detail. You will have far more design choices in this diagram -- whether to use a collection or not for orders (e.g. a list or some other collection type class), what your data access patterns are (Adapters, Managers, ORMs etc.). At this level you will most likely loose the strong aggregate notation, as at this level we are talking about classes referencing each other which is most simply denoted using basic associations. You might want to use arrows and/or dot-notation to indicate end ownership and reference directions so that it's more clear what the relationships between classes are.
So, I think your question is a classic question about levels of abstraction in models and analysis vs design. Thanks for asking it!
The aggregation just means: "if you delete the account you need to delete the orders as well".
I also recommend to just leave the aggregation away (for most cases) since it only adds little extra semantics to your model. In this case it seems obvious to delete the order when the account is deleted. The only thing the aggregation added here is (as in most cases) some confusion or some futile discussions about the worth of that diamond.
If you have a domain where the filled diamond is used it should be documented in the modeling rules. When using the shared aggregation the documentation is even mandatory since there is no semantics per se in the specs (see box on p. 110 of UML 2.5).
It depends on how deep you want to go with UML design.
If you target code generation from UML then you probably need to add the class you mentioned.
It would look a lot like Registry Pattern:
UML Diagram
You can add abstraction so you can change implementation of your DataManager (if your DataManager is third-party then just call the API from DataManagerImplementation).
After that, depending on your implementation, once you have the list, if you need to keep it then add the association Account -> Order, if you can live with the list on the stack then you are good to go.
C++ instanciation example:
DataManagerImplementation *db = new DataManagerImplementation();
// Dependency injection
Account *acc = new Account(db);
Then in 'Account' class:
Account::Account(DataManager *db)
{
// Fetch list at creation
// Here 'orders' could be a member
m_db = db;
vector<Order*> *orders = m_db->GetOrders(this);
}
PS: I also recommend to put arrow (direction) on association/aggregation, otherwise it implies that the association is bi-directional and so that account has a pointer to an order list, and every order also has a pointer to an account, and I am not sure this is needed.
To edit PlantUML: http://www.plantuml.com/plantuml/png/SoWkIImgAStDuN99B4dqJSnBJ4yjyimjo4dDJSqhIIp9pCzJqDMjiLFmBqf9BK9ImuKk05Hcfw2afGHHYIbjfL2McboINsG3bj6oKz1oJoq1iuir79EJyqlpIZIve0m5a566IfYMEgJcfG0T2m00

How to model OO scenario

I recurrently run into an scenario similar to this:
A container business class that models a hierarchy.
A business class that participates in this hierarchy and is aggregated by the aforementioned class.
Let me give you an example.
A Map has Countries. Now the Map should know where each Country is, since its main responsability besides containing all countries is to know the locations and proximity of each. From this point of view, a functionality such as isNeighbour(Country A, Country B) seems like a correct addition to Map. However, each Country should also offer a method to know if a country is nearby. Say spain.isNeighbour(italy). This is indeed useful. Now, if I don't want to duplicate functionality and responsability, what approach should I take?
The current example I am working on is something for my university, each course requires other courses and also blocks the next level ones. The major is the one that contains all courses and dictates which course precedes which. Say I want to add a dependency of a course over another, e.g to take Calculus 2 you need Calculus 1... Should I go calculus.addRequired(calculus2) and then pass it to the major object, or maybe computerScience.addRequired(calculus1, calculus2)...
I don't want to have both alternatives because to me it seems it can lead to error, but at the same time I want each course to be able to answer what are its requirements. I don't really know how to distribute responsabilities correctly.
First thing is, that there is no problem calling each other.
You can have
boolean Map.isNeighbour(Country A, Country B) { return A.isNeighbour(B); }
or
boolean Country.isNeighbour(Country other) { return map.isNeighbour(this, other); }
Second seems to need reference to global map. First makes Map look like simple facade.
Second thing is that you say it is persisted. There also might be good idea to create a service, that will query DB with related parameters. This can be either Map or some repository service. This will also allow you to query with only identities of entities (eg. countryId) instead of full objects.
I believe neither of the solutions is better or worse. Only point of difference is where other developers expect the methods to be located. But when I think about it, this would mean Map will have all responsibilities of Country, thus breaking SRP, especially if it is not call-through to the country method.
I would put the isNeighbour() method into Country.
Country would contain a map of neighbours. And then the container can call this method on the country instance in question.
This way the logic is maintained by the countries, and the container simply delegates to answer the question to them.
In case of courses it is possible that Course-1 is required for Course-2 in Major-1, but not in Major-2. In this case I would introduce another class, e.g. CourseInMajor that would contain the required courses for a given course in a given Major.

OOP: How do I deal with objects that have mutual relations?

Let's say there are two classes related to each other via some relations. For example, a Student maintains a list of the Classes he takes, and each Class has a list of Students taking it. Then I am afraid of letting the Student directly being able to modify its set of Classes, because each modification would have to be followed by a similar modification of a Class's list of Students, and vice versa.
One solution is to have a class whose sole purpose is to keep track of Class-Student relations, say Registrar. But then if some method in Student requires knowledge of its Class list, the Student needs to be passed the Registrar. This seems bad. It seems Student shouldn't have access to the Registrar, where it can also access other Students. I can think of a solution, creating a class that acts as a mediator between Student and Registrar, showing the Student only what it needs to know, but this seems possibly like overkill. Another solution is to remove from Student any method that needs to access its classes and put it instead in Registrar or some other class that has access to Registrar.
The reason I'm asking is that I'm working on a chess game in Java. I'm thinking about the Piece-Cell relations and the Piece-Player relations. If in the above example it wasn't OK for a Student to have access to the Registrar, is it OK here for a Piece to have access to the Board, since a Piece needs to look around anyway to decide if a move is valid?
What's the standard practice in such cases?
If relations can be changed - classes should be decoupled as much as possible, so along with each class create an interface, do not introduce tied relations between classes.
High level of separation you can achieve using intermediate services/helpers which encapsulates logic of communication between classes, so in this case you should not inject one class to an other even both are abstracted by interfaces, basically Student does not know anything about Class, and Class does not know anything about Student. I'm not sure whether such complexity is makes sense in your case but anyway you can achieve it.
Here is you may find a useful design pattern Mediator which can encapsulate interaction logic between two decoupled entities, take a look at it.
With the mediator pattern, communication between objects is
encapsulated with a mediator object. Objects no longer communicate
directly with each other, but instead communicate through the
mediator. This reduces the dependencies between communicating objects,
thereby lowering the coupling.
What I think you have found in your pretty nice example and explanation is that OO does not solve all problems well. As long as the responsibility is well shaped and sharp, everything is fine. And as long each responsibility fits in exactly one bucket (the class), it is pretty easy to design. But here you have a tradeoff:
If I define for each responsibility a separate class, I will get a bloated design that is pretty difficult to understand (and sometimes to maintain).
If I include for each separate responsibility at least one interface, I will get more classes and interfaces than I need.
If I decide that one of the two classes is responsible for the relation as well, this one object has more knowledge than usual about the other.
And if you introduce in each case a mediator or something similar, your design will be more complex than the problem.
So perhaps you should ask the questions:
What is the likelihood that the relation between the 2 objects will change?
What is the likelihood that the relation will exist between more 1 type of objects at each end?
Is that part of the system a highly visible part, so that a lot of other parts will interface it (and therefore will be dependent on it)?
Take the simplest solution that could possibly work and start with that. As long as the solution is kept simple, it is only your code (you don't design a library for others), there are chances that you can change the design later without hassle.
So in your concrete case,
the board field should have access to the whole board XOR
the figure on the field should have the responsibility of moving XOR
there should be an object type (ChessGame?) that is responsible for the overall knowledge about moving, blocking, attacking ...
I do think that all are valid, and it depends on your special "business case" which one is the most valid.

How to better organize a class with a lot of fields?

I am currently implementing something similar to an hospital intra site, where doctors can see info about their patients.
Currently, I have a LOT of info regarding each Client: his full name, date of birth, blood type, where he lives, diseases he had, etc.
My first attempt was something of the form:
class Client {
private string fullName;
private Date dateOfBirth;
...
public Get/Set FullName()
public Get/Set DateOfBirth()
...
}
which is basically putting everything together under the same class.
After a while I decided that maybe I should pack together similar concepts into a more general one. For example, I can encapsulate both userName and password into the same concept -- LoginInfo, for example.
If doing this, should I provide all the getters/setters on the Client class that delegate the work to the correct inner concepts, or should I just put getters for the concepts themselves? The first approach would shield the outside world to the Client class implementation, but then maybe, we wouldn't win that much by having all these innner concepts.
Should code outside the Client class even know the different kinds of concepts that'd use inside it?
Any other idea / approach?
I still don't know much about what methods I'll need to have on the Client class. Maybe if there are a lot, it'd be definetely good idea to use small inner concepts to group similar methods in themselves, instead of having such a loose coupled big class.
The data of Client will all be persisted using a standard database, if that makes any difference.
I would say it is useful to pack related pieces of data into common classes. I would only provide delegating getters/setters in Client for very commonly used properties though (if even then - it should be a case by case decision). If a concept makes sense in the problem domain, it is fine to expose it to the outside world too. Your LoginInfo is a marginal detail in this regard, but disease history, health check results etc. etc. are prime candidates for this.
I would also recommend you check out Martin Fowler's excellent Analysis Patterns, which dedicates a chapter to health care patterns; you may probably get some useful ideas out of it.
Something to consider when deciding how to organize data: are there any requirements for tracking history of data. For example, do you need to know what the patient's address was 5 years ago (in addition to knowing their current address, of course)? If so, making that "historically-sensitive" data its own class, will likely make it easier for you down the road. Of course, some data won't be "historically-sensitive" - date of birth for example. :)
Something else to consider: what data will be shared among patients? If you maintain data about family medical history, should that data be shared among siblings? If so, then encapsulating that data in its own object will save you lots of copy/synchronization pain later.
These aren't the only considerations when analyzing your data. But they're definitely part of the puzzle.

How to solve cross referencess in OOP?

I encountered this a couple of times now, and i wondered what is the OO way to solve circular references. By that i mean class A has class B as a member, and B in turn has class A as a member.
One example of this would be class Person that has Person spouse as a member.
Person jack = new Person("Jack");
Person jill = new Person("Jill");
jack.setSpouse(jill);
jill.setSpouse(jack);
Another example would be Product classes that have some Collection of other Products as a member. That collection could for example be products that people who are interested in this product might also be interested in, and we want to upkeep that list on a per-product base, not on same shared attributes (e.g. we don't want to just display all other products in the same category).
Product pc = new Product("pc");
Product monitor = new Product("monitor");
Product tv = new Product("tv");
pc.setSeeAlso({monitor, tv});
monitor.setSeeAlso({pc});
tv.setSeeAlso(null);
(these products are just for making a point, the issue is not about wether or not certain products would relate to each other)
Would this be bad design in OOP in general? Would/should all OOP languages allow this, or is it just bad practice? If it's bad practice, what would be the nicest way of solving this?
The examples you give are (to me, anyway) examples of reasonable OO design.
The cross-referencing issue you describe isn't an artifact of any design process but a real-life characteristic of the things you're representing as objects, so I don't see there's a problem.
What have you encountered that has given you the impression that this approach is bad-design?
Update 11 March:
In systems that lack garbage collection, where memory management is explicitly managed, one common approach is to require all objects to have an owner - some other object responsible for managing the lifetime of that object.
One example is Delphi's TComponent class, which provides cascading support - destroy the parent component, and all owned components are also destroyed.
If you're working on such a system, the kinds of referential loop described in this question may be considered poor design because there's no clear owner, no one object responsible for managing lifetimes.
The way that I've seen this handled in some systems is to retain the references (because they properly capture the business concerns), and to add in an explicit TransactionContext object that owns everything loaded into the business domain from the database. This context object takes care of knowing which objects need to be saved, and cleans everything up when processing is complete.
It's not a fundamental problem in OO design. An example of a time it might become a problem is in graph traversal, for instance, finding the shortest path between two objects - you could potentially get into an infinite loop. However, that's something you would have to consider on a case-by-case basis. If you know there could be cross-references in a case like that, then code some checks in to avoid infinite loops (for instance, maintaining a set of visited nodes to avoid re-visiting). But if there's no reason it could be a problem (such as in the examples you gave in your question), then it's not bad at all to have such cross-references. And in many cases, as you've described, it's a good solution to the problem at hand.
I do not think this is an example of cross referencing.
Cross referencing usually pertains to this case:
class A
{
public void MethodA(B objectB)
{
objectB.SomeMethodInB();
}
}
class B
{
public void MethodB(A objectA)
{
objectA.SomeMethodInA();
}
}
In this case each object kind of "reaches in" to each other; A calls B, B calls A, and they become tightly coupled. This is made even worse if A and B are in different packages/namespaces/assemblies; in many cases those would create compile time errors as assemblies are compiled linearly.
The way to solve that is to have either object implement an interface with the desired method.
In your case you only have one level of "reaching in":
public Class Person
{
public void setSpouse(Person person)
{ ... }
}
I do not think this is unreasonable, nor even a case of cross-referencing/circular references.
The main time this is a problem is if it becomes too confusing to cope with, or maintain, as it can become a form of spaghetti code.
However, to touch on your examples;
See Also is perfectly valid if this is a feature you need in your code - it is a simple list of pointers (or references) to other items a user may be interested in.
Similarily it is perfectly valid to add spouse, as this is a simple real world relationship that would not be confusing to someone maintaining your code.
I have always seen it as a potential code smell, or perhaps a warning to take a step back and rationalise what I am doing.
As for some systems finding recursive relationships in your code (mentioned in a comment above), these can come up regardless of this sort of design. I have recently worked on a metadata capture system that had recursive 'types' of relationships - i.e Columns being logically related to other columns. It needs to be handled by the code trying to parse your system.
I don't think the circular references as such are a problem.
However, putting all those relationships inside objects may add too much clutter, so you may instead want to represent them externally. E.g. you might use a hash table to store relationships between products.
Referencing other objects is not a real bad OO design at all. It's the way state is managed within each object.
A good rule of thumb is the Law of Demeter. Look at this perfect paper of LoD (Paperboy and the wallet): click here
One way to fix this is to refer to other object via an id.
e.g.
Person jack = new Person(new PersonId("Jack"));
Person jill = new Person(new PersonId("Jill"));
jack.setSpouse(jill.getId());
jill.setSpouse(jack.getId());
I'm not saying it is a perfect solution, but it will prevent circular references. You are using an object instead of a object reference to model the relationship.