Does Alloy have the ability to model a sequence? I could do it manually (i.e create a succeeds relation, and list all the one X where it applies), but imagine there is a more elegant approach.
Does Alloy have the ability to model a sequence?
Yes.
I could do it manually (i.e create a succeeds relation, and list all the one X where it applies),
Yes, and in some cases that is the way you want to go.
but imagine there is a more elegant approach.
As Colonel Thirty Two has already pointed out, util/ordering can be helpful, as can util/seqrel and util/sequence.
But in Alloy 4, the simplest route to sequences is the seq keyword documented on the Alloy website. I believe it was introduced after the second edition of Software abstractions went to press; at least, there's no index entry there for seq.
Related
I want to create a very basic sequence diagram for the first iteration of my app. I have a database of exercises, and I have a use case for creating, another for editing, and another for deleting an exercise. They are all very simple, and use the same elements and actors, like User, DAO, and Database. What I want to do is to create a single SD, that begins with the user asking to create an exercise, followed by the user asking to edit that exercise, and then asking to delete it. My question is: is this considered correct in a sequence diagram? I don't want to create 3 SDs almost identical to one another, and this seems like a simple way to represent all the information, but I don't know if this is correct by UML standards. Thanks.
From a standards conformance point of view, there is nothing in the UML standard, that imposes a relationship between your use case models and sequence diagramme models. So, no matter how many use cases you want to reflect in a sequence diagramme, it would be neither "correct" nor "incorrect".
From a personal point of view : What you are asking about is a question of modeling style, not conformity. As long as the people who are reading your models understand them, you can do whatever you want. So, something like this would be perfectly fine :
I would like to to create a sequence diagram to show some interaction, and then use that sequence diagram as an interaction occurrence (sub-sequence) on other sequence diagrams. The point is I would like to apply the sub-sequence each time to a different object instance that is involved in the interaction in the sub-sequence. In my case the instances are simply various file artifacts. Is there any legitimate way of doing this prescribed by UML?
EDIT: some more clarification of my context:
I have 2 main sequence diagrams where I want to reuse the sub-sequence as an interaction occurrence
on the 1st main sequence there is one file for which the sub-sequence has to be applied 3 times
on the 2nd main sequence there are 3 different files for which the sub-sequence has to be applied 3 times
the files are read by the same object instance
I model reading from a file by a call arrow stereotyped as <<read>> to a on object instance which represents the file.
I need to reference the file somehow in the sub-sequence, but I haven't found a good and simple way of doing this.
Complicated, but formally (almost) correct solution with Collaborations
Just using InteractionUses is not enough, because this doesn't allow you to assign the actual roles in the main interaction to the generic roles of your used interaction.
Collaborations, CollaborationUses and Role Bindings can be used for this.
See my example here:
This defines a Collaboration with generic roles sender, relay and receiver and shows the interaction between them.
You can now use this collaboration in a concrete situation:
Class S uses the Collaboration two times with different role bindings to its parts (A, B and C are assumed to be able to send and receive Sig1).
With these definitions you can now create your main sequence diagram:
Unfortunately, this is not correct UML, even though there is an example in the specification (I filed an Issue https://issues.omg.org/browse/UMLR-768). You will have to fake this notation until the taskforce comes up with a fix. How to fake it, depends on how strict your tool implements the specification.
Advantage: formally correct and versatile solution, backed by an example in the specification
Disadvantage: complicated and difficult to explain, not completely usable, because of a bug in the specification
Basically there are three different ways to specify such situations.
Using a gate. Whith gates you specify the sequence with messages that start or end at a gate that is defined and in most tools (if usable at all) not shown explicitly. Instead it is modelled with messages starting or ending at the interaction border.
Similar as gates are lost and found messages. These are special messages that pass out the control to another sequence or returns from one. Such as in the case before you can define a set of further diagrams specifying the interaction in more details.
Using abstraction, which is my favorit for most of the cases. This means you extract the common interface from the classes and specify the interaction against the interface instead of the concrete classes.
Use an Interaction with Parameters:
Now we would like to reference the Lifelines of the main Interaction in the arguments of the InteractionUse. Unfortunately, in UML this is not possible, since arguments are ValueSpecifications and they cannot reference another modelelement.
However, NoMagic suggested and implemented an additional ValueSpecification, called ElementValue, that does exactly this. I think this would be a valuable addition to UML and hopefully it will be added some day. Up to then, only MagicDraw users can use this solution (as far as I know).
With this non standard element, we can model this:
The connection between the lifelines is now via the arguments for the parameters of the generic interaction. Technically the lifelines would not need to be explicitely covered by the Interaction Use, but I think that it makes sense to do it (shown in my tool with a non standard circle on the border of the Interaction Use).
Advantage:
compact and versatile solution, almost conformant to the standard
Disadvantage:
uses a non standard model element, currently only available to MagicDraw users.
pragmatic non conformant solution with covered lifelines:
The collaboration and parameter solutions allow to specify it (almost) formally correct. However, in many cases, a simplified model would be sufficient. In your case, for example, you only have two participants and they have different types. So, even though there is no formal connection between the lifelines of the used interaction, and those of the main interaction, there would be no ambiguity. You could use the covered attribute of the InteractionUse to specify, which of the lifelines (files) you are targeting at a specific InteractionUse. Could that be the pragmatic solution, you are looking for?
Advantage:
compact solution
Disadvantage:
not conformant to UML, ambiguous in more complicated situations
Particularly interested on the merge right after the decision. Can you have this?
Yes, that's legal, however:
You can combine merge and decision here into a single diamond (that's also legal and more elegant),
You can use loop here instead of your construct (that's even better in your specific example, however not necessarily answers your question).
I'm looking for insight/ papers/ articles, etc. whether a fully declarative Domain Model (as per DDD) is possible.
For example:
Validation can be declarative (lot's of ORMs do this)
business flow logic can be declarative: having a DSL for defining a workflow / Finite State Machine / process manager / DDD Saga (whatever you want to call it) on Crud-operations, through ddd-repositories most likely
decision logic can be declarative. I.e: most of the time this boils down to simple conditionals
derived / calculated fields could be done declaratively but is as bit tricky, especially when this cascades. I.e: you'd have to keep a dependency graph on the calculated fields, etc. Still it can be done.
Any links to people having actually tried that, or some convincing couter-arguments why this can't be done?
p.s.: Please don't answer with "Yes it can be done, since a FSM is Turing-complete with enough memory bla bla"
"Everything is a nail if you hold a hammer"
Instead of asking if it is possible - ask:
What are the reasons I want to do this particular thing declaratively?
Data validation is a nice thing to do declaratively. You have a DTO, you add some attibutes, everything is clear and readable.
Business flow done declaratively... Reminds me of a great failure of Windows Workflow Foundation. Is anyone actually using it?
What is the benefit of making a behaviour-centric components in a declarative way? Imperative way seems to be well-fitted to this.
Decision logic... maybe. But again - why?
"derived / calculated fields could be done declaratively but is as bit tricky"
Why do you want to do tricky things when there is a way of achieving the same result with straightforward things?
So why?
Do you need to change the behaviour of the app in runtime by editing some config file? OK, go for it.
Do you have a generic domain that will be used by many clients and you need some reconfiguration to fit them? Ok, but you need to clearly distinguish the unchangeable core of your domain and the varying stuff. Don't try to make all the things configurable - you'll end up with Inner Platform syndrome.
Do you believe you can make a declarative language your client could use to change his domain without a need for a programmer? No. You will fail. I know a language which was supposed to be like this. An easy, declarative language that ordinary accountants would use to explore their data. It's called SQL :D
I fully concur with Bartłomiej Szypelow's remark. Regardless, I will try to answer your question.
A declarative language always depends on an imperative language for it to work. Take something as simple as arithmetic for example. When we ask for the outcome of 1+1 we first need to know how the 1 should be understood and how in that context the + operator can be calculated before the statement as a whole can be interpreted. This is one of the ways we are able to overcome complexity; you don't need to know how a plus operation is done to be able to use one.
From http://en.wikipedia.org/wiki/Imperative_programming:
Procedural programming could be considered a step towards declarative
programming. A programmer can often tell, simply by looking at the
names, arguments and return types of procedures (and related
comments), what a particular procedure is supposed to do, without
necessarily looking at the details of how it achieves its result. At
the same time, a complete program is still imperative since it 'fixes'
the statements to be executed and their order of execution to a large
extent.
In any domain the same applies. If you ask the flight attendant to reschedule your flight she knows what a flight and a passenger is and how to reschedule one. Creating a fully declarative flight scheduling domain model without describing how scheduling works is therefore impossible. Since all domain models contain operations/behavior it is therefore equally impossible to create a domain model in a declarative language unless your problem domain is not unique, for example when you have three flight companies that operate in similar fashion.
Back to why... you said:
Actually, the hypothetical reason why is actually to allow non-coders
to create a (trivial) backend by configuration
Declarative programming is not always simpler than imperative programming. Most of the time people tend to think in outcomes, but sometimes the outcomes are so varied that it is (much) simpler to think in steps. This is the reason why these different styles exist and continue to exist in the first place. The main difference between a coder and a non-coder is not that a non-coder tends to think in terms of outcomes instead of processes, but that the non-coder simply does not want to be bothered with the workings of a computer. The non-coder wants to focus on the problem. Depending on the domain a non-coder may be helped best with an imperative DSL, instead of an declarative DSL.
I've always avoided using aggregation because it seems so subjective which one-to-many relationships should be classed as aggregations. But I'm reviewing a model produced by someone else in which aggregations are used for many-to-many relationships (as in: a course consists of several modules, a module may be part of several courses). That strikes me as plain wrong, but I can't find a definitive rule against it. What's the official ruling?
Two things:
Are shared aggregations allowed? According to the UML spec, yes.
Is it useful in practice? Generally I'd say no.
I am not a fan of the UML Aggregation relationship. Whilst ownership is intuitively appealing, it is too subjective practically. I don't use it, and generally don't recommend it be used (although see footnote). Instead, focus on the important questions:
What's the cardinality?
What's the create/delete behaviour?
Why does the relationship exist? (i.e. what business fact/rule is the relationship capturing?
All above can be done with straight associations. If the answer is (a) it's one to many, (b) the 'one' end is responsible for creating/deleting the 'many' end and (c) you really want to, then use the Composite association. Aggregation however doesn't generally improve readability of the model, it adds confusion and detracts from surfacing the underlying domain rules/requirements.
hth.
footnote: there is one scenario where Aggregation does have well-defined semantics and can be useful. Specifically, if you have a recursive relationship, Aggregation says the resultant object structure is acyclic (i.e. a DAG). Downside is relatively few people realise that property - certainly not business domain experts. So you typically have to highlight anyway, e.g. in a comment / constraint.
A good website for this is
http://www.uml-diagrams.org/class-diagrams.html
If you search there for "Shared and Composite Aggregation" you will read, that shared parts can be modeled as aggregations. Even if the composite holding the part will be discarded the parts are allowed to survive.
This seems to make many to many relationships possible. For example sharing a part of a view for several view-components. Why not...
Personally this matches my understanding, that UML is very interpretative.
Let's set the terms. The Aggregation is a metaterm in the UML standard, and means BOTH composition and shared aggregation, simply named shared. To often it is named incorrectly "aggregation". It is BAD, for composition is an aggregation, too. As I understand, you mean "shared".
Again, if we'll look at the UML standards (look for Superstructure documentation there), we'll find, that "Precise semantics of shared aggregation varies by application area and modeler." So, ANY strategy you choose is acceptable. And you even can use different strategy for different projects.
But the shared aggregation IS useful and CAN be used with multiplicities on both sides and even the empty diamond can be on both sides.
The association in UML is an abstraction, that can be realized in any language and in any way, only the realization must be up to the diagram.
Such association, as on the diagram, can be realized as following:
Every instance of Student has a list of courses he is registered to,
and every instance of Courses has a list of registered
students/participants.
But this is not the only way of realization. There could be arrays instead of lists, and even somebody can make it without any normal collection at all - simply using the addresses in memory in C++.
Of course, we could draw two associations, one for student's list of courses and the second for courses' list of students. But thus:
our diagram becomes more complex and, therefore, less readable.
we are describing thoroughly the elementary things that any coder will do anyway in 99% cases.
we are limiting the freedom of coders. And in 1% of cases they'll have to choose between not following the diagram and not coding effectively. It is simply not your job.
So, do as you wish. Forbidden is only to change the strategy during one project and to FORBID others to use their only strategy.