From a541fe1a7593f95c5b7d36993cf3fba0ec525574 Mon Sep 17 00:00:00 2001 From: Burdette Lamar Date: Sun, 18 Jul 2021 17:43:34 -0500 Subject: [PATCH] Doc guide for class/module (#4600) Co-authored-by: Marivaldo Cavalheiro --- doc/documentation_guide.rdoc | 281 ++++++++++++++++++++++++++++++++++ doc/method_documentation.rdoc | 211 ------------------------- 2 files changed, 281 insertions(+), 211 deletions(-) create mode 100644 doc/documentation_guide.rdoc delete mode 100644 doc/method_documentation.rdoc diff --git a/doc/documentation_guide.rdoc b/doc/documentation_guide.rdoc new file mode 100644 index 0000000000..38438e94b4 --- /dev/null +++ b/doc/documentation_guide.rdoc @@ -0,0 +1,281 @@ += Documentation Guide + +This guide discusses recommendations for documenting +classes, modules, and methods +in the Ruby core and in the Ruby standard library. + +== Goal + +The goal of Ruby documentation is to impart the most important +and relevant in the shortest time. +The reader should be able to quickly understand the usefulness +of the subject code and how to use it. + +Providing too little information is bad, but providing unimportant +information or unnecessary examples is not good either. +Use your judgment about what the user needs to know. + +== General Guidelines + +- Keep in mind that the reader may not be fluent in \English. +- Write short declarative or imperative sentences. +- Group sentences into (ideally short) paragraphs, + each covering a single topic. +- Organize material with + {headers}[https://docs.ruby-lang.org/en/master/RDoc/Markup.html#class-RDoc::Markup-label-Headers]. +- Refer to authoritative and relevant sources using + {links}[https://docs.ruby-lang.org/en/master/RDoc/Markup.html#class-RDoc::Markup-label-Links]. +- Use simple verb tenses: simple present, simple past, simple future. +- Use simple sentence structure, not compound or complex structure. +- Avoid: + + - Excessive comma-separated phrases; + consider a {list}[https://docs.ruby-lang.org/en/master/RDoc/Markup.html#class-RDoc::Markup-label-Simple+Lists]. + - Idioms and culture-specific references. + - Overuse of headers. + +=== \RDoc + +Ruby is documented using RDoc. +For information on \RDoc syntax and features, see the +{RDoc Markup Reference}[https://docs.ruby-lang.org/en/master/RDoc/Markup.html#class-RDoc::Markup-label-RDoc+Markup+Reference]. + +=== Output from irb + +For code examples, consider using interactive Ruby, +{irb}[https://ruby-doc.org/stdlib/libdoc/irb/rdoc/IRB.html]. + +For a code example that includes +irb+ output, +consider aligning # => ... in successive lines. +Alignment may sometimes aid readability: + + a = [1, 2, 3] #=> [1, 2, 3] + a.shuffle! #=> [2, 3, 1] + a #=> [2, 3, 1] + +=== Headers + +Organize a long discussion with +{headers}[https://docs.ruby-lang.org/en/master/RDoc/Markup.html#class-RDoc::Markup-label-Headers]. + +=== Blank Lines + +A blank line begins a new paragraph. + +A {code block}[https://docs.ruby-lang.org/en/master/RDoc/Markup.html#class-RDoc::Markup-label-Paragraphs+and+Verbatim] +or {list}[https://docs.ruby-lang.org/en/master/RDoc/Markup.html#class-RDoc::Markup-label-Simple+Lists] +should be preceded by and followed by a blank line. +This is unnecessary for the HTML output, but helps in the +ri+ output. + +=== Auto-Linking + +In general, \RDoc's auto-linking should not be suppressed. +For example, we should write +Array+, not \Array. + +We might consider whether to suppress when: + +- The word in question does not refer to a Ruby entity + (e.g., some uses of _Class_ or _English_). +- The reference is to the current class document + (e.g., _Array_ in the documentation for class +Array+). +- The same reference is repeated many times + (e.g., _RDoc_ on this page). + +== Documenting Classes and Modules + +The general structure of the class or module documentation should be: + +* Synopsis +* Common uses, with examples +* "What's Here" summary (optional) + +=== Synopsis + +The synopsis is a short description of what the class or module does +and why the reader might want to use it. +Avoid details in the synopsis. + +=== Common Uses + +Show common uses of the class or module. +Depending on the class or module, this section may vary greatly +in both length and complexity. + +=== What's Here Summary + +The documentation for a class or module may include a "What's Here" section. + +Guidelines: + +- The section title is What's Here. +- Consider listing the parent class and any included modules; consider + {links}[https://docs.ruby-lang.org/en/master/RDoc/Markup.html#class-RDoc::Markup-label-Links] + to their "What's Here" sections if those exist. +- List methods as a {labeled list}[https://docs.ruby-lang.org/en/master/RDoc/Markup.html#class-RDoc::Markup-label-Labeled+Lists]. +- Each list entry's label is a method name; + if the method has aliases, include those with the "base" method method, + and do not list them separately. +- Check the rendered documentation to determine whether \RDoc has recognized + the method and linked to it; if not, manually insert a + {link}[https://docs.ruby-lang.org/en/master/RDoc/Markup.html#class-RDoc::Markup-label-Links]. +- Each entry's description is a 1-line synopsis for the method. +- Keep the description short. +- If there are more entries, consider gouping them into subsections with headers. +- If there are more than a few such subsections, + consider adding a table of contents just below the main section title. + +== Documenting Methods + +=== General Structure + +The general structure of the method documentation should be: + +* Calling sequence (for methods written in C). +* Synopsis (short description). +* Details and examples. +* Argument description (if necessary). +* Corner cases and exceptions. +* Aliases. +* Related methods (optional). + +=== Calling Sequence (for methods written in C) + +For methods written in Ruby, \RDoc documents the calling sequence automatically. + +For methods written in C, \RDoc cannot determine what arguments +the method accepts, so those need to be documented using \RDoc directive +{:call-seq:}[https://docs.ruby-lang.org/en/master/RDoc/Markup.html#class-RDoc::Markup-label-Method+arguments]. + +Example: + + * 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 omitted 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 omitted. + +Omit aliases from the call-seq, but mention them near the end (see below). + + +A +call-seq+ block should have {|x| ... }, not {|x| block } or {|x| code }. + +A +call-seq+ output should: + +- Have +self+, not +receiver+ or +array+. +- Begin with +new_+ if and only if the output object is a new instance + of the receiver's class, to emphasize that the output object is not +self+. + +=== 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 convertible 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 a +{labeled list}[https://docs.ruby-lang.org/en/master/RDoc/Markup.html#class-RDoc::Markup-label-Labeled+Lists]} + +=== 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 a \KeyError. + +=== Aliases + +Mention aliases in the form + + Array#find_index is an alias for Array#index. + +=== 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 +\Hash#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. diff --git a/doc/method_documentation.rdoc b/doc/method_documentation.rdoc deleted file mode 100644 index 83cd1ad632..0000000000 --- a/doc/method_documentation.rdoc +++ /dev/null @@ -1,211 +0,0 @@ -= Method Documentation Guide - -This guide discusses recommendations for documenting methods for Ruby core -classes and classes in the standard library. - -== Goal - -The goal when documenting 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 -* Aliases -* 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 omitted 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 omitted. - -Omit aliases from the call-seq. - -== 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 convertible 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. - -== Aliases - -Mention aliases in the form "Array#find_index is an alias for Array#index." - -== 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. - -=== Output from irb - -Consider whether # => ... in successive codeblock lines should be aligned. -Alignment may sometimes aid readability. - -=== Lists - -A list should be preceded by and followed by a blank line. -This is unnecessary for the HTML output, but helps in the +ri+ output. - -=== Call-Seq - -A +call-seq+ block should have {|x| ... }, not {|x| block } or {|x| code }. - -A +call-seq+ output should: -- Have +self+, not +receiver+ or +array+. -- Begin with +new_+ if and only if the output object is a new instance of the receiver's class, - to emphasize that the output object is not +self+. - -=== Auto-Links - -In general, RDoc's auto-linking should not be suppressed. -For example, we should write +Array+, not \Array. - -We might consider whether to suppress when: -- The word in question does not refer to a Ruby class (e.g., some uses of _Class_ or _English_). -- The reference is to the current class (e.g., _Array_ in the documentation for class +Array+)..