Home > Software design >  How can I document a subclass method with YARD?
How can I document a subclass method with YARD?

Time:12-02

How can I document a method that a subclass overrides without being redundant? For example...

class Parent
  # Is this the parent?
  # @return [Boolean]
  def parent?
    true
  end
end

class Child < Parent
  def parent?
    false
  end
end

YARD generates something like this.

Class: Parent

Instance Method Summary

#parent? ⇒ Boolean

Is this the parent?.

Class: Child

Instance Method Summary

#parent? ⇒ Boolean

The generated YARD documentation will not include "Is this the parent?" in the docs for Child#parent?, nor will it indicate that it is an override.

I would like to see something like this:

Class: Parent

Instance Method Summary

#parent? ⇒ Boolean

Is this the parent?.

Class: Child

Instance Method Summary

#parent? ⇒ Boolean

Is this the parent?.

Methods inherited from Parent

#parent?

I would prefer not to have to copy the documentation into every subclass.

CodePudding user response:

Simple Answer

The correct way to document this is to place a free-form description after the return type, and maybe document the method itself. For example:

class Parent
  # True when a passed argument has Parent
  # as an ancestor.
  #
  # @return [Boolean] ancestor of subclass
  def parent?
    true
  end
end

A More Comprehensive Example

You can also provide examples of usage and more detailed documentation by leveraging the free-form parts of the tag syntax and your markup language (RDoc by default).

class Parent
  # True when passed argument includes
  #  Parent  as an ancestor.
  #
  # @example Cousin isn't subclass of Parent
  #   parent? Cousin.new #=> false
  # @example Child is a subclass of Parent
  #   parent? Child.new #=> true
  # @param obj [Class, #ancestors] Class,
  #   instance, or other object that can
  #   #respond_to?(:ancestors)
  # @return [Boolean] ancestors of _obj_
  #   includes  Parent  class
  def parent? obj
    obj.class.ancestors.include? self.class
  end
end

There may be more elegant ways to do this, and I'm typing on a phone so caveat emptor with the code as I haven't actually tested the code or validated the formatting of the YARD output. Still, the general approach is sound and I use this type of formatting routinely.

Core Ideas

Basically, the core ideas are that one should:

  1. Place your description of each tagged item in-line if you want it associated with that item. Most tags support free-form descriptions or titles which will be formatted in a way that visually associates them with the tagged element.
  2. Use tags and formatting for classes, methods, arguments, examples, and so on. You don't have to cram it all into a single tag, although in your specific example you probably want to do so to keep things visually associated.
  3. You can wrap long free-form text with indentation in most cases.
  4. There are a few exceptions to wrapping (e.g. example titles vs. indented code blocks is illustrative) but you can often work around that with RDoc or Markdown syntax.
  5. If you can't get what you want, refer to item four for some alternative approaches or find a different tag or markup to represent your intent.
  6. Macros, custom tags, and directives will let you do weird and wonderful things if you can't get what you want out of the box. NB: I've almost never needed to resort to this, but the features are there if you need them.

In most cases, simpler is better. Understanding how and when YARD can't succinctly represent your authorial intent is admittedly a bit of an art form, but code that's hard to tag or render as expected may indicate a need to refactor the code rather than just modifying the YARD tags.

Keep YARD's Main Purpose in Mind

Just remember that YARD is primarily for ** elements of your documentation, and providing hints to a rendering engine or document reader, It's not a full-fledged markup language by itself, can't validate signatures like RBS with Steep, and doesn't enforce any sort of caller/callee contract.

It's all just comments. Make your code as self-explanatory as possible, then treat YARD as just one way to improve necessary comments by tagging documentation elements so the markup language generates better output.

CodePudding user response:

You can use a reference tag on each individual method to refer to the Parent methods.

class Child < Parent
  # (see Parent#parent?)
  def parent?
    false
  end
end

Child#parent? will have the same documentation as Parent::parent?

  • Related