Modelling Related Objects - oop

I'm designing an application which deals with two sets of data - Users and Areas. The data is read from files produced by a third party. I have a User class and an Area class, and the data is read into a Users array and an Areas array (or other appropriate memory structure, depending on the technology we go with).
Both classes have a unique ID member which is read from the file, and the User class contains an array of Area IDs, giving a relationship where one user is associated with many Areas.
The requirements are quite straightforward:
List of Users
List of Areas
List of Users for Specified Area
List of Areas for Specified Users
My first thought was to leave the data in the two arrays, then for each of the requirements, have a seperate method which would interrogate one or both arrays as required. This would be easy to implement, but I'm not convinced it's necessarily the best way.
Then I thought about having a 'Get Areas' method on the User class and a 'Get Users' member on the Area class which would be more useful if for example I'm at a stage where I have an Area object, I could find it's users by a property, but then how would a 'Get Users' method on the Area class be aware of/have access to the Users array.
I've had this problem a number of times before, but never really came up with a definitive solution. Maybe I'm just making it more complicated than it actually is. Can anyone provide any tips, URLs or books that would help me with this sort of design?
UPDATE:
Thank you all for taking your time to leave some tips. Your comments are very much appreciated.
I agree that the root of this problem is a many-to-many relationship. I understand how that would be modelled in a relational database, that's pretty simple.
The data I receive is in the form of binary files from a third party, so I have no control over the structure of these, but I can store it whichever way is best when I read it in. It is a bit square pegs in round holes, but I thought reading it in then storing it in a database, the program would then have to query the database to get to the results. It's not a massive amount of data, so I thought it would be possible to get out what I need by storing it in memory structures.

this is really a many-to-many relationship,
User <<--->> Area
break it up into 3 objects, User, Area, and UserArea:
User: Id, name, etc.
Area: Id, name, etc.
UserArea: UserId, AreaId

Very basic, but the idea is:
struct/class Membership
{
int MemberID;
int userID;
int areaID;
}
This class implements the "user belongs to area" membership concept.
Stick one of these for each membership in a collection, and query that collection for subsets that meet your requirements.
EDIT: Another option
You could store in each Member a list of Areas, and in each Area, a list of Members.
in Area:
public bool addMember(Member m)
{
if (/*eligibility Requirements*/)
{
memberList.add(m);
m.addArea(this);
return true;
}
return false;
}
and a similar implementation in Member (without the callback)
The advantage of this is that it's pretty easy to return an iterator to walk through an Area and find Members (and vice versa)
The disadvantage is that it's very tightly coupled, which could cause future problems.
I think the first implementation is more LINQ friendly.

Does an area belong to multiple users? If yes, it's a technically a many-to-many relationship. If you were to transform the data into a relational database, you'd create a table with all the relationships. I guess if you want to work with arrays, you could create a third array. Or if you actually want to do this in an OO way, both classes should have arrays of pointers to the associated areas/users.

I'm sorry, but this is not an object-oriented problem. It is a relational problem. Hence all the references to cardinality (many-to-many). This is relational database modeling 101. I don't mean to criticize Gavin, just to point out a new perspective.
So what good is my rant. The answer should be to integrate with a relational data store, not to pound it into a object oriented paradigm. This is the classic square peg, round hole issue.

Why not use DataTables with relations, if .NET is involved? You may want to look into Generics as well, again, if .NET is involved.

Agree with dacracot
Also look at DevExpress XPO

One option is to use a dictionary for each of the last 2 requirements. That is, a Dictionary<Area, List<User>> and a Dictionary<User, List<Area>>. You could build these up as you read in the data. You might even wrap a class around these 2 dictionaries, and just have a method on that class for each of the requirements. That would allow you to make sure the dictionaries stay in sync.

Related

How does one architect an entity in Core Data with a generic relationship?

Say you need to architect an app with an entity that can be associated with multiple other kinds of entities. For example, you have a Picture entity that can be associated with a Meal entity, a Person entity, a Boardroom entity, a Furniture entity, etc. I can think of a number of different ways to address this problem, but -- perhaps because I'm new to Core Data -- I'm not comfortable with any of them.
The most obvious approach that comes to mind is simply creating a relationship between Picture and each entity that supports associated pictures, but this seems sloppy since pictures will have multiple "null pointers."
Another possibility is creating a superentity -- Pictureable -- or something. Every entity that supports associated pictures would be a subentity of Pictureable, and Picture itself would have a one-to-one with Pictureable. I find this approach troubling because it can't be used more than once in the context of a project (since Core Data doesn't support multiple inheritance) AND the way Core Data seems to create one table for any given root entity -- assuming a SQLite backing -- has me afeard of grouping a whole bunch of disparate subentities under the umbrella of a common superentity (I realize that thinking along these lines may smack of premature optimization, so let me know if I'm being a ninny).
A third approach is to create a composite key for Picture that consists of a "type" and a "UID." Assuming every entity in my data model has a UID, I can use this key to derive an associated managed object from a Picture instance and vice versa. This approach worries me because it sounds like it might get slow when fetching en masse; it also doesn't feel native enough to me.
A fourth approach -- the one I'm leaning towards for the app I'm working on -- is creating subentities for both Picture and X (where X is either Meal, Person, Boardroom, etc.) and creating a one-to-one between both of those subentities. While this approach seems like the lesser of all evils, it still seems abstruse to my untrained eye, so I wonder if there's a better way.
Edit 1: In the last paragraph, I meant to say I'm leaning towards creating subentities just for Picture, not both Picture and X.
I think the best variations on this theme are (not necessarily in order):
Use separate entities for the pictures associated with Meal, Person, Boardroom, etc. Those entities might all have the same attributes, and they might in fact all be implemented using the same class. There's nothing wrong with that, and it makes it simple to have a bidirectional relationship between each kind of entity and the entity that stores its picture.
Make the picture an attribute of each of the entity types rather than a separate entity. This isn't a great plan with respect to efficiency if you're storing the actual picture data in the database, but it'd be fine if you store the image as a separate file and store the path to that file in an attribute. If the images or the number of records is small, it may not really be a problem even if you do store the image data in the database.
Use a single entity for all the pictures but omit the inverse relationship back to the associated entity. There's a helpful SO question that considers this, and the accepted answer links to the even more helpful Unidirectional Relationships section of the docs. This can be a nice solution to your problem if you don't need the picture->owner relationship, but you should understand the possible risk before you go down that road.
Give your picture entity separate relationships for each possible kind of owner, as you described in the first option you listed. If you'll need to be able to access all the pictures as a group and you need a relationship from the picture back to its owner, and if the number of possible owner entities is relatively small, this might be your best option even if it seems sloppy to have empty attributes.
As you noticed, when you use inheritance with your entities, all the sub-entities end up together in one big table. So, your fourth option (using sub-entities for each kind of picture) is similar under the hood to your first option.
Thinking more about this question, I'm inclined toward using entity inheritance to create subentities for the pictures associated with each type of owner entity. The Picture entity would store just the data that's associated with any picture. Each subentity, like MealPicture and PersonPicture, would add a relationship to it's own particular sort of owner. This way, you get bidirectional Meal<->MealPicture and Person<->PersonPicture relationships, and because each subentity inherits all the common Picture stuff you avoid the DRY violation that was bugging you. In short, you get most of the best parts of options 1 and 3 above. Under the hood, Core Data manages the pictures as in option 4 above, but in use each of the picture subentities only exposes a single relationship.
Just to expand a bit on Caleb's excellent summation...
I think it's important not to over emphasize the similarities between entities and classes. Both are abstractions that help define concrete objects but entities are very "lightweight" compared to classes. For one thing, entities don't have behaviors but just properties. For another, they exist purely to provide other concrete objects e.g. managed object context and persistent stores, a description of the data model so those concrete objects can piece everything together.
In fact, under the hood, there is no NSEntity class, there is only an NSEnitity***Description*** class. Entities are really just descriptions of how the objects in an object graph will fit together. As such, you really don't get all the overhead an inefficiency of multiplying classes when you multiply entities e.g. having a bunch of largely duplicate entities doesn't slow down the app, use more memory, interfere with method chains etc.
So, don't be afraid to use multiple seemingly redundant entities when that is the simplest solution. In Core Data, that is often the most elegant solution.
I am struggling with esactly this dilemma right now. I have many different entities in my model that can be "quantified". Say I have Apple, Pear, Farmer for all of those Entities, I need a AppleStack, PearStack, FarmerGroup, which are all just object+number. I need a generic approach to this because I want to support it in a model editor I am writing, so I decided I will define a ObjectValue abstract entity with attributes object, value. Then I will create child entities of ObjectValue and will subclass them and declare a valueEntity constant. this way I define it only once and I can write generic code that, for example, returns the possible values of the object relationship. Moreover if I need special attributes (and I actually do for a few of those) I can still add them in the child entities.

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 model value object relationships?

context:
I have an entity Book. A book can have one or more Descriptions. Descriptions are value objects.
problem:
A description can be more specific than another description. Eg if a description contains the content of the book and how the cover looks it is more specific than a description that only discusses how the cover looks. I don't know how to model this and how to have the repository save it. It is not the responsibility of the book nor of the book description to know these relationships. Some other object can handle this and then ask the repository to save the relationships. But BookRepository.addMoreSpecificDescription(Description, MoreSpecificDescription) seems difficult for the repository to save.
How is such a thing handled in DDD?
The other two answers are one direction (+1 btw). I am coming in after your edit to the original question, so here are my two cents...
I define a Value Object as an object with two or more properties that can (and is) shared amongst other entities. They can be shared only within a single Aggregate Root, that's fine too. Just the fact that they can (and are) shared.
To use your example, you define a "Description" as a Value Object. That tells me that "Description" with multiple properties can be shared amongst several Books. In the real-world, that does not make sense as we all know each book has unique descriptions written by the master of who authored or published the book. Hehe. So, I would argue that Descriptions aren't really Value Objects, but themselves are additional Entity objects within your Book Aggregate Root Entity boundery (you can have multiple entities within a single aggregate root's entity). Even books that are re-released, a newer revision, etc have slightly different descriptions describing that slight change.
I believe that answers your question - make the descriptions entity objects and protect them behind your main Book Entity Aggregate Root (e.g. Book.GetDescriptions()...). The rest of this answer addresses how I handle Value Objects in Repositories, for others reading this post...
For storing Value Objects in a repository, and retrieving them, we start to encroach onto the same territory I wrestled with myself when I went switched from a "Database-first" modeling approach to a DDD approach. I myself wreslted with this one, on how to store a Value Object in the DB, and retrieve it without an Identity. Until I stepped back and realized what i was doing...
In Domain Driven Design, you are modeling the Value Objects in your domain - not your data store. That is the key phrase. It means you are not designing the Value Objects to be stored as independant objects in the data store, you can store them however you like!
Let's take the common DDD example of Value Objects, that being an Address(). DDD presents that an Mailing Address is the perfect Value Object example, as the definition of a Value Object is an object of who's properties sum up to create the uniqueness of the object. If a property changes, it will be a different Value Object. And the same Value Object 9teh sum of its properties) can be shared amongst other Entities.
A Mailing Address is a location, a long/lat of a specific location on the planet. Multiple people can live at the address, and when someone moves, the new people to occupy the same Mailing Address now use the same Value Object.
So, I have a Person() object with a MailingAddress() object that has the address information in it. It is protected behind my Person() aggregate root with get/update/create methods/services.
Now, how do we store that and share it amongst the people in the same household? Ah, there lies DDD - you aren't modeling your data store straight from your DDD (even though, that would be nice). With that said, you simple create a single Table that presents your Person object, and it has the columns for your mailing address within it. It is the job of your Repository to re-hydrate that information back into your Person() and MailingAddress() object from the data store, and to split it up during the Create/Update operations.
Yep, you'd have duplicate data now in your data store. Three Person() entities with the same mailing address all now have three seperate copies of that Value Object data - and that is ok! Value Objects are meant to be copied and destoyed quite easily. "Copy" is the optimum word there in the DDD playbook.
So to sum up, Domain Drive Design is about modeling your Domain to represent your actual business use of the objects. You model a Person() entity and a MailingAddress Value Object seperately, as they are represented differently in your application. You persist them a copied-data, that being additional columns in the same table as your Person table.
All of the above is strict-DDD. But, DDD is meant to be just "suggestions", not rules to live by. That's why you are free to do what myself and many others have done, kind of a loose-DDD style. If you don't like the copied data, your only option is that being you can create a seperate table for MailingAddress() and stick an Identity column on it, and update your MailingAddress() object to have now have that identity on it - knowing you only use that identity to link it to other Person() objects that share it (I personally like a 3rd many-to-many relationship table, to keep the speed of the queries up). You would mask that Idenity (i.e. internal modifier) from being exposed outside of your Aggregate Root/Domain, so other layers (such as the Application or UI) do not know of the Identity column of the MailingAddress, if possible. Also, I would create a dedicated Repository just for MailingAddress, and use your PersonService layer to combine them into the correct object, Person.MailingAddress().
Sorry for the rant... :)
First, I think that reviews should be entities.
Second, why are you trying to model relationships between reviews? I don't see a natural relationship between them. "More specific than" is too vague to be useful as a relationship.
If you're having difficulty modeling the situation, that suggests that maybe there is no relationship.
I agree with Jason. I don't know what your rationale is for making reviews value objects.
I would expect a BookReview to have BookReviewContentItems so that you could have a method on the BookReview to call to decide if it is specific enough, where the method decides based on querying its collection of content items.

DDD: Should everything fit into either Entity or Value Object?

I'm trying to follow DDD, or a least my limited understanding of it.
I'm having trouble fitting a few things into the DDD boxes though.
An example: I have a User Entity. This user Entity has a reference to a UserPreferencesInfo object - this is just a class which contains a bunch of properties regarding user preferences. These properties are fairly unrelated, other than the fact that they are all user preferences (unlike say an Address VO, where all the properties form a meaningful whole).
Question is - what is this UserPreferencesInfo object?
1) Obviously it's not an Entity (I'm just storing it as 'component' in fluent nhibernate speak (i.e. in the same DB table as the User entity).
2) VO? I understand that Value Object are supposed to be Immutable (so you cant cange them, just new them up). This makes complete sense when the object is an address for instance (the address properties form a meaningful 'whole'). But in the case of UserPreferencesInfo I don't think it makes sense. There could be 100 properties (Realistically) There could be maybe 20 properties on this object - why would I want to discard an recreate the object whenever I needed to change one property?
I feel like I need to break the rules here to get what I need, but I don't really like the idea of that (it's a slippery slope!). Am I missing something here?
Thanks
Answer 1 (the practical one)
I'm a huge proponent of DDD, but don't force it. You've already recognised that immutable VOs add more work than is required. DDD is designed to harness complexity, but in this case there is very little complexity to manage.
I would simply treat UserPreferencesInfo as an Entity, and reference it from the User aggregate. Whether you store it as a Component or in a separate table is your choice.
IMHO, the whole Entity vs VO debate can be rendered moot. It's highly unlikely that in 6 months time, another developer will look at your code and say "WTF! He's not using immutable VOs! What the heck was he thinking!!".
Answer 2 (the DDD purist)
Is UserPreferencesInfo actually part of the business domain? Others have mentioned disecting this object. But if you stick to pure DDD, you might need to determine which preferences belong to which Bounded Context.
This in turn could lead to adding Service Layers, and before you know it, you've over-engineered the solution for a very simple problem...
Here's my two cents. Short answer: UserPreferenceInfo is a value object because it describes the characteristics of an object. It's not an entity because there's no need to track an object instance over time.
Longer answer: an object with 100+ properties which are not related is not very DDD-ish. Try to group related properties together to form new VOs or you might discover new entities as well.
Another DDD smell is to have a lot of set properties in the first place. Try to find the essence of the action instead of only setting the value. Example:
// not ddd
employee.Salary = newSalary;
// more ddd
employee.GiveRaise(newSalary);
On the other hand you may very well have legitimate reasons to have a bunch of properties that are no more than getters and setters. But then there's probably simpler methods than DDD to solve the problem. There's nothing wrong with taking the best patterns and ideas from DDD but relax a little of all the "rules", especially for simpler domains.
I'd say a UserPreferenceInfo is actually a part of the User aggregate root. It should be the responsibility of the UserRepository to persist the User Aggregate Root.
Value objects only need to be newed up (in your object model) when their values are shared. A sample scenario for that would be if you check for a similar UserPreferenceInfo and associate the User with that instead of Inserting a new one everytime. Sharing Value Objects make sense if value object tables would get to large and raise speed/storage concerns. The price for sharing is paid on Insert.
It is reasonable to abstract this procedure in the DAL.
If you are not shraing value objects, there is nothing against updating.
As far as I understand, UserPreferenceInfo is a part of User entity. Ergo User entity is an Aggregate root which is retrieved or saved using UserRepository as a whole, along with UserPreferenceInfo and other objects.
Personally, I think that UserPreferenceInfo is entity type, since it has identity - it can be changed, saved and retrieved from repository and still be regarded as the same object (i.e. has identity). But it depends on your usage of it.
It doesn't matter IMHO how object is represented in the DAL - is it stored in a separate table or part of other table. One of the benefits of DDD is persistence ignorance and is ususally a good thing.
Of course, I may be wrong, I am new to DDD too.
Question is - what is this UserPreferencesInfo object?
I don't know how this case is supported by NHibernate, but some ORMs support special concepts for them. For example DataObjects.Net include Structures concept. It seems that you need something like this in NH.
First time ever posting on a blog. Hope I do it right.
Anyway, since you haven't showed us the UserPreferencesInfo object, I am not sure how it's constructed such that you can have a variable number of things in it.
If it were me, I'd make a single class called UserPreference, with id, userid, key, value, displaytype, and whatever other fields you may need in it. This is an entity. it has an id and is tied to a certain user.
Then in your user entity (the root I am assuming), have an ISet.
100 properties sounds like a lot.
Try breaking UserPreferenceInfo up into smaller (more cohesive) types, which likely/hopefully are manageable as VOs.

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.