I have some code, which I want to present in UML, but I've stuck at one point. Let me tell you something about code's functionality.
I have a workspace in which I can place some Component
s, select them, delete, add new, move etc. I can also connect them according to some rules (there are different types of Component
s available). In order to determine if a group of Component
s can be connected or not, I've implemented some easy mechanism. In this mechanism the following parts appear:
[EDIT: Please note, that "PlausibilityRule" in UML and "ConnectionRule" are the same things - it's my oversight]
ConnectionRule
- get the type of connection, and checks if a collection of Component
s given as a parameter can be connected according to this ConnectionRule
.
ConnectionRulesSet
- has many rules inside. Client asks a set with rules like this: "according to which rules definied in a set, components given as a parameter, can be connected"? ConnectionRulesSet
gives a list of ConnectionRules
as a response. A concrete Connection rules set are exposed only throug interface - Client cannot create an instance of a concrete RulesSet.
RulesSetFactory
- depending on many circumstances, application can use different ConnectionRulesSet
s. That's why I've created a factory which gives a proper implemetation of ConnectionRulesSet
interface depending on specified circumstances.
And now let's take a look at the Client's code:
// list of components which should be verified in terms of connection plausibility:
List<Component> selectedComponents = ... ;
// Get set of rules for normal conditions:
ConnectionRulesSet setOfRules = RulesSetFactory.getRulesSet(NORMAL_SET);
List<ConnectionRule> fulfilledRules = setOfRules.getFulfilledRules(final selectedComponents);
// Do something with fulfilled rules:
for(PlausibilityRule rule : fulfilledRules){
addToAvailableRulesList(rule.getConnectionType().getName()); // display names of connetion types...
}
My problem is, that I'm not sure how to create an UML class diagram for such solution from Client's perspective... How to expose relationships between presented solution and a Client. Client uses actually all: ConnectionRule, RulesSet, RulesSetFactory...
There is one of my ideas below... What do you think? Have you got any better solution?
Sample UML class diagram
1 Answer 1
Alright, I'm going to give this answer a shot - hopefully I've understood everything correctly!
The Diagram
Firstly, let me apologize in advance for the layout (yUML is nice and quick, but lays large diagrams out strangely sometimes). Class diagram (from yUML.me)
As you can see, there aren't that many changes. But there are a few, namely:
Added an aggregation (specifically, a "composition ") from
ConnectionRuleSet
toConnectionRule
.This is more clear, I feel, than the returns list of relation in your original diagram (as a
ConnectionRuleSet
is a set ofConnectionRule
's). The container relationship reflects the aggregation responsibility ofConnectionRuleSet
, but may not explicitly explain the behavioural responsibility of thegetFulfilledRules
method.Removed the uses between
Client
andConnectionRuleSet
.Given the uses relation already in-place in-between
Client
andConnectionRule
directly, adding another uses betweenClient
andConnectionRuleSet
I feel needlessly overcomplicates things. It's clear that aConnectionRuleSet
containsConnectionRule
's (thanks to the composition).Added a
Component
class to the diagram.I'm not 100% sure exactly what a
Component
is in your domain, however I think it might be worth it to include it in the diagram. After all, it is mentioned in methods inConnectionRule
andConnectionRuleSet
. It is not entirely clear from your question what the relation betweenClient
andComponent
should be, I've used aggregation as it seems aClient
contains manyComponent
's.
Other Diagram Notes
Example concrete classes: I think the example concrete classes, such as
ConcreteConnectionRuleSet
,ConcreteRule1
andConcreteRule2
, etc add very little to the diagram. I've included them as they were in the original, but I think the diagram would be much simpler without them.Vector<Component>: Again, included as it was in the original, but I would STRONGLY recommend that you don't tie your design to particular data-structure implementations (this goes for List<Component> too!). Something like
Collection<Component>
, or at a minimum anIList<Component>
would be much better here.
Feel free to go on to yUML and edit the diagram... Below is the code yUML code I used to make it:
[«interface»;RuleSetFactory|+ getRuleSet(rulseSetType : enum)]-.- «instantiates»-.->[«interface»;ConnectionRuleSet|getFulfilledRules(comps : List≤Component≥)]
[«interface»;ConnectionRuleSet]++-[«interface»;ConnectionRule|+ getConnectionType();+ isFulfilledForComponents(comps : Vector≤Component≥)]
[«interface»;ConnectionRule]<-.- uses-.-[Client]
[Client]<>-?-[Component]
[Client]-.-requests RuleSet from-.->[«interface»;RuleSetFactory]
[«interface»;ConnectionRuleSet]^.=[ConcreteConnectionRuleSet]
[«interface»;ConnectionRule]^-.=[ConcreteRule1]
[«interface»;ConnectionRule]^-.=[ConcreteRule2]
PlausibilityRule
the same concept asConnectionRule
? If not: a) What is the difference? and b) Where isConnectionRule
(as opposed toConnectionRulesSet
) in the diagram?ConnectionRulesSet
just an aggregation/composition ofConnectionRule
's? Or is there more responsibility meant by theConnectionRulesSet
having the behavior togetFulfilledRules
?ConnectionRulesSet
(which I believe under most OOP naming conventions would/should be "ConnectionRuleSet
" - It's one set, of zero or moreConnectionRule
's, notConnectionRules
..) - has both a behavioural responsibility (filtering rules), and an aggregation responsibility (being a set of rules)?