In my organisation we have a complex product card with lots of different properties. I could use Steam product card to visualize what I'm talking about: http://store.steampowered.com/app/219740/ (PS: Awesome game, check it).
Product card representation consists of properties such as title, description, price and associations like screenshots, reviews, ratings, tags etc.
Segments of product are used in different parts of application - for example you can find tag lists in user library (where you don't need screenshots).
How would you structure read model here?
a) Try to create small, generic view models (Screenshot, Tag) and composite them in concrete view (ProductCard, UserLibrary)?
b) Create one, god Product view model that'll contain every property that is related to product? (performance-wise - doesn't sound very good)
c) Create property tailored view models for each view? If so, how can I avoid code duplications (we use parts of product on EVERY page) if I have to re-use some specific parts (product title, price etc) all across application?
d) ?
I cannot use event listeners as projectors since product state is changed via legacy CRUD application which we cannot modify - we rely on shared database.
The answer is...
Create property tailored view models for each view
Why? Because it's the simplest and the most maintainable solution. In a read context, you're just dealing with read-only data. You don't need encapsulation or granular representation (a specific model for 'Screenshot' or 'Tag'). That doesn't mean you can't reuse any of the other view models if you already have them and they have the same data, but the main principle here is to create a view model to serve a particular view only.
Duplication doesn't exist in this context, because DRY refers to (same context) behaviour not data.
Why do you want to avoid code duplication ? Or more specifically why do you want to avoid code duplication in different bounded context ;)... If you create dependencies only based in avoiding code duplication you will create a wrong abstraction (not related to a valid use case).
I will quote Sandi Metz :
duplication is far cheaper than the wrong abstraction
prefer duplication over the wrong abstraction
Find more here about wrong abstraction
Related
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
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.
I'm writing an application to help diabetics manage their condition. Information that is tracked includes blood sugar results, nutrition, exercise, and medication information.
In similar applications these entries are all presented in a single table view even though each type of entry has different fields. This data is manually tracked by many diabetics in a logbook, and I'm looking to keep that paradigm.
Each entry has some common information (timestamp, category, and notes) as well as information specific to each entry type. For instance, meal entries would have detailed nutrition information (carb counts, fiber, fat, etc), medication entries would indicate which medication and dosage, etc.
I've considered two different approaches but I'm getting stuck at both a conceptual level and a technical level when attempting to implement either. The first approach was to create an abstract entity to contain all the common fields and then create entities for each log entry type (meals, meds, bg, etc.) that are parented to the abstract entity. I had this all modeled out but couldn't quite figure out how to bind these items to an array controller to have them show up in a single table view.
The second approach is to have one entity that contains the common fields, and then model the specific entry types as separate entities that have a relationship back to the common record (sort of like a decorator pattern). This was somewhat easier to build the UI for (at least for the common field entity), but I come to the same problem when wanting to bind the specific data entities.
Of course the easiest approach is to just throw all the fields from each different entry type into one entity but that goes against all my sensibilities. And it seems I would still run into a similar problem when I go to bind things to the table view.
My end goal is to provide an interface to the user that shows each entry in chronological order in a unified interface instead of having to keep a separate list of each entry type. I'm fine with adding code where needed, but I'd like to use the bindings as much as possible.
Thanks in advance for any advice.
Don't get bogged down with entity inheritance. You shouldn't use it save duplicate attributes like you would with classes. It's major use is allow different entities to be in the same relationship. Also, entity inheritance and class inheritance don't have to overlap. You can have a class inheritance hierarchy without an entity inheritance hierarchy.
I'm not sure I understand exactly what you really need but here's some generic advice: You shouldn't create your data model based on the needs of the UI. The data model is really a simulation of the real-world objects, events or conditions that your app deals with. You should create your data model first and foremost to accurately simulate the data. Ideally, you should create a data model that could be used with any UI e.g. command-line, GUI, web page etc.
Once your model is accurately setup, then whipping up the UI is usually easy.
I often have the same trouble when I have to design my class for a web application. The requirements are :
- maintainable (no copy-paste for instance)
- layers fully separated (the business layer doesn't have to know which method of the data layer is used)
- high performance : don't load useless data.
First I have a table with all my customers and their addresses :
Code :
Customer
--Id
--Name
--Address
----City
----ZC
----Street
Now I want a table (in another page) with all my customers and the books that they bought, I have a few possibilities :
1/ I create a new class :
Code :
CustomerWithBooks
--Id
--Name
--Books[]
----ID
----name
PRO : I load only the useful data
CONS : I build my class after my UI , and there is copy-paste.
2/ I add Books[] to the first class.
PRO : Everything is in the same class, it's maintainable
CONS : I load the address for nothing. If I don't load the address I can : lazy loading, but I really don't like it, or when I use my class I have to know which method of my DAL i called, and I don't like it.
3/ I use inheritance :
Code :
ClientBase
--ID
--Name
ClientWithBooks : ClientBase
--Books[]
ClientWithAdress : ClientBase
--Address
PRO: really maintenable, and I don't load data for nothing
CONS : What do I do if in one UI I want to show the Books AND the Address ?
4/ ?? I hope there is a perfect solution
You option 1 is close to good, assuming I understand it correctly. A customer and a book are two completely different things. You want that data/functionality separate, and should not inherit from any common base class (that you have made).
As the "Con" you say: I build my class after my UI , and there is copy-paste.
A. If you mock up some UI to help clarify requirements before you settle on your design and code up classes, that's good, not bad.
B. Good arrangement of your domain objects helps eliminate copy/paste, not cause it. If you have some seemingly repetitive code within your well-arranged classes (often data access code) that's typical, don't worry. You can address with with a good data-access layer/tool, good shared logging resources, etc. Repetitive code within your classes just means you have more design improvement to do, not that having separate classes for all your domain realities is bad.
On the page where you need to deal with both customers and books, you will use customer objects and book objects, and probably a books collection object. And depending on how your db/object-model are set up, you might be dealing with other objects to get form customer to the books they bought. For example, the customers probably buy 1 or more books at the same time, and these are tied to an Order object, which has a reference to a customer. So, you'll probably go from a
Customer to an
Orders collection containing all of that customers orders to the individual
Order objects and from there to a corresponding
Books collection containing all the
Book objects that relate to that Order object.
None of these need to inherit from each other. Now, let's say getting all the books bought by a customer is something you do a lot, and you want to streamline that. You then want to have a Books collection directly off of Customer that gives you that, though the sql queries you use to get those books still goes through Orders in the db. You must start with your object model (and tables behind the scenes) reflecting reality accurately. Even if this give you seemingly many classes, it is more simple in the end. You might end up with some inheritance, you might not.
I would to avoid 2 and 3, because it locks you into a restrictive hierarchy that doesn't really meet your needs. As you point out, there could be any combination of things that you want, such as customers and their books, and maybe their address, and maybe their ordering history. Or maybe you'll want a book with it's list of customers. Since your underlying business information is not really hierarchical, you should try to avoid making your object model unnecessarily hierarchical. Otherwise, you will build in restrictions that will cause you a lot of headaches later, because you can't think of all the scenerios now.
I think you're on the right track with 1. I would say to create some basic classes for Customers and Books, and then create a CustomerBook association class that contains an instance both the customer and the book. Then you can have you methods worry about how to load the data into that list for a given scenerio.
I would stick the address into Customer, and have a separate collection of books.
Bookshelf
--Books[]
This way, a Customer doesn't have, but can have, one or more books associated to him. PHP-code example following:
class BookshelfFactory {
public static function getBookshelf(Customer $customer) {
// perform some fetching here
return $bookshelf;
}
}
You're sort of designing backwards from an OOA&D standpoint. It's normal to use data-driven design at the persistence (usually a relational database) layer. But in OOA&D it's more normal to think of the messages an object will send and receive (you model an object's methods not its members). I would think about it this way:
Customer
+getBooks():List<Book>
+getAddress():Address
I think your problem is an issue for the implementation of your data mapping layer.
You can have highly performant queries with JOINS that return you the Customers as well as their Books.
Your mapping layer maps this into the appropriate unique objects and is responsible for creating the right 1-many aggregation for your objects.
In addition you could cater for shallow loading, for display properties to save unnecessary amounts of data to be transferred where you only need a few attributes per object.
A lot of the time I will have a Business object that has a property for a user index or a set of indexes for some data. When I display this object in a form or some other view I need the users full name or some of the other properties of the data. Usually I create another class myObjectView or something similar. What is the best way to handle this case?
To further clarify:
If I had a class an issue tracker and my class for an issue has IxCreatedByUser as a property and a collection of IxAttachment values (indexes for attachment records). When I display this on a web page I want to show John Doe instead of the IxCreatedByUser and I want to show a link to the Attachment and the file name on the page. So usually I create a new class with a Collection of Attachment objects and a CreatedByUserFullName property or something of that nature. It just feels wrong creating this second class to display data on a page. Perhaps I am wrong?
The façade pattern.
I think your approach, creating a façade pattern to abstract the complexities with multiple datasources is often appropriate, and will make your code easy to understand.
Care should be taken to create too many layers of abstractions, because the level of indirection will ruin the initial attempt at making the code easier to read. Especially, if you feel you just write classes to match what you've done in other places. For intance if you have a myLoanView, doesn't necessarily you need to create a myView for every single dialogue in the system. Take 10-steps back from the code, and maybe make a façade which is a reusable and intuitive abstraction, you can use in several places.
Feel free to elaborate on the exact nature of your challenge.
One key principle is that each of your classes should have a defined purpose. If the purpose of your "Business object" class is to expose relevant data related to the business object, it may be entirely reasonable to create a property on the class that delegates the request for the lookup description to the related class that is responsible for that information. Any formatting that is specific to your class would be done in the property.
Here's some guidelines to help you with deciding how to handle this (pretty common, IMO) pattern:
If you all you need is a quickie link to a lookup table that does not change often (e.g. a table of addresses that links to a table of states and/or countries), you can keep a lazy-loaded, static copy of the lookup table.
If you have a really big class that would take a lot of joins or subqueries to load just for display purposes, you probably want to make a "view" or "info" class for display purposes like you've described above. Just make sure the XInfo class (for displaying) loads significantly faster than the X class (for editing). This is a situation where using a view on the database side may be a very good idea.