Class Diagram

Hi guys,
I'm trying to figure out an agregation relation between the admin, librarian and patron entites, all three entities are able to register. The patron and librarian can manage account, reserves books search etc... I have the following. are the agregation relationships correct?

There are a number of things I can point out in the diagram that don't make sense to me but let's start with the aggregation relationships. Please explain the ideas you're trying to convey with these and why you think they are aggregations.

That's not much of an explanation. If I drew two boxes and label one as "Team" and the other one as "Player" I would say that a team is comprised of one or more players. So players are part of a team. I don't see how you can make an analogous statement for your entities.

so the librara can registered a user and so can an admin. The admin can also create and manage the librarian account. The user can do most things that the librarian can do, like reserve books, pay fine, search items,cancel reservation etc.. but he/she cannot delete books. Hope this makes sense.

Let me put it this way then: I told you previously that a UML diagram is a means of communicating design ideas. If those ideas are not conveyed clearly and intuitively by your diagram, then the diagram fails to achieve its purpose. I don't understand what you mean by "the whole-part relationship between the admin <- (librarian/patron)" so both your textual explanation and your diagram fail to communicate your design ideas very well.

Let me give another analogy. If an inspector can inspect many parts, does that mean he aggregates those parts? If an admin can administer multiple accounts, does that mean the admin aggregates these accounts? I don't think so.

This reminds me why I don't like to draw up detailed class diagrams like this early on. They tend to waste a lot of time because you get sucked into focusing on all sorts of "academic" thinking about entity relationships and you lose focus on what you really want to do, which is to design software that does something useful. What is so interesting about admins creating librarian and patron accounts? Why do feel you need to model these relationships? What functionality and aspect of your system's design will modeling these relationships clarify?

Don't just model for the sake of defining arbitrary relationships, model because you have something interesting to communicate to other people who might want to understand what the system does and how it does it.

So are you actually going to have a Librarian class in this system? You mentioned a "User" but there's no such entity in your diagram. Did you mean "Patron" when you wrote "user"? One common error is to try to reflect too much of the real world in your models. This often misleads you because your software system is not made up of real-world objects. It is made up of abstractions. What you need to do is find the abstractions that will be used in your system by using your experience and knowledge of real-world relationships to create analogies within your system. By definition, an analogy is NOT entirely the same as the original thing. The analogy is used to clarify certain aspects. I suspect the abstraction you're really looking for that you can draw analogies with a Librarian or a Patron is something like an Account. It also seems like there needs to be a Permissions or Authorizations abstraction.

That is, an Admin account has the Authority/Permission to manage the Account of a librarian and the Account of a library patron. This is NOT an aggregation association. This might lead me to think that Librarian and Patron do not qualify as full-fledged objects/entities in your design but rather they become simply types that can be assigned to an Account entity. The AccountType abstraction can then be associated with a number of Permissions/Authorities so that anyone who logs in to the system and is associated with a certain type of account will also be associated with a certain set of Permissions/Authorities to system functionality. This would make more sense to me because then, I can start thinking of actual code for AccountType, which would be an enum that had { ADMIN, LIBRARIAN, PATRON } as its different possible values.

This brings me back to the usefulness of diagrams like this. Like I said before, I don't like drawing up detailed class diagrams like you have. If I use them, it's really as "throw away" strawman diagrams. They help me talk through my initial design ideas and help me discover the kind of objects that I might define in my code. Then I'd try to find interesting behavior for these objects. Then I'd go and write some tests and flesh out the design some more in actual code.

Diagrams that go into too much detail waste time, especially when you are in the very early stages of software development. When you write code, you'll often discover flaws in your initial ideas. That's when you need to refactor and revise your design ideas. However, when you invest a lot of time in drawing up detailed diagrams like what you have, there is a natural aversion to throwing out the effort you put into creating these diagrams and starting over or making major revisions to them. This traps you into a vicious cycle of starting out with a poor design, then writing poorly structured code to fit that poor initial design, then making more poor design choices because of this and then writing more bad code. This goes on until you are trapped in a big mess.

The way to make these diagrams really useful is if you can keep them disposable or you make them generic enough that they can be implemented in many different ways in code, thus making them less brittle/more resilient to changes in the implementation. Detailed diagrams like the one you have are more useful when they are drawn up after the fact, when you have a design that has been validated by actual code and tests. Then you can use software that will analyze your code and come up with detailed these UML class diagrams for you.

Thanks, yes that was a mistake, i meant patron. Ok, so you are basically saying to use a generalization relationship and have an abstract class call 'account' then have admin and patron as x2 concrete classes?

The analogy between software development and building construction is often the source of many fallacies and failures in software development. You might think that just because architects draw up detailed diagrams for their creations, then likewise, software "architects" can come up with detailed (UML) diagrams for the software they create as well. The fallacy is that there is an analogous relationship between detailed architectural diagrams for buildings and detailed architectural diagrams for software systems. The key here is the "detailed" part. In an architectural diagram for a building, what is depicted are actual real-world things. A depiction of a beam labeled with certain dimensions in a diagram will have more or less the same shape, dimensions, and intrinsic qualities such as load bearing strength, etc. The diagram depict real things. When you draw a beam that is attached to a column with rivets or bolts, then you go to the construction site, you can see the actual rivets and/or bolts, the beam, and the column that it's attached to.

On the other hand, a UML diagram depicts abstractions. When you draw a line between two boxes in a UML diagram, can you go to your software and see two boxes connected by a line? You won't, right? Instead, you see code that defines classes and fields and methods and then you read the code and understand the logic that represents the associations one class may have with another. The UML diagram only gives you a high-level idea of the relationship. The code is really what embodies the detailed design.

I found Jack Reeves' essays on how Code is Design very insightful. He explains the above ideas really well.

D Anthony wrote:Thanks, yes that was a mistake, i meant patron. Ok, so you are basically saying to use a generalization relationship and have an abstract class call 'account' then have admin and patron as x2 concrete classes?

No. I was saying that perhaps you'd have an enum that defined AccountType as one of {ADMIN, LIBRARIAN, PATRON}. Then an Account class would have a field defined as "type: AccountType" and the AccountType or Account might aggregate a set of Permissions or Authorizations that allowed a user associated with an Account of a certain type to do the things that the Permissions/Authorizations allowed.

Thanks, i get the concept of designing but i would probably find it easier to code it up than to do the design. Thanks for your insight its very helpful. I will go ahead and continue to workout a good design.

If you think that coding is simply banging at your computer keyboard and stringing together a bunch of computer instructions, then you are in for a rude awakening. Coding and designing are very much intertwined. I would say that more than half the effort of "coding" your program is actually should be spent thinking and rethinking about, and revising your design.

Again, I'm very much convinced on the veracity of Jack Reeves' assertion that the CODE is your software's DETAILED DESIGN. That is, you can't write code and not do design. The two activities go hand in hand.

D Anthony wrote:Yes, i get that, i meant i usaully develop from a design that is done by a system analyst whom would have gathered the requirements and model the system.

This is what leads you into the trap I mentioned earlier. Without working with actual code, the best a systems analyst can give you is often a flawed and incomplete design. When development responsibilities are siloed like that, with systems analysts gathering requirements and drawing up UML diagrams for a "design", the tendency to not throw away prior work that has become obsolete because of new discoveries about the system becomes much stronger. To most software development efforts, this becomes a fatal consequence of the organization. There's even a "law" associated with this: see Conway's Law

You will always find out new things downstream that either invalidate or require the reevaluation of prior assumptions and decisions. That's just part of the nature of software development. It's much more fluid and unpredictable than say erecting a building. Even though we borrow terms like "architecture" and "engineering" from seemingly related disciplines, our working materials and products lack much of the predictability and consistency associated with those in other engineering disciplines. Those disciplines deal with concrete and tangible things whereas we deal mostly with abstractions. It's hard to nail down abstractions.

A setup that often works better than Systems Analyst-Systems Designer-Developer is that of Business Analyst-Software Architect-Developer. The software architect provides insight into both sides of the divide between business-minded folks and technical-minded folks. The architect works with the business analysts and provides much needed technical insights in high-level discussions about the business problem. The architect also works with developers to provide technical guidance and make sure that non-technical concerns are addressed by the developers.

I have experience with both setups and have seen the latter produce far better outcomes. The architect, however, can't just sit in an ivory tower and throw technical requirements over the wall to developers. The worst architects are what we call in the industry "Visio Architects." The setup works best if the architect often pairs up with developers to do actual coding, at least twice a week for a few hours. This allows them to see the consequences and direction that their high-level design decisions are taking the software development effort. To work with the code and be part of producing the code allows software architects to also know the detailed design. This allows them to have a deeper understanding of the software system being developed and enhances their ability to see and address potential problems in the bigger and broader picture (the breadth of the system).

As I mentioned earlier on, there are many other potential problems with your design based on what's depicted in that class diagram. Let's take a look at the Patron-PatronRecord part. What is the difference between a Patron and a PatronRecord? A closer look makes me even more confused. The Patron has a name field. The PatronRecord has a dateOfMembership field. Barring mistakes in recording their initial values, both fields are more or less immutable, that is, they don't change over time. The PatronRecord also has email, address, and phone number. Again, these are more or less the same throughout the lifetime of a Patron or at least they change very infrequently. Why are these fields kept separated in two different classes/entities then? Why not keep them all together in one of these, like in Patron?

The maxBookLimit field is somewhat of a mystery. Why is it a field of the PatronRecord entity? Is this value different for each PatronRecord? Isn't this more a matter of policy of the library that applies to *all* patrons? Why would this kind of information need to be kept at the level of each individual PatronRecord? For example, my library allows anyone who has a library card to borrow up to 10 book titles, 5 video titles, and 5 audio recordings at a time. So, at any single time, you can have at most 20 items checked out and recorded against your account.

Then you have the finesOwed field. This looks like a premature optimization to me. Why do you have it as a field in the PatronRecord? This value will change over time. Also, it can be calculated if you have an entity called Fine. A Fine would be created when a borrowed item is returned past its due date. The fine would stay on record as being "outstanding" until it is paid. Once created, a Fine will "live" in the system forever, until the associated Patron is deleted. This implies a few business rules and it also enables some functionality in the system:

1. A patron can view a history of fines he/she has paid over time.
2. The "finesOwed" can be calculated at any time as the total of all fines that are still "outstanding".
3. Upon payment, a receipt can be printed for the patron so that they can see which overdue items they have paid for.

Given the above, I would say that your early design choice to have the finesOwed field in the PatronRecord appears to be flawed. Similar reasons apply to the noBookeIssued [sic] field, which I assume stands for "number of books issued." A number of flaws cascade throughout the diagram from there.

While having these details in the diagram have helped us identify and possibly head off a number of problems with the design, having those details in there also represents time and effort on the part of the person creating the diagram. That time could have probably been spent more wisely by keeping these kind of details out of the diagram until later on in the development process. These kind of UML diagrams are really best kept on a whiteboard, so that you can easily revise them and you don't get too attached to them. Experienced developers know they are almost always wrong.

Thank you for the break down feedback. This is very spot on and you have share some very useful insight that helps me see the flaws in my design. Yes, you are very correct, there is no need for Patron Record entity, this is redundant and yes, it is better to have a fined entity that would perform calculation and thus allow patron to view paid fine etc..

I will now take this feedback and redesign. I may repost the modified version for more feedback.

Many thanks for your help.

D Anthony

Ranch Hand

Posts: 55

posted 4 months ago

Please see the modified version and please let me know your thoughts based off your last comments. Thanks

There is something off about your understanding of "relationships" as depicted by lines between entities on the diagram. Just because an Admin issues a Fine, that doesn't mean you have to model it as a relationship in a class diagram. You seem to be thinking in terms of process and data flow. A class diagram is not meant to communicate that kind of thing.

A class diagram helps to show associations in terms of lifetime and what I suppose can be called "intimacy" -- maybe "affinity" is a better word. Entity associations help you create an "audit trail" of everything that happens in a system. That is, when one object gets created, updated, deleted, or otherwise made to exhibit behavior of some kind, what other objects are created, updated, deleted, or called upon to exhibit some kind of behavior of their own as a consequence?

Working backwards, you can ask "When does a Fine get created?" It gets created when a Book is overdue. (BTW, your diagram still shows that as Books, plural, instead of just Book, singular). When is a Book overdue? When an associated Transaction has a blank dateReturned and the current date is past the Transaction.dueDate or when its dateReturned is past the dueDate. Actually, for purposes of creating a Fine, the dateReturned must be known.

Let's work forward:

1. When a Patron borrows a Book, a Transaction is created. The Transaction records the association between the Patron and the Book by keeping the following information: Patron Id, Book Id, dateBorrowed, dateDue (may be a calculated value based on dateBorrowed and rules for #days a book can be checked out), dateReturned. The cardinality of Patron:Transaction is 1:(0..N). There is also an association between Book:Transaction. There is NO meaningful relationship between Patron and Book. The relationship line between Patron and Book that you show on your diagram is bogus. A Patron requests a Book via a RESERVATION. So, the Patron creates a Reservation which is associated with a Book, or rather, it should be a Title. A Library can have many copies of a Title. I would actually introduce a Title entity and change Book into Item. An Item can have a type, which would be Book, Magazine, Video, Audio, or something else.

2. So, a Patron can reserve a Title by creating a Reservation. The Library will have several Items for that Title. That is, Title:Item is (1:N). When an Item associated with the Title becomes available, the Reservation is updated so that the Patron can be notified that the Reservation has been completed.

3. When the Patron goes to the library to pick up the reserved Item and checks it out, a Transaction is created. The Transaction is a temporal association between the Patron and the Item that was borrowed.

4. If an Item is returned past the dueDate on the Transaction, then a Fine is created. The Fine records this information: Transaction Id, amountOwed, etc. The cardinality of the Transaction:Fine relationship is 1:(0..1). A Transaction can have 0 or 1 Fine associated to it.

5. When the Patron pays a Fine, it may or may not be for the full amount. Each Payment will be associated with a Fine. The Fine will remain outstanding until it is fully paid. Therefore, there can be multiple Payments for each Fine. That is, the cardinality of the Fine:Payment relationship is 1:N. On the other hand, a Payment may also cover multiple Fines. Some Fines covered by a Payment may be covered in full while some may be only partially covered.

While I think these kind of things are challenging and perhaps even fun to do as an exercise, in real-world software development, you shouldn't go into this much detail without first roughly fleshing out the high-level ideas in actual code. You have spent many days working on this diagram already and if this were a real-world project, you would have already wasted a lot of time and money.

If you're just learning about analysis and design, I still think that spending too much time mucking about with diagrams doesn't give you much feedback as to whether or not you're on the right track. Like I said before, coding and designing are very much intertwined activities and you can do one well without the other. Similarly, you can't learn this properly if you don't do it properly.

There are also a number of issues with the methods you assigned to these entities. Again, this stems from your attempt to use a Class Diagram to communicate process and flow.

Look at the Fine class. Why does it have a reportPatron() method? The Payment class, why does it have a change field and setChange/getChange methods? That's not right. There is no need to keep that kind of information in a Payment object. You're getting way ahead of yourself by thinking about the process of paying fines here. That's not the kind of thing you put in a class diagram.

What about the Admin class, why does it have a search() method? That makes no sense.

Why does a Patron have search(), borrowBooks(), payFine(), and printReceipt() methods? Again, these have to do with processes, they have nothing to do with a Patron per se as an entity and its relationships to other entities in this system you are designing.

In a class diagram, if you're going to get into details of methods and fields, it's only useful to include the fields and methods that are directly related to establishing and clarifying relationships between entities/classes. Too much information in the class diagram makes it complicated and harder to read. When you try to communicate too much information, sometimes you end up mis-communicating, misinforming, or worse, misleading, your audience.

Similar problems exist with your depiction of a relationship between the Library and BookDB (what is that anyway?), the Library and LibraryAccount, Patron and BookDB, Patron and Fine.

I don't understand the arrow you have between Patron and Admin either. That kind of arrow is meant to show an inheritance relationship. On your diagram, it says that a Patron is-an Admin. That doesn't make sense.

One more thing. You may or may not have done this intentionally but notice how your Patron class is kind of the central hub for your diagram. This tells me that you probably see a Patron is a key entity in your system design. I would argue otherwise. If this is a Library Reservation system, the key entities are more likely to be things like Title, Item, and Reservation. Everything this system does revolves mainly around these classes. Just because a real-world patron is a key user of your system, that doesn't mean the software representation of a patron is central to your system's design.

I wrote:The relationship line between Patron and Book that you show on your diagram is bogus.

Let me explain this a little bit more. First, let's call it an Item instead of Book, per my comment in a previous reply.

You might think that there is a significant relationship between Patron and Item because in the real world, those are the tangible things you can see and easily relate to. When a Patron leaves the library, they are in physical possession of the Item(s) they borrowed. This kind of thing often leads novice designers down deep rabbit holes. They are often nothing but red herrings. Experienced designers know better. Many real-world relationships like this don't matter in the context of the software system.

In the software system, a Transaction gets created to show that the Patron borrowed one or more Item(s). So, what you should see in the diagram is not [Patron]-----borrows----[Item] but rather [Patron]----completes checkout----[Transaction]----includes/is checked out----[Item]. Read these as "A Patron completes a checkout with a Transaction" and "A Transaction includes one or more Items / An Item gets checked out with a Transaction." Once these relationships are recorded in the software system, it is assumed that the Patron is in fact now in possession of the Item(s) included in the Transaction. Likewise, when a Transaction is changed such that it can be shown that an Item has been returned, then it is assumed that the Patron no longer has physical possession of the Item.

This is why you need to remember that you are not trying to model the real-world in your diagram; you're trying to model the software entities that work together to reflect, in an abstract way, the state of the software system. There's a huge distinction to be made between real-world objects and software objects and the more your remind yourself there is that distinction, the more you can avoid falling into the trap of trying to model the real-world in your UML diagrams.

Also note that the above may even turn out to be somewhat flawed but at least it's a step away from the original [Patron]---borrows---[Item] red herring.

Thank you again for the clear explanation around class diagram and modelling, as you can tell i'm a novice at modelling and you are right my thought process is around 'process and data flow', as migration analyst is my day job i deal with a lot of packages, staging areas and data flow etc. I seems to misunderstand the purpose of a class diagram. Based am are you feedback i will continue to improve the diagram until i get it right. Thanks again.

D Anthony

Ranch Hand

Posts: 55

posted 4 months ago

Junilu Lacar wrote:One more thing. You may or may not have done this intentionally but notice how your Patron class is kind of the central hub for your diagram. This tells me that you probably see a Patron is a key entity in your system design. I would argue otherwise. If this is a Library Reservation system, the key entities are more likely to be things like Title, Item, and Reservation. Everything this system does revolves mainly around these classes. Just because a real-world patron is a key user of your system, that doesn't mean the software representation of a patron is central to your system's design.

Yes, i intentionally modeled this to show the patron as the central hub in the diagram as i believe that without a patron then what is the point of a library, the items, reservation, librarian etc cannot therefore exist without patron.

If you take that view, then Patron or User would be the central entity of every software system in creation because what would be the point of a software system if one of the key beneficiaries wasn't central to its design, right? In my opinion, that's a flawed and dangerous viewpoint to take because it can lead to many wrong decisions just as I have shown it has in your diagrams so far.

Again, hopefully you'll realize that there is a big difference between a main user of a system and a main entity in the system's design. Yes, users play an important role in the larger scheme of things but as far as the class diagram, an entity like User or Patron is often on the periphery, not at the core, of the design. In fact, use case diagrams depict users as external actors who are not even part of the system under consideration.

If there is a "central" or "core" entity in a Library system, I would argue that something like a Catalog would be the most likely candidate. Patron, Librarian, and Admin, not so much. Like I said, these are entities that lie on the periphery. That doesn't mean they are unimportant though. Because they are on the periphery, they are often the starting points of any kind of interesting interaction between entities in the software system. I would say they are catalysts rather than main ingredients. In chemistry, a catalyst is something that starts or enables a reaction to start. Likewise, in a software system, entities like Patron, Library, and Administrator initiate interactions between two or more entities in the software system.

Think about your library's website. What's the key part of that website? When you log in, are you immediately presented with your account information? In my local library's website, as with most websites, things that have to do with a user's account are usually accessible via a small link or icon at the top right of the screen, beside the link to log out of the system. In my library's website, the most prominent and central feature you see after logging in is the Catalog Search feature, just like when you go to www.google.com, you get one input field where you can type in a search term. In fact, you don't even have to be logged in as a patron of the library to use the Catalog Search feature in my library's website. You only need to log in if you want to reserve an item. I think this supports my assertion that the Catalog is the entity with top billing in a library system. User, Patron, Admin, these play the "supporting actor" role.

Think about any other software system you've ever interacted with. After establishing your identity with the system by logging in, is your User information what's presented to you? It's not, right? In a banking system, it's usually a summary of your account positions. In a trading system, it's an overview of your portfolio positions. In an inventory system, it's usually an overview of the stock levels and perhaps a chart that shows demand trends. An airline reservation system would start off by asking you for details about your planned Trip.

I don't know what book you're using as a reference but I would recommend that you get a copy of Eric Evans' book, "Domain-Driven Design". It is a highly-recommended book and while its focus is not on UML diagrams, the discussions in the book will give you many valuable insights into how to think about various entities in your software system.

You might also want to look into Entity-Relationship diagrams first. This is a more high-level diagram that often leads to better and more relevant class diagrams. In fact, I would argue that you should start with an Entity-Relationship diagram to give you a high-level abstract view before you create a Class Diagram, which is more of a low-level implementation view.

D Anthony wrote:Based am are you feedback i will continue to improve the diagram until i get it right.

It's not about getting the diagram right. The only time you can ever truly say a diagram like this is "right" is when it accurately reflects the implemented design of a software system. That is, the diagram is made AFTER you already have a good, working software system and you want to document some of its details.

Trying to get a diagram like this "right" in the sense that you're saying is like to trying to draw a picture of a herd of horses. It's only going to reflect what you imagine the system will look like and the best you'll get is an approximation. The idea that you can get the diagram "right" before you have working software is wishful thinking at best.

As I said very early on, diagrams like these are meant to be used to communicate ideas with other members of the team. As such, there needs to be conversations around those ideas, tests and production code to see if those ideas pan out, and other kinds of diagrams that show other aspects and facets of the software system being developed.

The best a diagram like this can be is "good enough". Good enough to start conversations about other aspects of the system. Good enough to serve as a way to validate how other aspects of the system are viewed. Good enough to serve as the basis for some initial tests and implementations. Don't focus on getting your diagram right, focus on getting your ideas right.