1
+ <!--
2
+ ~ Copyright (C) 2012 United States Government as represented by the Administrator of the
3
+ ~ National Aeronautics and Space Administration.
4
+ ~ All Rights Reserved.
5
+ -->
6
+
7
+ <!-- $Id: Design and Coding Guidelines.html 1171 2013-02-11 21:45:02Z dcollins $ -->
8
+ < body >
9
+ < h1 > WorldWind Multi-Platform Design and Coding Guidelines</ h1 >
10
+
11
+ < h2 > General</ h2 >
12
+ < ul >
13
+ < li >
14
+ Our required target platforms are OS X, Windows XP and Vista, and the most popular versions of Linux. All code
15
+ and all products must run on all those systems.
16
+ </ li >
17
+ < li >
18
+ Read the WorldWind API's Overview section for a description of WorldWind architecture, design and usage. Read
19
+ the overview pages of each WorldWind package for descriptions of those. These descriptions contain critical
20
+ information that is not repeated elsewhere. To avoid making mistakes, everyone working on WorldWind must read
21
+ them before using or modifying the code.
22
+ </ li >
23
+ < li >
24
+ The project's development IDE is IntelliJ IDEA. The IDEA configuration files for this project are checked in to
25
+ the code repository. They define within them global and local library links, formatting rules, etc.
26
+ </ li >
27
+ < li >
28
+ Most major classes need a no-argument constructor so that the declarative instantiation mechanism can work. WW
29
+ objects should avoid constructors with arguments so that they can be created generically by name. This means
30
+ they should self-configure if at all possible, drawing their parameterized info from Configuration. They should
31
+ also contain an interface to set the configuration details programmatically.
32
+ </ li >
33
+ < li >
34
+ Make field and variable names clear and easy to read. Don't label them with "my" or "m_" or some other goofy
35
+ notation. Within a class refer to all member fields with "this", e.g., this.tileCount.
36
+ </ li >
37
+ < li >
38
+ The buffers one must use to pass arrays of info to JOGL must have their byte order set to that of the machine
39
+ they're used on. Call nativeByteOrder() on NIO buffers when you deal with them, use the methods in
40
+ com.jogamp.common.nio.Buffers.
41
+ </ li >
42
+ < li >
43
+ Favor immutability (all fields final) in classes representing some small entity like a Point or Vector.
44
+ Immutable classes are fully thread safe and generally less error prone.
45
+ </ li >
46
+ < li >
47
+ Don't worry too much about frequent memory allocations. Java is now so optimized for this that allocating an
48
+ object on the heap has similar performance to allocating it on the stack, and this includes the cost of garbage
49
+ collection. There is still a cost to executing any code, however, so be smart about allocation frequency.
50
+ </ li >
51
+ < li >
52
+ Configuration items typically have two values and thus two attribute names: a DEFAULT value that is used if not
53
+ overridden, and a non-default value that can be set programmatically (in Configuration) to a current value
54
+ without losing the ability to recover the default value.
55
+ </ li >
56
+ < li >
57
+ Classes such as BasicDataFileStore and the logger are effectively singletons but they are not defined in their
58
+ class definition as such. Their singleton nature comes from their 1:1 association with the truly singleton
59
+ WorldWind class, which provides access to instances of these "singleton" classes.
60
+ </ li >
61
+ < li >
62
+ Do not use classes that are not available in the standard 1.6 JRE. Don't incur additional or external
63
+ dependencies. The only 3rd-party library we rely on is JOGL.
64
+ </ li >
65
+ < li >
66
+ Constants are defined as String and namespace qualified. This enables easy and non-conflicting extension.
67
+ </ li >
68
+ < li >
69
+ Do not use GUI builders to generate interfaces for examples or applications. They prevent others from being able
70
+ to maintain the code.
71
+ </ li >
72
+ < li >
73
+ Protect OpenGL state within a rendering unit, such as a layer, by bracketing state changes within try/finally
74
+ clauses. The util.OpenGLStackHandler utility class makes this easy. It manages both attribute state and matrix
75
+ stack state. The goal is to isolate any OpenGL state changes to the rendering unit, both when the unit succeeds
76
+ and when it fails.
77
+ </ li >
78
+ < li >
79
+ WorldWind never crashes. Always catch exceptions at least at the highest entry point from the runtime, e.g., UI
80
+ listeners, thread run() methods.
81
+ </ li >
82
+ < li >
83
+ Within a rendering pass WorldWind does not touch the disk or the network. Always fork off a thread to do that.
84
+ Use the TaskManager and Retriever systems to start threads during rendering. These are set up to govern thread
85
+ usage to avoid swamping the local machine and the server.
86
+ </ li >
87
+ < li >
88
+ Too much micromanagement of state makes the code brittle. Try to design so that the right thing just happens
89
+ once things are set up, and the effect of something going wrong is benign. For example, Layers fork off
90
+ Retriever objects to retrieve data from the network. But they don't try to keep track of these. If the retriever
91
+ succeeds then the data will be available the next time the layer looks for it. The fact that it's not there
92
+ because of a timeout or something tells the layer to ask for it again if it needs it.
93
+ </ li >
94
+ < li >
95
+ DOMs are expensive in memory and time. Use an event for any documents that might be large. Use the parser in
96
+ gov.nasa.worldwind.util.xml when appropriate.
97
+ </ li >
98
+ </ ul >
99
+
100
+ < h2 > Exceptions</ h2 >
101
+ < ul >
102
+ < li >
103
+ WW objects running in the Main thread pass exceptions through to the application unless there's good
104
+ reactive/corrective behavior that can be applied within WW.
105
+ </ li >
106
+ < li >
107
+ Log any exceptions prior to throwing them. Use the same message for the log as for the exception.
108
+ </ li >
109
+ < li >
110
+ Ensure all exception messages are generated using the i18n method details below.
111
+ </ li >
112
+ < li >
113
+ Public methods validate their arguments and throw the appropriate exception, typically InvalidArgumentException,
114
+ and identify the exception message the parameter name and the problem -- null, out of range, etc. See the
115
+ message resource file, util.MessageStrings.properties, for common messages and their identifiers.
116
+ </ li >
117
+ < li >
118
+ In Retriever threads, do not catch Throwable. Catch and react to Exception if there's a good reactive/corrective
119
+ behavior to apply, otherwise allow them to pass up the stack. Retriever threads should have an uncaught
120
+ Exception handler specified for the thread. The method should log the Exception or Throwable and then return.
121
+ </ li >
122
+ < li >
123
+ Private and protected methods whose calling client can't be trusted validate their arguments and throw an
124
+ appropriate exception.
125
+ </ li >
126
+ < li >
127
+ The audience for exceptions is not primarily the user of the client program, but the application or WorldWind
128
+ developer. Throw exceptions that would let them know immediately that they're using faulty logic or data.
129
+ </ li >
130
+ </ ul >
131
+
132
+ < h2 > Logging</ h2 >
133
+ < ul >
134
+ < li >
135
+ Logging using java.util.logging has the nice feature of capturing the class and method name at the site of the
136
+ logging call. That's why there is the common idiom of create message, log message, throw exception. Wrapping
137
+ these three actions in some utility method would lose the class and method-name feature, so don't do that. Don't
138
+ use any logging system other than that in the JRE.
139
+ </ li >
140
+ < li >
141
+ Log all exceptional conditions before rethrowing or throwing a new exception.
142
+ </ li >
143
+ < li >
144
+ Ensure all logging uses i18n messages as detailed below.
145
+ </ li >
146
+ < li >
147
+ Use level SEVERE for things that prevent the intended action,e.g., file can't be written. Use level WARN for
148
+ things that don't stop the action but seem exceptional, e.g., a file was retrieved or written redundantly. Use
149
+ level FINE for simple notifications. Use FINER for method traces. Using the "FINE"series prevents screen display
150
+ of these when the default JAVA logging settings are used. Since we're a component, we don't communicate such
151
+ things directly to the application's user; the application does.
152
+ </ li >
153
+ </ ul >
154
+
155
+ < h2 > Concurrency</ h2 >
156
+ < ul >
157
+ < li >
158
+ Use collection classes from the java.util.concurrent package if there's any chance at all that the collection
159
+ may be accessed from multiple threads.
160
+ </ li >
161
+ < li >
162
+ Except for simple atomic variables (but not long or double) the safest way to manage multi-thread access is
163
+ through the blocking queue classes of java.util.concurrent.
164
+ </ li >
165
+ < li >
166
+ Making a class' fields final avoids concurrency problems, but it makes the class much less extensible. If using
167
+ private, make sure there are overridable set/get accessors.
168
+ </ li >
169
+ </ ul >
170
+
171
+ < h2 > Offline Mode</ h2 >
172
+
173
+ < p > WorldWind's use of the network can be disabled by calling {@link gov.nasa.WorldWind.setOfflineMode}. Prior to
174
+ attempting retrieval of a network resource -- anything addressed by a URL -- WorldWind checks the offline-mode
175
+ setting and does not attempt retrieval if the value is true. To honor this contract, all code must check network
176
+ status prior to attempting retrieval of a resource on the network.</ p >
177
+
178
+ < h2 > Documentation</ h2 >
179
+ < ul >
180
+ < li >
181
+ Use the appropriate Ant target to generate worldwind.jar and javadoc API documentation. Do not use the IDEA
182
+ Tools command because it's not configured appropriately, only the Ant targets are.
183
+ </ li >
184
+ < li >
185
+ All public and protected classes, methods and fields should be commented for javadoc documentation generation.
186
+ </ li >
187
+ < li >
188
+ Descriptions of classes, methods, etc. should start with a capital letter. Parameter descriptions and
189
+ return-value description should start with a lower-case letter. All descriptions end with a period.
190
+ </ li >
191
+ < li >
192
+ If a class overrides methods from {@link Object} such as < code > toString()</ code > and < code > equals()</ code > ,
193
+ their behavior for the specific class should be described. For < code > equals()</ code > that would be the fields
194
+ compared. For < code > toString()</ code > that would be the representation returned.
195
+ </ li >
196
+ < li >
197
+ Use links liberally, e.g., {@link WorldWind}. They help the reader get to information fast.
198
+ </ li >
199
+ </ ul >
200
+
201
+ < h2 > Code Formatting</ h2 >
202
+ < ul >
203
+ < li >
204
+ Use the code formatting and style that's in the IDEA project file. It makes it possible to review previous code
205
+ modifications.
206
+ </ li >
207
+ < li >
208
+ Use the code formatting rules specified in WorldWindJ.ipr. They are in the project file under (Settings Project
209
+ Settings Project Code Style). To apply them, simply use Code Auto-indent Lines. You can also just check the box
210
+ at Subversion check-in time and the formatting will be applied before check-in. Be sure the formatting rules are
211
+ not overridden in your IDEA workspace.
212
+ </ li >
213
+ < li >
214
+ We generally use the traditional Sun coding conventions. Constants are in all upper case with words separated by
215
+ underscores. Everything else is in camel case. Class names start with an upper case character, variables start
216
+ in lower case.
217
+ </ li >
218
+ < li >
219
+ White space is preferred over packing code into a small space. Please use white space liberally.
220
+ </ li >
221
+ < li >
222
+ Set up IDEA to automatically place the standard project header in newly created files by putting the following
223
+ as the File Header in the Includes tab of IDEA in the File Templates dialog: < br > < code > < br > /* Copyright (C)
224
+ 2001, 2011 United
225
+ States Government
226
+ as represented by
227
+ < br > the Administrator of the National Aeronautics and Space Administration. < br > All Rights Reserved. < br > */ < br > package
228
+ ${PACKAGE_NAME};
229
+ < br > < br > /** < br > * @author ${USER} < br > * @version $Id: Design and Coding Guidelines.html 1171 2013-02-11 21:45:02Z dcollins $ < br > */ </ code >
230
+
231
+ < p >
232
+ Then remove the package name property from first line of the Class and Interface items of the Templates tab
233
+ in the File Templates dialog. (The package name is in the "include" now, so it gets inserted after the
234
+ copyright.) Test it out by creating a dummy class. Unfortunately this set-up is a personal configuration in
235
+ IDEA, not project specific.</ p > </ li >
236
+ < li >
237
+ When creating a new file, the Id subversion keyword has to be explicitly set via Version Control --> Set
238
+ Property --> Property name: svn:keywords, and the term Id included in the text box. If the property is not
239
+ included in this list then Subversion doesn�t replace the property string when updating the file.
240
+ </ li >
241
+ < li >
242
+ Resolve all IDEA warnings before checking in a file. If the warning refers to an intentional case, add an
243
+ exception statement.
244
+ </ li >
245
+
246
+ </ ul >
247
+
248
+ < h2 > Internationalization (i18n)</ h2 >
249
+ < ul >
250
+ < li >
251
+ String "constants" are stored in separate resource files (e.g. MessageStrings.properties). These files must end
252
+ in ".properties" and must be stored in the src directory. Strings are stored with the format:
253
+ packageOfClass.className.nameOfString=value of the string
254
+ </ li >
255
+ < li >
256
+ Access the string constants by using the following pattern: (e.g.
257
+ Logging.getMessage("myPackage.myClass.targetStringName");).
258
+ </ li >
259
+ </ ul >
260
+
261
+ < h2 > Books</ h2 >
262
+ The books we go back to again and again are the following:
263
+ < ul >
264
+ < li >
265
+ < i > Core Java</ i > , Horstmann & Cornell, Volumes 1 and 2, Prentice Hall. Be sure to get the editions covering at
266
+ least J2SE 5. Get the newest edition (currently 8).
267
+ </ li >
268
+ < li >
269
+ < i > The Java Programming Language</ i > , Arnold & Gosling, Addison Wesley. Be sure to get the most recent edition
270
+ covering at least Java 6.
271
+ </ li >
272
+ < li >
273
+ < i > Concurrent Programming in Java</ i > , Lea, Addison Wesley
274
+ </ li >
275
+ < li >
276
+ < i > Java Threads</ i > , Oaks & Wong, O�Reilly
277
+ </ li >
278
+ < li >
279
+ < i > Java Cookbook</ i > , Darwin, O�Reilly
280
+ </ li >
281
+ < li >
282
+ < i > OpenGL Programming Guide</ i > , Shreiner & Woo & et al, Addison Wesley. Be sure to get the version covering
283
+ OpenGL 2.0, which is currently the Fifth Edition.
284
+ </ li >
285
+ < li >
286
+ < i > Mathematics for 3D Game Programming & Computer Graphics</ i > , Lengyel, Charles River Media. Be sure to get the
287
+ Second (or later if there is one) edition.
288
+ </ li >
289
+ </ ul >
290
+ </ body >
0 commit comments