From d43e99b7220ae3a7fbd58fbc8bde74085f6bd14c Mon Sep 17 00:00:00 2001 From: Jeremy Evans Date: Mon, 10 Aug 2020 12:47:31 -0700 Subject: [PATCH] Add Method Documentation Guide (#3399) This documents how methods for core classes and classes in the standard library should be documented. Co-authored-by: Eric Hodel --- doc/method_documentation.rdoc | 176 ++++++++++++++++++++++++++++++++++ 1 file changed, 176 insertions(+) create mode 100644 doc/method_documentation.rdoc diff --git a/doc/method_documentation.rdoc b/doc/method_documentation.rdoc new file mode 100644 index 0000000000..d13a334ba5 --- /dev/null +++ b/doc/method_documentation.rdoc @@ -0,0 +1,176 @@ += Method Documentation Guide + +This guide discusses recommendations for documenting methods for Ruby core +classes and classes in the standard library. + +== Goal + +The goal when documentating a method is to impart the most important +information about the method in the least amount of time. A reader +of the method documentation should be able to quickly understand +the purpose of the method and how to use it. Providing too little +information about the method is not good, but providing unimportant +information or unnecessary examples is not good either. Use your +judgment about what the user of the method needs to know to use the +method correctly. + +== General Structure + +The general structure of the method documentation should be: + +* call-seq (for methods written in C) +* Synopsis (Short Description) +* Details and Examples +* Argument Description (if necessary) +* Corner Cases and Exceptions +* Related Methods (optional) + +== call-seq (for methods written in C) + +For methods written in C, RDoc cannot determine what arguments +the method accepts, so those need to be documented using a +call-seq. Here's an example call-seq: + + * call-seq: + * array.count -> integer + * array.count(obj) -> integer + * array.count {|element| ... } -> integer + +When creating the call-seq, use the form + + receiver_type.method_name(arguments) {|block_arguments|} -> return_type + +Omit the parentheses for cases where the method does not accept arguments, +and omit the block for cases where a block is not accepted. + +In the cases where method can return multiple different types, separate the +types with "or". If the method can return any type, use "object". If the +method returns the receiver, use "self". + +In cases where the method accepts optional arguments, use a call-seq +with an optional argument if the method has the same behavior when an argument +is ommitted as when the argument is passed with the default value. For example, +use: + + * obj.respond_to?(symbol, include_all=false) -> true or false + +Instead of: + + * obj.respond_to?(symbol) -> true or false + * obj.respond_to?(symbol, include_all) -> true or false + +However, as shown above for Array#count, use separate lines if the +behavior is different if the argument is ommitted. + +== Synopsis + +The synopsis comes next, and is a short description of what the +method does and why you would want to use it. Ideally, this +is a single sentence, but for more complex methods it may require +an entire paragraph. + +For Array#count, the synopsis is: + + Returns a count of specified elements. + +This is great as it is short and descriptive. Avoid documenting +too much in the synopsis, stick to the most important information +for the benefit of the reader. + +== Details and Examples + +Most non-trivial methods benefit from examples, as well as details +beyond what is given in the synopsis. In the details and examples +section, you can document how the method handles different types +of arguments, and provides examples on proper usage. In this +section, focus on how to use the method properly, not on how the +method handles improper arguments or corner cases. + +Not every behavior of a method requires an example. If the method +is documented to return +self+, you don't need to provide an example +showing the return value is the same as the receiver. If the method +is documented to return +nil+, you don't need to provide an example +showing that it returns +nil+. If the details mention that for a +certain argument type, an empty array is returned, you don't need +to provide an example for that. + +Only add an example if it provides the user additional information, +do not add an example if it provides the same information given +in the synopsis or details. The purpose of examples is not to prove +what the details are stating. + +== Argument Description (if necessary) + +For methods that require arguments, if not obvious and not explicitly +mentioned in the details or implicitly shown in the examples, you can +provide details about the types of arguments supported. When discussing +the types of arguments, use simple language even if less-precise, such +as "level must be an integer", not "level must be an Integer-convertible +object". The vast majority of use will be with the expected type, not an +argument that is explicitly convertable to the expected type, and +documenting the difference is not important. + +For methods that take blocks, it can be useful to document the type of +argument passed if it is not obvious, not explicitly mentioned in the +details, and not implicitly shown in the examples. + +If there is more than one argument or block argument, use an RDoc +definition list: + +argument_name1 :: type and description +argument_name2 :: type and description + +== Corner Cases and Exceptions + +For corner cases of methods, such as atypical usage, briefly mention +the behavior, but do not provide any examples. + +Only document exceptions raised if they are not obvious. For example, +if you have stated earlier than an argument type must be an integer, +you do not need to document that a TypeError is raised if a non-integer +is passed. Do not provide examples of exceptions being raised unless +that is a common case, such as Hash#fetch raising KeyError. + +== Related Methods (optional) + +In some cases, it is useful to document which methods are related to +the current method. For example, documentation for Hash#[] might +mention Hash#fetch as a related method, and Hash#merge might mention +#merge! as a related method. Consider which methods may be related +to the current method, and if you think the reader would benefit it, +at the end of the method documentation, add a line starting with +"Related: " (e.g. "Related: #fetch"). Don't list more than three +related methods. If you think more than three methods are related, +pick the three you think are most important and list those three. + +== Methods Accepting Multiple Argument Types + +For methods that accept multiple argument types, in some cases it can +be useful to document the different argument types separately. It's +best to use a separate paragraph for each case you are discussing. + +== Use of English + +Readers of this documentation may not be native speakers of English. +Documentation should be written with this in mind. + +Use short sentences and group them into paragraphs that cover a single +topic. Avoid complex verb tenses, excessive comma-separated phrases, +and idioms. + +When writing documentation, define unusual or critical concepts in +simple language. Provide links to authoritative sources, or add a +general description to the top-level documentation for the class or +module. + +== Formatting + +Extraneous formatting such as headings and horizontal lines should be +avoided in general. It is best to keep the formatting as simple as +possible. Only use headings and other formatting for the most complex +cases where the method documentation is very long due to the complexity +of the method. + +Methods are documented using RDoc syntax. See the +{RDoc Markup Reference}[https://docs.ruby-lang.org/en/master/RDoc/Markup.html#class-RDoc::Markup-label-RDoc+Markup+Reference] +for more information on formatting with RDoc syntax.