-
-
Notifications
You must be signed in to change notification settings - Fork 401
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Documenting keys in a return value #425
Comments
While I'm more or less on the fence with this proposal, I'm leaning heavily towards saying this should probably not be added, for a few reasons. First, a technicality: it would really be an "options hash", so The other issue with this is that it's extremely volatile documentation. What you are effectively doing by returning a Hash is defining an ad-hoc interface in your return field. It's not very reusable, and it's inherently uneasy to document-- and because documentation is communication, it's not very easy to communicate this to your users. I used a similar Hash returning method as an example of bad docs in my RubyConf 11 talk. This is a scenario where you will quickly lose sync with the implementation because of the volatile nature of a Hash interface, and it's even harder for your users to track what those changes are, if they occur. If this is really necessary, you can define your own tags via the YARD commandline (or .yardopts). You could define a custom Another way to do this, and my personal recommendation, is to refactor any ad-hoc interfaces into real classes or modules. You don't strictly need to use these classes, they can be dummy classes, but then you can refer to those classes as the official "interface" for the object being returned. Consider: # @return [MyInterface] the data returned from space!
def foo
{:a => 1, :b => 2}
end
# @abstract
# @todo We could subclass OpenStruct here if we really wanted
class MyInterface
# Documentation for the +a+ key
attr_accessor :a
# Documentation for the +b+ key
attr_accessor :b
# Hash-like interface to access keys in the +[]+ syntax.
def [](key) self.send(key) end
# Hash-like interface to access keys in the +[]=+ syntax.
def []=(key, value) self.send("#{key}=", value) end
end Note that we are still returning the object as a Hash (which might be a requirement if you're pulling this data from another lib or data source)-- but the interface is defined as being of type MyInterface (you might want to The above are my objections-- but I'm open to your views too. Like I said, I'm on the fence about this, but I'm leaning pretty heavily to saying we should do this via plugin if at all. |
While I agree that returning a hash may be an indication of poor OO practice, I don't agree that a documentation system should be enforcing coding standards. It seems to me that providing the tag is unambiguously better than the arbitrary, inconsistent solutions out there like @returns [Hash<:Symbol Value, :Symbol Value>], @returns [Hash{:symbol=>value,:symbol=>value}], or even worse, just @returns [Hash] with nothing else. That said, if something like this were added, I agree that making the tag return-value specific is more accurate than using @options. Perhaps the more general name @return_detail could be used for appending an unordered list of items to a return value in the same way @options does for params? |
I suppose this is where we would disagree. It's certainly not enforcing any coding standards, because there are a hundred and one different ways to workaround this, but there is certainly a concept of "documentable" and "undocumentable" coding standards. Documentation is definitely tied and influenced by the way you structure your code (down to the way you name your code). One of the goals of YARD is to improve the documentation in the Ruby community. In doing so, this also means attempting to break some of the bad coding practices in order to make code more documentable. This means getting rid of some poor documentation practices, but also means making recommendations about poor structural practices-- like abusing dynamic module inclusion (ie. ClassMethods & InstanceMethods) as well as the overuse of metaprogramming (which is inherently undocumentable). I would say that the approach YARD takes is often pragmatic, not idiomatic, and we try to bridge the gap as much as possible, but there are certainly practices that make for better documentation. I don't think YARD should encourage the breaking of these best practices, and for that reason, I think adding this kind of functionality into core would undercut this important goal of the project. The way I see it, YARD takes on the Ruby principle of making ugly things look ugly, not by "enforcement", but just by "annoyance". You can document hashes in a return by either defining a custom tag or by marking up your own list in a # @return [Hash]
# * :key [String] a key that accepts a string object
# * :otherkey [Date] the date object to pass in
# ... It won't look quite as nice as options, but that's the whole "ugly things should look ugly" principle that Ruby follows, too. That said, YARD also allows you to extend the behaviour and implement this kind of a feature through plugins and even custom tags on the command line. So you could (and quite easily, I might add) extend YARD to have an options tag named |
Closing because this hasn't really gone anywhere in a while. Just to summarize, YARD isn't enforcing coding standards here, we just don't [currently] fully support weakly structured API designs. In other words, you can document the behaviour, it just won't look very pretty, because there is no special way to display these kinds of return values. Frankly, I'm not sure how to do this any better than we do right now, but if you can figure out a way, I would gladly look at a pull request for this. |
+1 for a slightly different feature: specification of key and value types in hashes using the syntax YARD already supports @lsegal the |
@ssimeonov YARD supports |
Note that you can also just use the more "generic friendly" style of |
ail |
Say you have:
@return [Hash]
...and you want to document the keys within. I can't find in the docs anywhere that states how to do this. I've tried several different variations of @options whatever [type] key desc with no luck.
Wouldn't it make sense to have:
@options return [type] key description be supported in the same way it is for params?
The text was updated successfully, but these errors were encountered: