I'm writing some javadocs (actually they are jsdocs but it doesn't make a difference for this question) and found this repeating pattern:
Imagine a method that just returns a value, maybe product of some calculation. For example, let say it is the time in milliseconds since the unix epoch.
public long getTimeSinceTheEpoch(){
//calculate time
return time;
}
So far, so good. Now when the time comes to add javadocs (or jsdocs, or rdocs, whatever), I've been writing something like this:
/**
* Gets the time in milliseconds since the unix epoch
*
* #returns the time in milliseconds since the unix epoch
*/
public long getTimeSinceTheEpoch(){
Here, the problem is obvious.
My question is, what do you put in the body of the comment, and what do you choose for the #returns attribute of the comment?
IMPORTANT
I'm not a fan of these kind of comments, if it depended on me I would rename the method to something like getTimeInMillisecondsSinceTheEpoch and avoid the comments at all.
I cannot do that (avoid the comments), so I'm striving to make them as useful as possible.
Best is to provide only the #return description as you need to document what you are returning for sure.
In the comment section, you could also throw in that same one-liner but also add how you are going to go about returning what you return, for e.g.
/**
* Gets the time in milliseconds since the unix epoch
* by doing something incredible.
* http://stackoverflow.com/questions/4307142/documenting-a-method-that-just-returns-something
*
* #note thank you stackoverflow
*
* #returns the time in milliseconds since the unix epoch
*/
public long getTimeSinceTheEpoch(){
The Sun (now Oracle) style guide "How to Write Doc Comments for the Javadoc Tool" recommends this:
The #return tag is required for every
method that returns something other
than void, even if it is redundant
with the method description. (Whenever
possible, find something non-redundant
(ideally, more specific) to use for
the tag comment.)
I'm not fond of the redundancy, and it goes against the DRY principle. Personally, I either make one a summary and the other a detail (as suggested above), or provide only an #return. As you point out, the name of a simple getter may suffice as the summary.
Related
We used to use the guava cache and we want to change it to caffeine.
We want to set for each entity its own "expiration time", something like - put(K key, V value, long expiration_time).
I saw the 3 functions above and I wonder what exactly they are doing, if you can explain me the meaning ant the operations of each one of them it will be great.
For example, the return value of expireAfterCreate should be the duration we want for this entity from it's creation untill it's expiration? or something else?
I'm also wondering why we have the parameter "currentTime" in both expireAfterRead and expireAfterUpdate if we don't use it in the function?
When we used the guava cache we used the expireAfterAccess, what is the substitution for it in caffeine?
My last question is how can I set a default value for entities without a unique expiration time.
Thank you,
May
When we used the guava cache we used the expireAfterAccess, what is the substitution for it in caffeine?
We mirror the Guava API, so this is also available on the cache builder.
My last question is how can I set a default value for entities without a unique expiration time.
Use expireAfterAccess, expireAfterWrite, or return a constant duration with expireAfter(Expiry).
I saw the 3 functions above and I wonder what exactly they are doing, if you can explain me the meaning ant the operations of each one of them it will be great.
Expiry is a callback interface where a single timestamp value is updated. The invoked method corresponds to the operation performed on the cache entry (created, updated, read). An update or read that should have no effect can return currentDuration to no-op.
For example, the return value of expireAfterCreate should be the duration we want for this entity from it's creation untill it's expiration? or something else?
Yes. However if the expireAfterUpdate returns a custom value (something other than currentDuration), then that overrides the prior expiration duration.
I'm also wondering why we have the parameter "currentTime" in both expireAfterRead and expireAfterUpdate if we don't use it in the function?
This can most often be ignored, but is provided if somehow useful. It is the current nano timestamp from the Ticker (not wall clock time).
We want to set for each entity its own "expiration time", something like - put(K key, V value, long expiration_time).
The callback Expiry is required and generally recommended, because ideally entries are loaded through the cache to avoid stampedes (e.g. LoadingCache). A stampede is when multiple threads lookup the same entry, miss, load it, and overwrite each other putting it in. That wasted work rather than having only one thread perform the load and others wait for the results.
That said, this method is available under Cache.policy().expiresVariably(). Those configuration-specific methods are stashed in that area to offer more power when deemed necessary.
Thank you,
You're very welcome.
I'll take a real example I have to implement in a program I'm coding:
I have a database that has the score of every game bowled in the past three years in a bowling center. With a GUI, you can choose to either search for the best score on each lane, search for the best score between two dates, for the best score for each week, etc.
I'm wondering what the best way to implement this is. Should I code something like this:
public Vector<Scores> grabMaxScores(sortType, param1, param2)
{
if(sortType.equals("By lane"))
...
else if(sortType.equals("Between given dates")
...
}
Or is it more appropriate to code different methods for each type and call the correct one in the listener?
public Vector<Scores> grabMaxScoresBetweenDates(startDate, endDate)
{
...
}
public Vector<Scores> grabMaxScoresByLane(minLane, maxLane)
{
...
}
I'm not necessarily asking for this particular problem, it's just a question I find asking myself often when I'm coding multiple methods that are alike where the principle is the same, but the parameters are different.
I can see there are good reasons to use each of them, but I want to know if there is a "more correct" or standard way of coding this.
In my personal opinion, I would prefer your second option over the first. This is because you have the opportunity to be precise about things like the types of the parameters. For example, minLane and maxLane may just be integers, but startDate and endDate could very well be Date objects. It's often nicer if you can actually specify what you expect, as it reduces the need for such things as casting and range checks, etc. Also, I would find it more readable, as the function names just say what you are trying to do.
However, I may have an alternative idea, which is kind of a variation on your first example (I actually got this inspiration from Java's Comparator, in case you're familiar with that). Rather than pass a string as the first argument, pass some sort of Selector object. Selector would be the name of a class or a interface, which would look something like so (in Java):
interface Selector {
public void select(Score next);
public Score getBest( );
}
If the select method "likes" the value of next which is given to it, it can store the value for later. If it doesn't like it, it can simply discard it, and keep whatever value it already has. After all the data is processed, the best value will be left over, and can be requested by calling getBest. Of course, you can alter the interface to suit your particular needs (e.g. it seems like you might be expecting more than one value to be retrieved. Also, generics might help a lot as well).
The reason I like this idea is that now your function is very general purpose. In order to add new functionality, you don't need to add functions, and you don't need to modify any functions you already have. Instead, the user of your code can simply define their own implementation of Selector as they see fit. This allows your code to be far more compositional, which makes it easier to use. The only inconvenience is the need to define implementations of Selector, though, you could also provide several default ones.
The approach you have used would also work. But if you want to add some new functionality like "get lowest scores on Friday evening", you will need to add one more function, which kinda not so good thing to do.
As you have already have the data in a database you can generate database queries which would fetch the required results and display. So you need not modify your code every time.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 5 years ago.
Improve this question
For simple getters/setters, like the one below, what's the best way to document it?
public float getPrice()
{
return price;
}
I'm pretty strict about coding standards, so my IDE warns me about any undocumented public/protected methods.
Option 1:
/**
* Get the price field.
*
* #return
*/
Option 2:
/**
* #return Price
*/
Or don't document it at all?
If "price" is anything other than the most obvious value, then your comment should describe what "Price" means and is used for, not just what it is called.
Some hypothetical examples:
Is it the "price before tax" or the "price including tax"?
Is it expressed in dollars, euros or pounds?
Is it rounded to the nearest cent, 5 cents, or dollars?
Is a special value returned to indicate a free item (e.g. 0.0f)?
Can a price be "uninitialised", and if so, what value is returned (e.g. -1.0f)?
For a good proportion of methods and properties, there is something you can say that tells the reader more than just the name will tell them. That will save other progammers a lot of time and reduce the risk of bugs. Even if it merely confirms their guesses/assumptions, it will still save them time.
In the case of "simple" values that are totally self-explanatory (e.g. Rectangle.Width), then don't waste your time typing - AtomineerUtils will create that level of documentation for you with a single keypress. (The advantage of AtomineerUtils in your case is that it supports Doxygen, Javadoc and Documentation XML comment formats, and VB, C#, C++/CLI, C++ and C code, so you can retain your existing format while massively reducing the time you spend on documentation commenting. GhostDoc will do a similar job, but it only supports Xml documentation for VB and C#)
I'd write the bare minimum to keep the linter quiet. If it's obvious what the getter/setter is getting/setting, I'd use some copy-paste documentation that makes it clear that nothing fancy is going on:
/**
* Simple getter.
* #return Price
*/
I personally consider too many getters and setters to be a code smell, as it's a possible sign that you're not providing operations at the correct level of abstraction (this is obviously not always true, but a rule of thumb).
Describe the minimum for another programmer to understand what the method does or returns.
I would use this:
/**
* #return the price.
*/
or
/**
* Returns the prize.
*
* #return the price.
*/
This duplicates the same text, but a it might be necessary if you agreed on certain coding standards that require a description and not only the tags.
I would not mention that it returns the price field, since that describes the internal representation.
Document the interface as if the user knew nothing about the implementation. The docs are for callers of the method, who don't have to know or care what the specific internal state is, but do have to care what the method does for them.
I was looking for a standard way to doco functions until i searched SO and found people using:
GhostDoc - http://submain.com/products/ghostdoc.aspx
It's one of the best auto doco tools out there and formats each of your comments the same way. The best thing about it is if your methods are aptly named, then you don't even need to edit the auto-generated doco as it will make sense.
Also, the comments comes up when you use intellisense so you can be reminded of what your code does a month after you've written it! :)
GhostDocs will do this to your property: (shortcut Ctrl+Shift+D)
/// <summary>
/// Gets the price.
/// </summary>
/// <returns></returns>
public float getPrice()
{
return price;
}
Similar to Is hard-coding literals ever acceptable?, but I'm specifically thinking of "magic strings" here.
On a large project, we have a table of configuration options like these:
Name Value
---- -----
FOO_ENABLED Y
BAR_ENABLED N
...
(Hundreds of them).
The common practice is to call a generic function to test an option like this:
if (config_options.value('FOO_ENABLED') == 'Y') ...
(Of course, this same option may need to be checked in many places in the system code.)
When adding a new option, I was considering adding a function to hide the "magic string" like this:
if (config_options.foo_enabled()) ...
However, colleagues thought I'd gone overboard and objected to doing this, preferring the hard-coding because:
That's what we normally do
It makes it easier to see what's going on when debugging the code
The trouble is, I can see their point! Realistically, we are never going to rename the options for any reason, so about the only advantage I can think of for my function is that the compiler would catch any typo like fo_enabled(), but not 'FO_ENABLED'.
What do you think? Have I missed any other advantages/disadvantages?
If I use a string once in the code, I don't generally worry about making it a constant somewhere.
If I use a string twice in the code, I'll consider making it a constant.
If I use a string three times in the code, I'll almost certainly make it a constant.
if (config_options.isTrue('FOO_ENABLED')) {...
}
Restrict your hard coded Y check to one place, even if it means writing a wrapper class for your Map.
if (config_options.isFooEnabled()) {...
}
Might seem okay until you have 100 configuration options and 100 methods (so here you can make a judgement about future application growth and needs before deciding on your implementation). Otherwise it is better to have a class of static strings for parameter names.
if (config_options.isTrue(ConfigKeys.FOO_ENABLED)) {...
}
I realise the question is old, but it came up on my margin.
AFAIC, the issue here has not been identified accurately, either in the question, or the answers. Forget about 'harcoding strings" or not, for a moment.
The database has a Reference table, containing config_options. The PK is a string.
There are two types of PKs:
Meaningful Identifiers, that the users (and developers) see and use. These PKs are supposed to be stable, they can be relied upon.
Meaningless Id columns which the users should never see, that the developers have to be aware of, and code around. These cannot be relied upon.
It is ordinary, normal, to write code using the absolute value of a meaningful PK IF CustomerCode = "IBM" ... or IF CountryCode = "AUS" etc.
referencing the absolute value of a meaningless PK is not acceptable (due to auto-increment; gaps being changed; values being replaced wholesale).
.
Your reference table uses meaningful PKs. Referencing those literal strings in code is unavoidable. Hiding the value will make maintenance more difficult; the code is no longer literal; your colleagues are right. Plus there is the additional redundant function that chews cycles. If there is a typo in the literal, you will soon find that out during Dev testing, long before UAT.
hundreds of functions for hundreds of literals is absurd. If you do implement a function, then Normalise your code, and provide a single function that can be used for any of the hundreds of literals. In which case, we are back to a naked literal, and the function can be dispensed with.
the point is, the attempt to hide the literal has no value.
.
It cannot be construed as "hardcoding", that is something quite different. I think that is where your issue is, identifying these constructs as "hardcoded". It is just referencing a Meaningfull PK literally.
Now from the perspective of any code segment only, if you use the same value a few times, you can improve the code by capturing the literal string in a variable, and then using the variable in the rest of the code block. Certainly not a function. But that is an efficiency and good practice issue. Even that does not change the effect IF CountryCode = #cc_aus
I really should use constants and no hard coded literals.
You can say they won't be changed, but you may never know. And it is best to make it a habit. To use symbolic constants.
In my experience, this kind of issue is masking a deeper problem: failure to do actual OOP and to follow the DRY principle.
In a nutshell, capture the decision at startup time by an appropriate definition for each action inside the if statements, and then throw away both the config_options and the run-time tests.
Details below.
The sample usage was:
if (config_options.value('FOO_ENABLED') == 'Y') ...
which raises the obvious question, "What's going on in the ellipsis?", especially given the following statement:
(Of course, this same option may need to be checked in many places in the system code.)
Let's assume that each of these config_option values really does correspond to a single problem domain (or implementation strategy) concept.
Instead of doing this (repeatedly, in various places throughout the code):
Take a string (tag),
Find its corresponding other string (value),
Test that value as a boolean-equivalent,
Based on that test, decide whether to perform some action.
I suggest encapsulating the concept of a "configurable action".
Let's take as an example (obviously just as hypthetical as FOO_ENABLED ... ;-) that your code has to work in either English units or metric units. If METRIC_ENABLED is "true", convert user-entered data from metric to English for internal computation, and convert back prior to displaying results.
Define an interface:
public interface MetricConverter {
double toInches(double length);
double toCentimeters(double length);
double toPounds(double weight);
double toKilograms(double weight);
}
which identifies in one place all the behavior associated with the concept of METRIC_ENABLED.
Then write concrete implementations of all the ways those behaviors are to be carried out:
public class NullConv implements MetricConverter {
double toInches(double length) {return length;}
double toCentimeters(double length) {return length;}
double toPounds(double weight) {return weight;}
double toKilograms(double weight) {return weight;}
}
and
// lame implementation, just for illustration!!!!
public class MetricConv implements MetricConverter {
public static final double LBS_PER_KG = 2.2D;
public static final double CM_PER_IN = 2.54D
double toInches(double length) {return length * CM_PER_IN;}
double toCentimeters(double length) {return length / CM_PER_IN;}
double toPounds(double weight) {return weight * LBS_PER_KG;}
double toKilograms(double weight) {return weight / LBS_PER_KG;}
}
At startup time, instead of loading a bunch of config_options values, initialize a set of configurable actions, as in:
MetricConverter converter = (metricOption()) ? new MetricConv() : new NullConv();
(where the expression metricOption() above is a stand-in for whatever one-time-only check you need to make, including looking at the value of METRIC_ENABLED ;-)
Then, wherever the code would have said:
double length = getLengthFromGui();
if (config_options.value('METRIC_ENABLED') == 'Y') {
length = length / 2.54D;
}
// do some computation to produce result
// ...
if (config_options.value('METRIC_ENABLED') == 'Y') {
result = result * 2.54D;
}
displayResultingLengthOnGui(result);
rewrite it as:
double length = converter.toInches(getLengthFromGui());
// do some computation to produce result
// ...
displayResultingLengthOnGui(converter.toCentimeters(result));
Because all of the implementation details related to that one concept are now packaged cleanly, all future maintenance related to METRIC_ENABLED can be done in one place. In addition, the run-time trade-off is a win; the "overhead" of invoking a method is trivial compared with the overhead of fetching a String value from a Map and performing String#equals.
I believe that the two reasons you have mentioned, Possible misspelling in string, that cannot be detected until run time and the possibility (although slim) of a name change would justify your idea.
On top of that you can get typed functions, now it seems you only store booleans, what if you need to store an int, a string etc. I would rather use get_foo() with a type, than get_string("FOO") or get_int("FOO").
I think there are two different issues here:
In the current project, the convention of using hard-coded strings is already well established, so all the developers working on the project are familiar with it. It might be a sub-optimal convention for all the reasons that have been listed, but everybody familiar with the code can look at it and instinctively knows what the code is supposed to do. Changing the code so that in certain parts, it uses the "new" functionality will make the code slightly harder to read (because people will have to think and remember what the new convention does) and thus a little harder to maintain. But I would guess that changing over the whole project to the new convention would potentially be prohibitively expensive unless you can quickly script the conversion.
On a new project, symbolic constants are the way IMO, for all the reasons listed. Especially because anything that makes the compiler catch errors at compile time that would otherwise be caught by a human at run time is a very useful convention to establish.
Another thing to consider is intent. If you are on a project that requires localization hard coded strings can be ambiguous. Consider the following:
const string HELLO_WORLD = "Hello world!";
print(HELLO_WORLD);
The programmer's intent is clear. Using a constant implies that this string does not need to be localized. Now look at this example:
print("Hello world!");
Here we aren't so sure. Did the programmer really not want this string to be localized or did the programmer forget about localization while he was writing this code?
I too prefer a strongly-typed configuration class if it is used through-out the code. With properly named methods you don't lose any readability. If you need to do conversions from strings to another data type (decimal/float/int), you don't need to repeat the code that does the conversion in multiple places and can cache the result so the conversion only takes place once. You've already got the basis of this in place already so I don't think it would take much to get used to the new way of doing things.
Do you often see in API documentation (as in 'javadoc of public functions' for example) the description of "value limits" as well as the classic documentation ?
Note: I am not talking about comments within the code
By "value limits", I mean:
does a parameter can support a null value (or an empty String, or...) ?
does a 'return value' can be null or is guaranteed to never be null (or can be "empty", or...) ?
Sample:
What I often see (without having access to source code) is:
/**
* Get all readers name for this current Report. <br />
* <b>Warning</b>The Report must have been published first.
* #param aReaderNameRegexp filter in order to return only reader matching the regexp
* #return array of reader names
*/
String[] getReaderNames(final String aReaderNameRegexp);
What I like to see would be:
/**
* Get all readers name for this current Report. <br />
* <b>Warning</b>The Report must have been published first.
* #param aReaderNameRegexp filter in order to return only reader matching the regexp
* (can be null or empty)
* #return array of reader names
* (null if Report has not yet been published,
* empty array if no reader match criteria,
* reader names array matching regexp, or all readers if regexp is null or empty)
*/
String[] getReaderNames(final String aReaderNameRegexp);
My point is:
When I use a library with a getReaderNames() function in it, I often do not even need to read the API documentation to guess what it does. But I need to be sure how to use it.
My only concern when I want to use this function is: what should I expect in term of parameters and return values ? That is all I need to know to safely setup my parameters and safely test the return value, yet I almost never see that kind of information in API documentation...
Edit:
This can influence the usage or not for checked or unchecked exceptions.
What do you think ? value limits and API, do they belong together or not ?
I think they can belong together but don't necessarily have to belong together. In your scenario, it seems like it makes sense that the limits are documented in such a way that they appear in the generated API documentation and intellisense (if the language/IDE support it).
I think it does depend on the language as well. For example, Ada has a native data type that is a "restricted integer", where you define an integer variable and explicitly indicate that it will only (and always) be within a certain numeric range. In that case, the datatype itself indicates the restriction. It should still be visible and discoverable through the API documentation and intellisense, but wouldn't be something that a developer has to specify in the comments.
However, languages like Java and C# don't have this type of restricted integer, so the developer would have to specify it in the comments if it were information that should become part of the public documentation.
I think those kinds of boundary conditions most definitely belong in the API. However, I would (and often do) go a step further and indicate WHAT those null values mean. Either I indicate it will throw an exception, or I explain what the expected results are when the boundary value is passed in.
It's hard to remember to always do this, but it's a good thing for users of your class. It's also difficult to maintain it if the contract the method presents changes (like null values are changed to no be allowed)... you have to be diligent also to update the docs when you change the semantics of the method.
Question 1
Do you often see in API documentation (as in 'javadoc of public functions' for example) the description of "value limits" as well as the classic documentation?
Almost never.
Question 2
My only concern when I want to use this function is: what should I expect in term of parameters and return values ? That is all I need to know to safely setup my parameters and safely test the return value, yet I almost never see that kind of information in API documentation...
If I used a function not properly I would expect a RuntimeException thrown by the method or a RuntimeException in another (sometimes very far) part of the program.
Comments like #param aReaderNameRegexp filter in order to ... (can be null or empty) seems to me a way to implement Design by Contract in a human-being language inside Javadoc.
Using Javadoc to enforce Design by Contract was used by iContract, now resurrected into JcontractS, that let you specify invariants, preconditions, postconditions, in more formalized way compared to the human-being language.
Question 3
This can influence the usage or not for checked or unchecked exceptions.
What do you think ? value limits and API, do they belong together or not ?
Java language doesn't have a Design by Contract feature, so you might be tempted to use Execption but I agree with you about the fact that you have to be aware about When to choose checked and unchecked exceptions. Probably you might use unchecked IllegalArgumentException, IllegalStateException, or you might use unit testing, but the major problem is how to communicate to other programmers that such code is about Design By Contract and should be considered as a contract before changing it too lightly.
I think they do, and have always placed comments in the header files (c++) arcordingly.
In addition to valid input/output/return comments, I also note which exceptions are likly to be thrown by the function (since I often want to use the return value for...well returning a value, I prefer exceptions over error codes)
//File:
// Should be a path to the teexture file to load, if it is not a full path (eg "c:\example.png") it will attempt to find the file usign the paths provided by the DataSearchPath list
//Return: The pointer to a Texture instance is returned, in the event of an error, an exception is thrown. When you are finished with the texture you chould call the Free() method.
//Exceptions:
//except::FileNotFound
//except::InvalidFile
//except::InvalidParams
//except::CreationFailed
Texture *GetTexture(const std::string &File);
#Fire Lancer: Right! I forgot about exception, but I would like to see them mentioned, especially the unchecked 'runtime' exception that this public method could throw
#Mike Stone:
you have to be diligent also to update the docs when you change the semantics of the method.
Mmmm I sure hope that the public API documentation is at the very least updated whenever a change -- that affects the contract of the function -- takes place. If not, those API documentations could be drop altogether.
To add food to yours thoughts (and go with #Scott Dorman), I just stumble upon the future of java7 annotations
What does that means ? That certain 'boundary conditions', rather than being in the documentation, should be better off in the API itself, and automatically used, at compilation time, with appropriate 'assert' generated code.
That way, if a '#CheckForNull' is in the API, the writer of the function might get away with not even documenting it! And if the semantic change, its API will reflect that change (like 'no more #CheckForNull' for instance)
That kind of approach suggests that documentation, for 'boundary conditions', is an extra bonus rather than a mandatory practice.
However, that does not cover the special values of the return object of a function. For that, a complete documentation is still needed.