-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathcode-documentation.txt
More file actions
378 lines (256 loc) · 11.3 KB
/
code-documentation.txt
File metadata and controls
378 lines (256 loc) · 11.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
.. _code-documentation:
******************
Code Documentation
******************
.. default-domain:: mongodb
.. contents:: On this page
:local:
:backlinks: none
:depth: 2
:class: singlecol
Code Documentation
==================
Mongoid uses its own flavor of `YARD <https://github.com/lsegal/yard>`_
for code documentation. Please note the conventions outlined in this document.
.. _code-documentation-structure:
Structure
---------
- **Modules:** All class and module definitions should be preceded by
a documentation comment.
.. code-block:: ruby
# This is the documentation for the class. It's amazing
# what they do with corrugated cardboard these days.
class CardboardBox
- **Methods:** All method definitions should be preceded by a documentation comment.
Use ``@param``, ``@yield``, and ``@return`` to specify inputs and output.
For further details, refer to
:ref:`Type Declaration <code-documentation-type-declaration>` below.
.. code-block:: ruby
# Turn a person into whatever they'd like to be.
#
# @param [ Person ] person The human to transmogrify.
#
# @return [ Tiger ] The transmogrified result.
def transmogrify(person)
- **Errors:** Use ``@raise`` to explain errors specific to the method.
.. code-block:: ruby
# @raise [ Errors::Validations ] If validation failed.
def validate!
- **Private Methods:** Private methods should be documented unless they are
so brief and straightforward that it is obvious what they do. Note that,
for example, a method may be brief and straightforward but the type of
its parameter may not be obvious, in which case the parameter must be
appropriately documented.
.. code-block:: ruby
private
# Documentation is optional here.
def do_something_obvious
- **API Private:** Classes and public methods which are not intended for
external usage should be marked ``@api private``. This macro does not
require a comment.
Note that, because Mongoid's modules are mixed into application classes,
``private`` visibility of a method does not necessarily indicate its
status as an API private method.
.. code-block:: ruby
# This is an internal-only method.
#
# @api private
def dont_call_me_from_outside
- **Notes and TODOs:** Use ``@note`` to explain caveats, edge cases,
and behavior which may surprise users. Use ``@todo`` to record
follow-ups and suggestions for future improvement.
.. code-block:: ruby
# Clear all stored data.
#
# @note This operation deletes data in the database.
# @todo Refactor this method for performance.
def erase_data!
- **Deprecation:** Use the ``@deprecated`` macro to indicate deprecated
functionality. This macro does not require a comment.
.. code-block:: ruby
# This is how we did things back in the day.
#
# @deprecated
def the_old_way
.. _code-documentation-formatting:
Formatting
----------
- **Line Wrapping:** Use double-space indent when wrapping lines of macros.
Do not indent line wraps in the description.
.. code-block:: ruby
# This is the description of the method. Line wraps in the description
# should not be indented.
#
# @return [ Symbol ] For macros, wraps must be double-space indented
# on the second, third, etc. lines.
- **Whitespace:** Do not use leading/trailing empty comment lines,
or more than one consecutive empty comment line.
.. code-block:: ruby
# GOOD:
# @return [ Symbol ] The return value
def my_method
# BAD:
# @return [ Symbol ] The return value
#
def my_method
# BAD:
# @param [ Symbol ] foo The input value
#
#
# @return [ Symbol ] The return value
def my_method(foo)
.. _code-documentation-type-declaration:
Type Declaration
----------------
- **Namespaces:** Always use fully-namespaced class/module names.
Do not use leading colons ``::``.
.. code-block:: ruby
# GOOD:
# @param [ ActiveSupport::TimeWithZone ] time Time for alarm.
# BAD:
# @param [ TimeWithZone ] time Time for alarm.
# @param [ ::ActiveSupport::TimeWithZone ] time Time for alarm.
- **Module Types:** It is acceptable to reference types by a module
which they include.
.. code-block:: ruby
class Person
include ActiveModel::Model
end
# @param [ ActiveModel::Model ] model Any object whose class
# includes ActiveModel::Model. An instance of Person would
# be acceptable here.
- **Type Unions:** Use pipe ``|`` to denote a union of allowed types.
.. code-block:: ruby
# @param [ Symbol | String ] name Either a Symbol or a String.
- **Nested Types:** Use angle brackets ``< >`` to denote type nesting.
.. code-block:: ruby
# @param [ Array<Symbol> ] array An Array of symbols.
- **Hash:** Use comma ``,`` to denote the key and value types.
.. code-block:: ruby
# @param [ Hash<Symbol, Integer> ] hash A Hash whose keys are Symbols,
# and whose values are Integers.
- **Array:** Use pipe ``|`` to denote a union of allowed types.
.. code-block:: ruby
# @param [ Array<Symbol | String> ] array An Array whose members must
# be either Symbols or Strings.
- **Array:** Use comma ``,`` to denote the types of each position in a tuple.
.. code-block:: ruby
# @return [ Array<Symbol, Integer, Integer> ] A 3-member Array whose first
# element is a Symbol, and whose second and third elements are Integers.
- **Array:** Use pipe ``|`` on the top level if the inner types cannot be
mixed within the Array.
.. code-block:: ruby
# @param [ Array<Symbol> | Array<Hash> ] array An Array containing only
# Symbols, or an Array containing only Hashes. The Array may not contain
# a mix of Symbols and Hashes.
- **Nested Types:** For clarity, use square brackets ``[ ]`` to denote nested unions
when commas are also used.
.. code-block:: ruby
# @param [ Hash<Symbol, [ true | false ]> ] hash A Hash whose keys are Symbols,
# and whose values are boolean values.
- **Ruby Values:** Specific values may be denoted in the type using Ruby syntax.
.. code-block:: ruby
# @param [ :before | :after ] timing One of the Symbol values :before or :after.
- **True, False, and Nil:** Use ``true``, ``false``, and ``nil`` rather than
``TrueClass``, ``FalseClass``, and ``NilClass``. Do not use ``Boolean`` as a type
since it does not exist in Ruby.
.. code-block:: ruby
# GOOD:
# @param [ true | false | nil ] bool A boolean or nil value.
# BAD:
# @param [ TrueClass | FalseClass | NilClass ] bool A boolean or nil value.
# @param [ Boolean ] bool A boolean value.
- **Return Self:** Specify return value ``self`` where a method returns ``self``.
.. code-block:: ruby
# @return [ self ] Returns the object itself.
- **Splat Args:** Use three-dot ellipses ``...`` in the type declaration and
star ``*`` in the parameter name to denote a splat.
.. code-block:: ruby
# @param [ String... ] *items The list of items name(s) as Strings.
def buy_groceries(*items)
- **Splat Args:** Do not use ``Array`` as the type unless each arg is actually an Array.
.. code-block:: ruby
# BAD:
# @param [ Array<String> ] *items The list of items name(s) as Strings.
def buy_groceries(*items)
buy_groceries("Cheese", "Crackers", "Wine")
# OK:
# @param [ Array<String>... ] *arrays One or more arrays containing name parts.
def set_people_names(*arrays)
set_people_names(["Harlan", "Sanders"], ["Jane", "K", ""Doe"], ["Jim", "Beam"])
- **Splat Args:** Use comma ``,`` to denote positionality in a splat.
.. code-block:: ruby
# @param [ Symbol..., Hash ] *args A list of names, followed by a hash
# as the optional last arg.
def say_hello(*args)
- **Splat Args:** Specify type unions with square brackets ``[ ]``.
.. code-block:: ruby
# @param [ [ String | Symbol ]... ] *fields A splat of mixed Symbols and Strings.
- **Keyword Arguments:** Following YARD conventions, use ``@param`` for keyword
arguments, and specify keyword argument names as symbols.
.. code-block:: ruby
# @param [ String ] query The search string
# @param [ Boolean ] :exact_match Whether to do an exact match
# @param [ Integer ] :results_per_page Number of results
def search(query, exact_match: false, results_per_page: 10)
- **Hash Options:** Define hash key-value options with ``@option`` macro
immediately following the Hash ``@param``. Note ``@option`` parameter names
are symbols.
.. code-block:: ruby
# @param opts [ Hash<Symbol, Object> ] The optional hash argument(s).
# @option opts [ String | Array<String> ] :items The items(s) as Strings to include.
# @option opts [ Integer ] :limit An Integer denoting the limit.
def buy_groceries(opts = {})
- **Double Splats:** Use double-star ``**`` in the parameter name to denote a
keyword arg splat (double splat). Note that type does not need declared on
the double-splat element, as it is implicitly <Symbol, Object>. Instead,
define value types with ``@option`` macro below. Note ``@option`` parameter
names are symbols.
.. code-block:: ruby
# @param **kwargs The optional keyword argument(s).
# @option **kwargs [ String | Array<String> ] :items The items(s) as Strings to include.
# @option **kwargs [ Integer ] :limit An Integer denoting the limit.
def buy_groceries(**kwargs)
- **Blocks:** Use ``@yield`` to specify when the method yields to a block.
.. code-block:: ruby
# @yield [ Symbol, Symbol, Symbol ] Evaluate the guess of who did the crime.
# Must take the person, location, and weapon used. Must return true or false.
def whodunit
yield(:mustard, :ballroom, :candlestick)
end
- **Blocks:** If the method explicitly specifies a block argument, specify the block
argument using ``@param`` preceded by an ampersand ``&``, and also specify ``@yield``.
Note ``@yield`` should be used even when method calls ``block.call`` rather than
``yield`` internally.
.. code-block:: ruby
# @param &block The block.
# @yield [ Symbol, Symbol, Symbol ] Evaluate the guess of who did the crime.
# Must take the person, location, and weapon used. Must return true or false.
def whodunit(&block)
yield(:scarlet, :library, :rope)
end
# @param &block The block.
# @yield [ Symbol, Symbol, Symbol ] Evaluate the guess of who did the crime.
# Must take the person, location, and weapon used. Must return true or false.
def whodunit(&block)
block.call(:plum, :kitchen, :pipe)
end
- **Blocks:** Use ``@yieldparam`` and ``@yieldreturn`` instead of ``@yield`` where
beneficial for clarity.
.. code-block:: ruby
# @param &block The block.
# @yieldparam [ Symbol ] The person.
# @yieldparam [ Symbol ] The location.
# @yieldparam [ Symbol ] The weapon used.
# @yieldreturn [ true | false ] Whether the guess is correct.
def whodunit(&block)
yield(:peacock, :conservatory, :wrench)
end
- **Proc Args:** Proc arguments should use ``@param`` (not ``@yield``). The
inputs to the proc may be specified as subtype(s).
.. code-block:: ruby
# @param [ Proc<Integer, Integer, Integer> ] my_proc Proc argument which must
# take 3 integers and must return true or false whether the guess is valid.
def guess_three(my_proc)
my_proc.call(42, 7, 88)
end