can two use cases extend or include each other at the same time?
A extend/include B and B extend/include A
I'm pretty sure the answer is "NO".
You've just described the digital equivalent fo the chicken and egg problem.
Circular references are [almost] always Bad Things (tm). The only place I know it to not be horrible is in the context of a linked list, in which each entry has a pointer to another of its own type.
If (A includes/extends B and B includes/extends A) then A = B
Admitting that if A extends/includes B then A >= B
It seems likely not, though I'm sure you could do it if you went generic [and useless] enough. Do you have a specific example? There are always exemptions to the rules and I'd be curious to see one.
below is the senario for business use case (business modelling) not system use case:
USE Case A: Service Vehicle
Use Case B: Authorise Additional repair
Use Case C: Repair Vehicle
Additional repair could be identified during initial repair.
or repair could be identified as a new repair during service,
in both case, customer authorisation is required?
A extend B and B extend C (authorisation and start of repair identified during service)
C extend B (authorisation for additional repair identified during repair)
It's rare but in the general case, there's nothing that prevents use cases from including/using each other.
the answer is no. extend and include are mutually-exclusive relationship types. Most likely the use-cases are incorrectly factored/separated, or you've misunderstood the extend/include relationship definitions, or both.
given the example you posted (fyi it is better for you to edit the question rather than post an answer that does not answer the original question) i would venture that B extends A and B extends C, since in both cases A and C additional repairs (case B) may be identified.
alternately, use cases A and C could conditionally include use case B
offhand, i would model this as Work On Vehicle, which is a composition of 2 use-cases, Obtain Customer Authorization, and Service Vehicle, where the latter includes any kind of service or repair and requires the output of the former before starting the work. The notion of 'additional repairs' is just another instance of Work On Vehicle.
but i don't know the full business context, so your mileage may vary ;-)
EDIT: you wrote "but in this case: work is being carried out and further authorisation is required during the course of work", but i don't see how that really matters.
the first step is to eliminate the confusion about includes and extends. Try modeling each use-case completely and independently, and then look at what is common to see if includes/extends is warranted
"YES" - Checked the Spec.
I just read through the UML specification section for use cases:
http://www.omg.org/spec/UML/2.1.2/Superstructure/PDF/
There was no rule that would prevent doing this that I could find. Many people may conceptually have a problem with this, but that is ok, as you are just instinctively trying to objectize or structure use cases logically. Use Cases are a behavior (or set) and are not like classes/"objects". We are not talking about Java objects.
Even in Rational Software Modeler (IBM) allows this "circular reference".
In practice and in trying to map this to Java or other Object languages it may not make sense or get confusing.
Related
I'm working on a module for a larger solution.
In this solution they tried in the past to work with DDD.
However that didn't turn out how it should of been because there was no DDD expert. (and there still isn't one present imo.)
Everything was under a single root aggregate, lazy loading was enabled, and so on.
Now for the new module we want to make it better.
However i'm failing to see how i can use DDD without lazy loading and not drain the entire database.
For example i have an object let's call it "B".
B has a flag let's say "AwesomeFlag"
B has children
If one of B's children is Awesome, then B is awesome as well.
If none of B's children is Awesome, then B isn't awesome.
Now if I would not work with DDD; I'd just get B and execute a linq query that check's if one of B's children is awesome without actually retrieving all of the children.
However if i got a domainobject where i am not allowed to perform queries, how can i do this?
Is DDD forcing me to get all of B's children just to get the calculated flag "IsAwesome" to work?
Or how am i supposed to do this correctly in a DDD environment?
A small hint in which direction i need to focus my research on would be appreciated.
UPDATE
As I was a bit broad in what my question is I'd like to rephrase whilst still using the same terms to be consistent.
B is awesome when one of it's children is awesome.
B itself, does not have a flag "awesome" as this is a calculated field based on the children.
B could have quite a few children, with the children each having allot of properties and data, which you do not want to retrieve just to check if one of the children is Awesome.
B has a method ShouldIBecomeADeveloper
If one of B's children is awesome, making B awesome, it should return a boolean "true"
If none of B's children are awesome, making B not awesome, it should return a boolean "false"
Disclaimer: although this is somehow a valid question, it is very broad, thus it may have many different valid answers.
You need to analyze the business requirements regarding the valid states in which the system is allowed to be. For this you need to answer the question: after a child of B becomes awesome, how fast needs B to become awesome as well?
There are two answers:
Immediately, in a strongly consistent matter. This means that the "awesome mutation" of a child of B and the "awesome mutation" of B are performed in an atomic fashion, they are in the same transaction. In this case you must load B and all its children before mutating one of its children awesomeness. The children of B are nested entities inside the B Aggregate.
It can be delayed, eventually changing its awesomeness to match the business rule, that is, the system can be for some time in a temporary invalid state. In this case, the children of B are also Aggregates. You need a way of mutating B when one of its "past childrens" mutate and for this you can use a Saga/Process manager.
In neither of the two cases you don't use lazy-loading, there is not such thing in case of DDD Aggregates. You can't anyway, if you have pure Aggregates, with no dependencies to Repositories (as you should).
B itself, does not have a flag "awesome" as this is a calculated field based on the children.
Even though "awesome" is a calculated field any operation you perform on the child entity has to go through "B" only, as it is the aggregate root. So you could have a state in "B" called numberOfAwesomeChildren and a child can become awesome/not awesome only when some operation happens on it and since all the operations are directed via "B" only, you can update the numberOfAwesomeChildren whenever a child becomes awesome/not awesome.
So "B" is awesome when numberOfAwesomeChildren is greater than zero.
Even this solution won't solve your lazy loading problem, since to perform an operation on a child entity you will end up loading all the child entity. You may have to have a re-look at your design.
Let's say I have class A with associations to classes X, Y, and Z, respectively. I need to indicate that only one of these associations may be instantiated for any given instance of class A (so, an xor constraint). I know how to do this if the constraint is just across two associations. Obviously I can just make three seperate xor constraints (X-Y, X-Z, Y-Z) but I'm wondering if there is a better/cleaner/proper way to do it?
edit: The multiplicity constraints on the respective associations are not the same. Using an abstract class or interface will not work. Furthermore, a note is insufficient. I need to use some sort of formalized structure, preferably something standardized (e.g. by OMG) to express this because I am programmatically processing the model elements (i.e. it isn't just a picture). I understand how the underlying model for UML provides for this facility. It also specifies (though slightly vaguely) how it should be notated. I guess my main issue is, in fact, with finding a tool that allows me to make that notation. I don't think MagicDraw does so. I should have stated these things earlier.
FWIW, I'm using MagicDraw. It would be a nice bonus if the I could do this in a way that MagicDraw actually understood. I can live with it if that isn't possible.
The xor constraint is just a stylized and rather under-specified constraint for the 2-way case.
You can define an explicit constraint (in Complete OCL) as:
context A
inv OnlyAorBorC: A->size() + B->Size() + C->size() <= 1
MagicDraw may allow you to specify a similar contextual Constraint on A.
If "X", "Y" and/or "Z" can be somehow generalized (I mean, if you not doing this puraly for a conditional flow control), you can make an interface (or and abstract class) "I" for example, and make "X", "Y" and "Z" implement this interface. Then, you put an association with multiplicity 1 between A and the interface I.
See the diagram below:
Edit: The example above doesn't work in the case of A having different cardinalities between X, Y and Z. For this case, the only way that I can see is use an UML Constraint to restrict those relationships. You can define a Constraint in UML putting some OCL expression between curly braces. E. g.
Here, account owner is either Person or Corporation and this {xor} is predefined UML constraint.
I'm not sure about the details of your cardinalities requirements but, a combination between this {xor} and the interface example that I gave might be enough. At least it gives you a little bit more of options, like:
If you need to know more about the UML constraints subject, I got this example from uml-diagrams.org: http://www.uml-diagrams.org/constraint.html
Let's say I have class Foo that has an association to some thing(s) that fulfill(s) a role. This role could be fulfilled by either (strictly) one Bar xor any number of Baz. Similarly, the role might be fulfilled by either any number or Bar xor any number of Baz (but a mixed collection is intolerable). Are there reasonable ways to represent these in a class diagram using only associations, classes, and interfaces? I would (really) like to avoid using OCL or constraint elements.
(The reason I would like to avoid these is because we are generating code from our UML. We have already implemented generation that handles associations, classes, and interfaces. Dealing with OCL would be quite the task. Constraint elements wouldn't be so bad but still quite a lot of work.)
I would start with the picture below and create several different versions before deciding which one generates best code (junior-40).
The yellow blocks represent necessary "glue code" needed to straighten your example against your other requirements
Consider creating an abstract class Thing and derive Bar and Baz from it. It abstract the whole role, can contain some own atts and methods if needed and is quite flexible and extendible.
Now Account has an association only with AccountOwner (role "role", as Jim L. has explained in his comment, a role name must be unique in this context).
Note that this does not eliminate the need of some additional restrictions. For example, all linked "roles" should be of the same type. Sometimes is not easy (or even possible) to remove all restrictions. Otherwise we would make complete systems out of class diagram. I agree though, that as much information as possible should be contained in classes, their taxonomies and features (atts, assocs and methods).
EXAMPLE:
EXAMPLE 2 (after comments):
This version overcomes the need to use OCL ant yet keeps the simplicity and flexibility:
Multiplicities are now also derived and refined for each concrete "role". No OCL needed. :)
You add a constraint on the class in OCL:
(self.role->exists(r|r.oclIsType(Bar)) and self.role->notexists(r|r.oclIsType(Baz)) ) or
(self.role->exists(r|r.oclIsType(Baz)) and self.role->notexists(r|r.oclIsType(Bar)))
You can try this out with MDriven Designer.
The reason for introducing OCL (object constraint language) in the UML specification was just this; ability to add constraint not possible or practical to convey with simple cardinality and type information
Could this image help you ? It is extracted from the norm.
Are you thinking of something like the following:
(source: uml-diagrams.org)
Where Account is your Foo, Person is your Bar, and Corporation is your Baz.
You can then specify multiplicity on each of the two associations: [1] for Bar (Person) and [1..*] for Baz (Corporation).
Is it legal to draw up an include relationship between two use cases that are each associated with a different actor?
Yes this is legal, but I think it should not interpreted as #vainolo suggested.
Suppose this scenario
In this case Actor X has direct access to Use Case A and because Use Case B is included by Use case A Actor X also executed the behavior described in Use CAse B
But only Actor Y has direct access Use Case B.
Actor A only has indirect access through Use Case A
At least that is how I interpret it. The UML specs will only tell you this is a valid UML syntax but will not say much about the meaning of such a scenario.
It's completely legal. What this means is that if the including use case calls the included use case, the actor that is connected to this use case is required.
In UML, when drawing a use case diagram, can I include the already included use case? (Or extend the already extended use case?)
Does it make sense? I have such a situation where I think I can include B in A and include C in B; where A, B, C are all use cases.
A ----------------> B ----------------> C
<<include>> <<include>>
Dose it technically make sense?
Technically, it is possible to do what you mentioned, if it fits your scenario. But just remember, use 'include' usually to abstract sequences of steps out of the primary Use Cases that are helpful to the analyst to avoid repetition. This means it comes into picture after you have completed at least the first cut basic flows for all your main Use Cases. The main purpose is to simplify your use-case diagram, not to complicate it.
It depends on whether the usecase A is being called from C directly and not within the scope of B. If A is being used by C directly, then it makes sense to draw that in your C use case and qualify A as included. Else you could ignore.