Show last authors
1 {{box cssClass="floatinginfobox" title="**Contents**"}}
2 {{toc/}}
3 {{/box}}
4
5 {{warning}}
6 This document is still a draft. Note that the current content also reflects the view of its authors and NOT the view of the XWiki development team. We'll need to agree with the content before we can consider any of these best practices.
7 {{/warning}}
8
9 = Introduction =
10
11 This document has the objective of describing how to best write an XWiki Application or Module. It explains:
12
13 * The different parts that can make an XWiki Application
14 * How to organize the pages in spaces and how to name the pages
15 * Naming conventions for the different pages, the translations, the CSS
16 * Conventions for the Application documentation
17
18 An Application is made of several modules. What we will describe here is how to organize each of these modules.
19
20 = General Organization =
21
22 A module should separate its data and its code. Modules should be built to be able to have data in several XWiki spaces, which allows to instanciate the module multiple times.
23
24 {{warning}}
25 It is therefore important that an application most often displays data from the current space.
26 {{/warning}}
27
28 The only exception would be for applications that would spread multiple spaces on purpose. However, it should be most often possible to handle this by having space level sheets showing only data from the current space and global sheets showing data from the whole Wiki.
29
30 = Naming Conventions =
31
32 == Module Name ==
33
34 It is best to choose a module name between 5 and 10 characters. Your module name should represent your data well. The wiki module name is usually using capital letters. The module name used in the CSS or Javascript or Translations strings is in lower case.
35
36 {{info}}
37 We will use throughout this document the module name 'MyModule' to show the naming conventions.
38 {{/info}}
39
40 It is very important to gather most of the logic code in the Code space. For this we should use macros and sheets (included using ##includeInContext##).
41
42 == Spaces ==
43
44 * Code Space
45 (((
46 {{info}}
47 The code space should be names by the module name suffixed by Code. In our example this would be: MyModuleCode
48 {{/info}}
49 )))
50 * Data Space(((
51 {{info}}
52 The default data space should be name by the module name. In our example this would be: MyModule
53 {{/info}}
54 )))
55
56 == Classes ==
57
58 The classes should be stored in the code space and should be suffixed by 'Class'. The properties of the classes should be camel case. They should be written in english and represent their meaning as much as possible. The 'title' and 'name' property should be kept for a field that can be used as a title for the document. Examples:
59
60 * expireDate
61 * externalRef
62
63 {{info}}
64 The class definition should be stored in the Code space: MyModuleCode.MyModuleClass
65 {{/info}}
66
67 There can be multiple classes per module.
68
69 == Sheets ==
70
71 The sheets are used for coding the presentation of a document of your class. The template is a sample document that can be used to pre-initialize data in your documents using this class.
72
73 {{info}}
74 A sheet page should be stored in the code space and start by the class name followed by the Sheet word: MyModuleCode.MyModuleClassSheet
75 {{/info}}
76
77 There is usually only one sheet per class.
78
79 A sheet should be coded only using the XWiki Public API. It should be made to work both in view more or in edit mode (inline). A good example of a sheet that uses many functions available (tooltips and validation) is available in [[this tutorial>>platform:DevGuide.Creating a form with validation and tooltips]].
80
81 == Templates ==
82
83 {{info}}
84 A template page should be stored in the code space and start by the class name followed by the Template word: MyModuleCode.MyModuleClassTemplate
85 {{/info}}
86
87 There is usally one template per class, but it is possible to have multiple templates, though this requires more user-interface work.
88
89 == Translations ==
90
91 Translations are used to store strings to translate the user interface of your application.
92
93 {{info}}
94 Translations should be stored in the code space in a page called Translations: MyModuleCode.Translations. Each language has its own translated wiki page.
95 {{/info}}
96
97 The translations strings are each on one line and should be prefixed by the module name in lower case and by the sub-module or page name in which it is used:
98
99 {{code}}
100 mymodule.sheet.title=Title
101 mymodule.sheet.description=Description
102 mymodule.sheet.errormessage.cannotsave=The document {0} cannot be saved
103 {{/code}}
104
105 Translations strings can contain wiki syntax or HTML which can be interpreted. You have to be extra carefull to not use wiki syntax or HTML without knowing it (for example < > & are special characters). Parameters named {0} {1} {2} can be used in translations.
106
107 == CSS ==
108
109 {{warning}}
110 **[[SkinExtensions>>extensions:Extension.Skin Extension Plugin]] should always be used on XWiki versions where they are available.**
111 {{/warning}}
112
113 CSS should use a similar naming convention as translations. CSS can be stored either in skin files or in wiki pages.
114
115 {{code language="css"}}
116 .mymodule-sheet-p {
117 // etc..
118 }
119 #mymodule-sheet-title {
120 // etc..
121 }
122 {{/code}}
123
124 When stored in wiki pages CSS should be surrounded by the pre and slash-pre macros that prevent wiki syntax to be executed in the content.
125
126 {{info}}
127 * If stored in Wiki pages the CSS page should be stored in the code space and suffixed with CSS: MyModuleCode.CSS or MyModuleCode.SubModuleCSS
128 * If stored in skins the CSS page should be named by the module: mymodule.css
129 {{/info}}
130
131 == Javascript ==
132
133 {{warning}}
134 **[[SkinExtensions>>extensions:Extension.Skin Extension Plugin]] should always be used on XWiki versions where they are available.**
135 {{/warning}}
136
137 Modules can provide Javascript to extend the functionnality of the wiki.
138
139 JS functions should be named by the module:
140
141 {{code language="javascript"}}
142 function mymodule-init() {
143 }
144 function mymodule-openwindow() {
145 }
146 etc..
147 {{/code}}
148
149 JS has the same constraints as CSS files and need to be protected by pre and slash-pre when stored in wiki pages.
150
151 {{info}}
152 * If stored in Wiki pages the Javascript page should be stored in the code space and suffixed with JS: MyModuleCode.JS or MyModuleCode.SubModuleJS
153 * If stored in skins the Javascript page should be named by the module: mymodule.js
154 {{/info}}
155
156 == Macros ==
157
158 Macros should be used extensively to modularize the code in the wiki. Macros can be stored in wiki pages or in skins files.
159
160 {{info}}
161 * If stored in Wiki pages the macros page should be stored in the code space and suffixed with Macros: MyModuleCode.Macros or MyModuleCode.SubModuleMacros
162 * If stored in skins the macros page should be named by the module: mymodulemacros.vm
163 {{/info}}
164
165 Macros should be named by the module and the submodule or page that uses it:
166
167 {{code language="velocity"}}
168 ## comment explaining the macro
169 #macro(mymodule_sheet_header $param1 $param2)
170
171 #end ## end macro sheet_footer
172
173 ## comment explaining the macro
174 #macro(mymodule_sheet_footer $param1 $param2)
175
176 #end ## end macro sheet_footer
177 {{/code}}
178
179 == Groovy ==
180
181 Groovy should be used when more logic is needed. There can be one or multiple groovy classes in the module. If possible we should stick to one module. Functions should use the submodule or page in the function names when it makes sense.
182
183 Example code is:
184
185 {{code language="java"}}
186 public class Groovy {
187 def context;
188
189 public setContext(context) {
190 this.context = context;
191 }
192
193 public sheetAdd(param1, param2) {
194 return param1 + param2;
195 }
196 }
197 {{/code}}
198
199 Groovy code can be instanciated in velocity using:
200
201 {{code}}
202 #set($mymodule = $xwiki.parseGroovyFromPage("MyModuleCode.Groovy"))
203 $module.setContext($context)
204 $module.sheetAdd($param1, $param2)
205 {{/code}}
206
207 {{info}}
208 Groovy code should be stored in the code space and suffixed with Groovy: MyModuleCode.Groovy or MyModuleCode.SubModuleGroovy or MyModuleCode.PageGroovy
209 {{/info}}
210
211 == Plugins ==
212
213 Plugins are optional possibilities offered to developers of modules, as an alternative solution to groovy. Plugins should be named using the module name.
214
215 Plugins should be instanciated this way:
216
217 {{code}}
218 #set($mymodule = $xwiki.mymodule)
219 $module.sheetAdd($param1, $param2)
220 {{/code}}
221
222 == Comments and Documentation ==
223
224 We should document all pages in the wiki that contain code. For this we should use a standard documentation comment:
225
226 {{code}}
227 #**
228 * This is page for foo
229 *
230 * @author XXX
231 * @progrights This page requires programming rights
232 *#
233 {{/code}}
234
235 We should document macros:
236
237 {{code}}
238 #**
239 * This is macro for foo
240 *
241 * @param footext Represents the footext
242 * @param secondargument Represents the second argument
243 * @author XXX
244 *#
245 {{/code}}
246
247 These comments are modeled after javadoc and parsable by [[velocidoc>>http://sourceforge.net/projects/velocidoc/]]. We will have to modify the source code to parse the wiki pages using velocidoc.

Get Connected