Projet

Général

Profil

MAY Best Practices » Historique » Version 21

Anonyme, 14/10/2014 11:38

1 18 Anonyme
h1. MAY Best Practices
2 1 Anonyme
3 14 Anonyme
{{>toc}}
4
5 2 Anonyme
h2. Typical Workflow
6 1 Anonyme
7 16 Anonyme
In the Java project, sources (Java and SpeADL) edited by the developer are in the *src* folder (or equivalent), and the generated Java code is in the *speadl-gen* folder.
8
The *speadl-gen* folder is not meant to be touched by hand.
9 1 Anonyme
10 2 Anonyme
Each modification of a SpeADL file is followed by the generation of its equivalent Java class.
11
12
A typical workflow for creating a component is as follow:
13 21 Anonyme
* [[MAY Project Setup|Creation of a SpeADL file]].
14 13 Anonyme
* [[SpeADL Reference|Description of a component]].
15
* Description of the interfaces needed by the component description.
16
* [[SpeADL Reference|Implementation of the component]] extending the corresponding class.
17 2 Anonyme
* And so on...
18
19 17 Anonyme
See [[SpeADL Minus Tutorial]] for a detailed tutorial.
20
21 8 Anonyme
h2. Module View
22 9 Anonyme
23 2 Anonyme
On top of component declarations, interfaces and component implementation, it is relevant to define sometimes datatypes used in the interface or as type parameters of the components used.
24
25
A software component, its declaration, its implementation and classes it relies on form altogether what is called a module.
26
27
When creating interfaces or datatypes for one or several components, it is important to ask oneself to which module (i.e., with a given component) these declarations should belong to and why.
28
29
h2. Project Organisation
30
31 15 Anonyme
For a simple project, a good organisation of the src directory is as follow:
32 2 Anonyme
* Package my.project
33
** SpeADL file *myproject.speadl* with a single namespace *my.project*.
34
** Package *interfaces* containing the interfaces declarations
35
** Package *impl* containing the implementations
36 10 Anonyme
** Package *datatypes* containing extra classes needed 
37 2 Anonyme
** Package *exception* containing exceptions needed in the interfaces
38
39
In this case, all the modules are intermixed together.
40
41
For a more complex project, a good organisation of the src directory is as follow:
42
* Package my.project
43
** Package aComponent
44
*** SpeADL file *aComponent.speadl*
45 10 Anonyme
*** Package *interfaces* containing the interfaces declarations owned by this component
46
*** Package *impl* containing the implementation of the component
47
*** Package *datatypes* containing extra classes needed by this component
48
*** Package *exception* containing exceptions needed in the interfaces owned by this component
49 2 Anonyme
** Package anotherComponent
50
*** ...
51
52
In this case each module has its own package.
53
54
h2. Exploiting the Eclipse Editor
55
56
h3. Errors
57
58
When creating a Java file to implement a component, one has to extend the Java class generated from the component declaration.
59
60 4 Anonyme
Errors are shown in the Java editor, and the Quick Fix *Add unimplemented methods* proposed by Eclipse will generate automatically the skeleton for the Java file.
61 2 Anonyme
62
From that:
63
<pre>
64
public class MySimpleComponentImpl extends MySimpleComponent {
65
}
66
</pre>
67
68
We get that:
69
<pre>
70
public class MySimpleComponentImpl extends MySimpleComponent {
71
	@Override
72
	protected AnotherJavaInterface make_p1() {
73
		// TODO Auto-generated method stub
74
		return null;
75
	}
76
}
77
</pre>
78
79
This gives the possibility to very quickly approach the implementation of a component.
80
81
h3. Completion
82
83
When implementing the *make_XXX()* method of a provided port, one can exploit completion to gain a lot of time.
84
For example in the following situation (just after using the Quick Fix):
85
<pre>
86
class MySimpleComponentImpl extends MySimpleComponent {
87
	@Override
88
	protected AnotherJavaInterface make_p1() {
89
		// TODO Auto-generated method stub
90
		return null;
91
	}
92
}
93
</pre>
94
95 7 Anonyme
Remove the _null_ after the return statement and replace it with _new AnotherJavaInterface_, use completion (*Ctrl+Space*) and select *AnotherJavaInterface() Anonymous Inner Type* to generate the anonymous type declaration as well as the skeleton to implement its methods:
96
97
<pre>
98
public class MySimpleComponentImpl extends MySimpleComponent {
99
	@Override
100
	protected AnotherJavaInterface make_p1() {
101
		return new AnotherJavaInterface() {
102
			@Override
103
			public Integer test() {
104
				// TODO Auto-generated method stub
105
				return null;
106
			}
107
		};
108
	}
109
}
110
</pre>
111 19 Anonyme
112
h2. Implementing Provided Ports
113
114
When implementing provided ports, there is two main ways of doing it:
115
* Using an anonymous instance of the interface.
116
* By implementing the interface directly with the component implementation.
117
118
Using an anonymous class is as follow:
119
<pre>
120
public class MySimpleComponentImpl extends MySimpleComponent {
121
122
    @Override
123
    protected AnotherJavaInterface make_p1() {
124
        return new AnotherJavaInterface() {
125
            @Override
126
            public Integer test() {
127
                return 10;
128
            }
129
        };
130
    }
131
132
}
133
</pre>
134
135
Implementing the interface is as follow:
136
<pre>
137
public class MySimpleComponentImpl extends MySimpleComponent implements AnotherJavaInterface {
138
139
    @Override
140
    public Integer test() {
141
        return 10;
142
    }
143
144
    @Override
145
    protected AnotherJavaInterface make_p1() {
146
        return this;
147
    }
148
}
149
</pre>
150
151 20 Anonyme
h2. Required Ports and Their Importances
152 19 Anonyme
153
Components expose their required functionalities through explicit ports bound when composition is done.
154
This is very different from objects that must be given directly an object providing a required functionality.
155 1 Anonyme
156 20 Anonyme
h3. Implicit Dependencies
157
158 19 Anonyme
An error that must be avoided when defining a component is to express a dependency to a functionality by requiring objects to be passed to their implementation constructor or by instantiating other objects in their implementation.
159
It is better to explicit such dependencies through required ports.
160
161
Of course this rule can be bent when the functionality is really internal to the component implementation and when it has nothing to do with the architecture the component is part of.
162 1 Anonyme
But it is a good practice to explicit required functionalities like this for facilitating future evolution.
163 20 Anonyme
164
h3. No Shared Objects between Components
165
166
A very dangerous case of the previous discussed case is when two components actually share a reference to a same object.
167
This really means that there is a functionality that must be explicited through the creation of a third component that exposes the functionality through one of its port.