I would like to draw a UML sketch to communicate part of a software but the type of relationship between classes does not seem very clear cut to me.
Let's say I want to periodically fetch the recent orders from the database and update a graphical view that has the order details.
This is a highly simplified pseudo code example but my implementation is java
//Order objects contain information about a single order
class Order
{
private String orderNumber;
private String buyerName;
public Order(String number, String name)
{
//initialize fields
}
//public getters
}
now I have a class called Model that has a single static function for fetching orders in a time frame:
class Model
{
private Model()
{}
public static List<Order> getOrders(LocalDateTime from, LocalDateTime until)
{
//...get order objects from database and return
}
}
Model.getOrders()
is accessed by my Controller class which is in charge of fetching Order
objects and updating a view periodically
class Controller implements Runnable
{
private RecentOrdersView target; //view to update
private Controller()
{
}
public Controller getInstance(RecentOrdersView input)
{
//...singleton
//compose the returned object with the view, so it needs which view to update
}
public void Run()
{
//... client code runs this function periodically
List<Order> recentOrders = Model.getOrders(...);//get Orders
for(int i=0; i<recentOrders.size(); i++)
{
target.updateView(recentOrders.get(i).getOrderNumebr(),
recentOrders.get(i).getBuyerName());
}
}
}
As you might have guessed there is a class for my view as follows:
class RecentOrdersView
{
private RecentOrdersView()
{
}
public RecentOrdersView getInstance()
{
//...singleton implementation
}
public void updateView(String orderNumber, String buyerName,...)
{
//...update the view based on the parameters
}
}
so the controller and the view are implemented as singletons, but the model is accessed through public static function.
Client code is responsible for putting it together:
class Client
{
public static void main(String[] args)
{
RecentOrderView view = RecentOrdersView.getInstance();
Runnable controller= Controller.getInstance(view);
//schedule controller to run periodically
}
}
Now I want to create a UML diagram for this setup, however I don't know if I should use aggregation or composition between Controller
, Model
and Order
my best guess looks like this:
I have selected composition relationship between Client
and RecentOrdersView
and Controller
, because Client
owns an instance of each. I have also selected an aggregation relationship between RecentOrdersView
and Controller
, because Controller
holds a reference of RecentOrdersView
(even though it does not own it).
where I am confused is the relationships between Order
, Controller
and Model
. Specifics:
Relationship between Model
and Controller
:
I know that Controller
calls a static function in Model
, but since there is no object instances, I am unsure what to do
Relationship between Model
and Order
: I almost want to use composition because Model
instantiates Order
objects, but since this happens in a static function there is no immediate owner, the Order
objects get passed back to Controller
Relationship between Controller
and Order
:
inside Controller
method Run()
is where Order
objects fall out of scope, but Controller
object is not the one that directly instantiated those objects. should I be using composition here?
Thank you for reading this long question. I also highly appreciate advice about the overall design pattern used.
Best Answer
Here is a good explaination on differentiating association, aggregation, and composition.
But here's a thing. If you try to show everything your system is capable of (or every description of your system) on the same diagram, you're going to run out of relationships, or end up reusing the relationship kinds with widely different meaning on the same diagram.
You're showing several different kinds of things on the same single diagram. The order is mostly an informational entity. The model is largely informational as well (it is the collection of orders), but of course, has some low-level (CRUD) behaviors around persistence. Whereas the controller and view are a mostly behavioral entities.
If you choose instead to use more than one diagram may help clarify things both for you and the consumers of your documentation.
For example, I might suggest that a sequence diagram would more effectively illustrate the interaction (the dynamic relationship) between a controller, the model, and an order. (Personally, I would hesitate to describe the controller/order relationship as even a mere association because that relationship is never materialized in a formal way or persisted for any duration.)
An object diagram (or block diagram, rather than a class diagram) can be effective at showing the full-program lifetime (primordial) singletons (objects, sometimes subsystems and modules), like model and its relationship with, say, the top-level controller object. As such these are a good at showing design at the highest level.
A class diagram for showing the composition relationship between model and orders (which I am presuming cannot exist or do not make sense without being in the model).
(Technically, the class diagram relationship between the controller class and order class is via a return type on a method in Model, this is one reason why I would hesitate to describe this as an association between classes controller and order; however, that is probably not all that interesting for a top-level diagram intended to show the system design, especially when you might use another diagram to show that instead.)