-
Notifications
You must be signed in to change notification settings - Fork 0
XMind diagram conventions
- Last updated on 01/09/2020
Please note: In the future the use of this Xmind Parser may be replaced with the Masters project that Arnab is working on currently
-
Your diagram should have "Root" as the root topic (not "DataLink", that was for an older version of the parser), with a child called "Application". All instances that you wish to convert into code must be descendants of this Application node. Floating topics are ignored by the parser.
-
The following order should always be followed: Instance A -> AcceptedPortOfA -> ImplementedPortOfB -> Instance B
NOTE: Parser is space-sensitive. Beware of spaces after the data types e.g. >IEvent start
will cause the exception above.
Note that this also works in the reverse direction:
And works the same with red arrow wiring too:
Red arrow wires, i.e. "relationships" in XMind, are used when you want to wire to something that is already a child in another subtree.
-
Instances should follow the following template, with an example of a PopupWindow instance:
-
If the instance has a variable name, the Instance Name is automatically generated with the same variable name and if it was defined another InstanceName in the Xmind Wiring, it will be overwritten by the automatically generated e.g. scpConnector is has an automatically generated InstanceName = "scpConnector"
If the instance does not have a variable name it will have an automatically generated reference key and a InstanceName = "Default"
-
Wirings connected in the tree structure happen first (from top to bottom), and then red arrow wirings occur in the order that they were wired.
-
You can use "@" at the start of an instance (as the first character of its abstraction type) to indicate that the instance is a reference instance, and has already been instantiated, i.e. it already exists somewhere else in the current diagram, or in some other diagram that will be used to generate code. For example, "AppStartEventConnector" is the event connector that runs at the start of the application: ![@reference wiring](images/@reference wiring.PNG)
NOTE: Care must be taken to ensure that if an output port is wiring to multiple instances, then that port should be a fanout list of some kind (i.e. it must start with "*", and it must be a list in the abstraction code). Otherwise, an exception will be thrown. As an example, AppStartEventConnector has a fanoutList as an output port.
A reference instance can be added to the diagram before the original instance itself is there: you just need to ensure that the original instance appears at some point within one of the diagrams that you are converting to code.
-
"*" at the start of a port means a fanout list. If a port doesn't have this, then you can only wire from it to one other port. A "port already wired" exception is thrown if this rule is violated (i.e. if you try to wire a non-fanout list accepted port to more than one implemented port).
-
"#" at the start of an instance can be used to indicate that that instance is a connector, although this does not impact the parser in any way, and can be omitted if desired.
-
"NEEDNAME" is used as placeholder names for input ports. Ideally, all ports should have descriptive variable names instead of this placeholder.
-
The parser has some support for comments. Comments cannot be added inside instances themselves, and the parent of a comment must always be an instance.
-
You can only wire from accepted ports, and can only wire to implemented ports. To see what it means for a port to be accepted vs being implemented, let's have a look at part of the Apply abstraction:
![abstraction ports code example](images/abstraction ports code example.PNG)
Ports are an ALA term that refer to, at this point in time, C# interfaces. Apply implements
IDataFlow<T1> input
, and acceptsIDataFlow<T2> output
(side note: the<
and>
are used to show "<" and ">", respectively, in IntelliSense summaries). An abstraction can only implement a single interface type at a time (as they are not actually given C# variable names), whereas an abstraction can accept as many ports (even of the same type) as you want. Also, note that e.g.IDataFlow<bool>
andIDataFlow<string>
are considered to be different types. -
Named instances (e.g. HttpRequest myHttpRequest) must have unique names, however if your instance is unnamed (e.g. just HttpRequest), then an id will be automatically generated and given as the instance's name in the generated code. This is important for when you use reference instances (instances that have their abstraction type starting with @): All reference instances must be named.
-
The arrow before a port name (e.g. the ">" in "> IEvent start") represents the direction of data flow. You will notice that ports that allow bidirectional data flow, like ITableDataFlow, have "<>" before the port name. Since the direction of data flow should help you decide how to wire a port, I have made an exception for bidirectional ports: implemented bidirectional ports will start with either "<<" or ">>", depending on where the instance node is relative to it. For example: ![bidirectional arrows](images/bidirectional arrows.PNG)
Both of these mean the same thing: Filter implements an ITableDataFlow port. Note that the ">>" or "<<" symbols only need to be added to the implemented ports, i.e. ports that you will wire to. (the input side)
-
IDataFlowB and IEventB are currently the only two kinds of ports that have data flow in the reverse direction of their wiring direction. In other words, if you wire to an IDataFlowB port, you are actually pulling data from the IDataFlowB port's parent instance.
-
By default, all port names for all instances should be visible, even if they are not currently being wired to. This makes it easier to wire to these ports later on. Currently, there is a limitation in that changing the ports in Templates does not automatically update all ports in an XMind diagram, so you may choose to only show some of an instance's ports at a time and delete the rest, if you are worried that these unused ports may change over time.
-
If you do decide to change the port names for an abstraction, be sure to change the port names in your Templates diagram, as well as making the changes in every existing diagram.
-
I sometimes use a substitute accepted port called "> IKeepTreeStructure ~>" (i.e. this port isn't actually accepted by the abstraction) when I want to add an instance as a child of another instance for convenience, but the two instances aren't actually wired together:
Here, naitSetPlaceHolderValues can be wired to from some other starting point (hence the red arrow wired to its implemented IEvent port), while keeping the instance grouped together with the abstractions that use the placeholder values. This is similar to the use of "|" in past XMind diagrams.
-
If you have a case where you need to wire a single EventConnector to multiple ports that are already children of some other subtree in the diagram. Listed below are possible solutions.
Solution 1 - Create a sub-tree to wire the red arrows into
![multiple red arrows - problem case](images/multiple red arrows - problem case.PNG)
The problem with this is that you need to ensure that the red arrows are wired in an exact order such that the HttpRequest for pingThisFirst/Second/Third.com receives the event first/second/third. This is possible by creating and attaching the red wires in that order, but what if later on you decide to insert another HttpRequest in that sequence? You would have to delete some wires and then rewire them carefully in the appropriate order (you could even edit the label of a red wire to reflect its order in the sequence). It may not seem like a big deal a small case like this, but once you have more complicated sequences, updating and refactoring them can become unnecessarily time-consuming.
Solution 2 - Create a separate event connectors for the fanout list
![multiple red arrows - solution](images/multiple red arrows - solution.PNG)
Giving each red wire its own EventConnector may feel like too much, but it's safer and produces less of a headache in the future, because it both explicitly describes what's happening, and XMind is good at handling modifications to subtrees.
Solution 3 - (Preferred approach) Use the @ to reference instance
And on the instance side to do a reference that it has already been wired, shown below.
Note: // # DataFlowConnector<bool> noDeviceConnectedConnector
is on one line
It is possible to wire the @ on the other side e.g. textSearchingPorts would wire to the noDeviceConnectedConnector with the @, however this means the references will be scattered rather than grouped at the the fanout list side.
This solution eliminates the use of the problem with ordering the wiring of the red arrows and also promotes a more tidier diagram.
-
New changes added to the diagram can be added with a visual border. This can be useful when the diagram is worked on one at a time by different person.
-
Please be aware of the wiring direction when using String Format
Tips:
- Do not forget to write a boolean input to open the gates otherwise data flow will not flow
- When dealing with fanoutlist of DataFlowConnector or EventConnector, be aware of the sequence of the wiring, make sure to order them in occurance sequencessd.
- When creating Xmind diagrams, use
Ctrl + Alt + C
to copy andCtrl + Alt + V
to paste topic style. - In Xmind, when adding topics before a topic, DO NOT use
Ctrl + Enter
, because this will remove all red arrows behind the topic. Better way to do this would be, create a sub-topic first and then drag and drop topics.
Example:
When use Ctrl + Enter
to add a sub-topic before Subtopic1
, we will get error result: