On Github CodeFX-org / talk-comment-your-code
Nicolai Parlog
Comments are always failures.
(Some guy with a book.)
He’s wrong!
I don’t care about your code!
I want to know what happens when I use it!
pre- & postconditions
what return value can I expect?
thread-safety
(im)mutability
good names, small methods, SOLID, … don’t help here
observed behavior != contract
how many interface implementations am I supposed to check?
what if I have to implement an interface?
You’re code is not a special snowflake - it’s the all singing all dancing crap of the world.
I am in a hurry and have to get shit done.
I care even less about your tests!
How do you test this?
"for all" propositions
thread-safety
(im)mutability
do you have tests for interfaces?
test coverage better be > 90%.
Ever heard RTFT? (Read The &*☠# Tests)
No?
What was I thinking about?
That’s like saying "Car’s crash".
So? Do we get rid of them?
crashes are caused by negligence
are often punishable by law
do not harm the overall benefit
What about names?
do they age?
do you update them?
Yes?!
Then update the comments, too!
or
Writing a comment is harder…
… the later it is done
… the more complex the code is
… the more precise the comment is
Usually affordable compared to writing code and tests.
cost is capped when abstraction works well
What do to with comments when code changes?
updating ⇝ takes time
leaving unchanged ⇝ causes confusion
deletion ⇝ wastes past efforts
Whatever schema you decide onmaintenance is critical!
changing comments takes little time
but finding them can be hard
⇝ Comments and code must be close!
pesky, time-consuming, error-prone
Comments that are
outdated
ambiguous
lacking detail
cause confusion!
Costs are unpredictable but potentially enormous!
Deteriorates trust in comments.
good coding techniques reduce risk
Takes up screen space.
(Fold that shit!)
they may be hard to write
they turn nothing green
nobody gets a pat on the back for a clever comment
Get over it!
Small note: Benefits suffer from diminishing returns.
Duh!
intrinsically redundant
can cause confusion
Might be necessary for arcane language features.
Every unit of code provides an abstraction.
do one thing and to it well
hide how it does it
should not require us to look past the abstraction
The core to modularizing any non-trivial problem!
Abstractions provide two benefits:
reuse code
reuse understanding
Comments can help with both!
abstractions lose value if I have to step into them
tests, clean code, … only shines then
you have to build a new context
most people learn better top down
clean code, tests, … are a bottom up approach
Comments can be signposts, helping to stay on the right level of abstraction.
similar to keeping abstractions intact
Context is invaluable when revisiting code!
why?
no seriously, WHY?
why the &*☠#?!
other tools contain this info
working through them takes time
and is transient!
Comments can be 2nd line of defense.
It’s funny how writing documentation can spur redesign: it’s easier to simplify a complex API than try to document it completely.
(Mike Bostok on Twitter.)
actuality
locality
alternatives
some comments need to be very up-to-date
others can be slightly or even totally outdated
This influences costs:
maintenance
confusion
How far can a comment be away from what it describes?
some must basically be on the same line to make any sense at all
others might span several concepts so they can be some classes away
It is hard to update far-away comments!
There are plenty of alternatives to comments.
But not all work for everything.
clean code
tests, demos
version control
issue tracker
wiki
public int activeUserCountSince(Date date) { int activeUserCount = 0; // loop through the users for (User user : users) // check whether user logged in if (user.loggedInSince(date)) // increase activeUserCount activeUserCount++; return activeUserCount; }
Usually inline comments.
explain what the code does
speak on a very technical level
very high
need to be absolutely up to date!
right on the narrated line(s)
good names
transparent design
well-known patterns
composition: medium
maintenance: high
confusion: high risk
obstruction: yes, can’t be hidden
explain what happens: yes
keep abstractions intact: no
top down over bottom up: no
documenting intent: a little
Narrations suck!
With one exception:
arcane language features are used
there is no alternative
there is no way to improve readability
public interface Map<K, V> { /** * ............................... * ................................ * .................................... * .................................... * * @return ....................... * .................... */ int size(); }
public interface Map<K, V> { /** * Returns the number of key-value * mappings in this map. .......... * .................................... * .................................... * * @return the number of key-value * mappings in this map */ int size(); }
public interface Map<K, V> { /** * Returns the number of key-value * mappings in this map. If the map * contains more than Integer.MAX_VALUE * elements, returns Integer.MAX_VALUE. * * @return the number of key-value * mappings in this map */ int size(); }
(or just Contracts)
Usually JavaDoc on classes and methods.
They define
the code’s central abstraction
pre- and postconditions
quirks
highlight "define" (not "describe")
they make a promise
high
right on the class or method
good names (limited)
tests (limited)
composition: high
maintenance: considerable
confusion: high risk
obstruction:
can be hidden
and viewed on demand
explain what happens: yes
keep abstractions intact: yes
top down over bottom up: to a degree
documenting intent: no
It’s complicated.
costs are high if code changes often
benefits are high if code is read often
⇝ The more stable & reused the code, the better the outcome!
"resused" often implies "stable" by necessity
good documentation improves discoverability and adoption
/** * When keys are Comparable, this class may * use comparison order among keys to help * break ties. */ public class HashMap<K, V> { }
/** * When keys are Comparable, this class may * use comparison order among keys to help * break ties. */ public class HashMap<K, V> { /* This map usually acts as a binned * (bucketed) hash table, but when bins * get too large, they are transformed * into bins of TreeNodes, each * structured similarly to those in * java.util.TreeMap. */ }
another example: a class explaining that a factory is required
Often non-Javadoc blocks at the beginning of a class/method.
(Check out @apiNote and @implNote.)
clarify what code is for
when to use it and when not
explain implementation details
(This is not a contract!)
can even give examples
contracts make a promise, context comments explain why it was made
not that important
not that important
demos
existing code (limited)
composition: moderate
maintenance: not so much
confusion: possible
obstruction:
can be hidden
and viewed on demand
explain what happens: somewhat
keep abstractions intact: a little
top down over bottom up: to a degree
documenting intent: yes
A clear winner!
costs are moderate
benefits are considerable
avoid confusion with contracts
public Color randomFavoriteColor() { while (true) Color favorite = randomColor(); if (isNotWhiteish(favorite)) return favorite; }
public Color randomFavoriteColor() { while (true) Color favorite = randomColor(); // In China white is often seen // as a color of mourning and // some Chinese users did not // like it. We hence disallow // whitish colors as favorites. // For details see issue #1534. if (isNotWhitish(favorite)) return favorite; }
clarifies why (oh why?) code looks the way it does
can document paths not taken
negligible
not that important
commit messages
issues, wikis
composition: moderate
maintenance: negligible
confusion: low
obstruction:
can be hidden
and viewed on demand
explain what happens: somewhat
keep abstractions intact: no
top down over bottom up: no
documenting intent: yes
Even better!
costs are negligible
benefits are considerable
These are great breadcrumbs when tracking down bugs!
Let’s move away from
All comments are failures.
Instead
Comments are a tool to facilitate understanding. We should use it wisely!
For individual comments:
make obvious which kind they are
put yourself in your reader’s mind
strive for high locality
get them reviewed
use phrases like "at the time of writing"
use @apiNote, @implNote
use different styles: /* vs / vs //
This is my proposal:
avoid narrations whenever possible
always have a paragraph that explains a class’s central abstraction
add contracts to reused APIs
provide as much context as possible
But the details depend on many factors:
team:
size
technical backgrounds
code base:
size
heterogeneity
ownership
So:
get the team together and speak freely about comments
go through the code base anddiscuss concrete examples
settle on a shared approach and include it in your style guide
use pair programming or code reviews to adapt and enforce
you can hire me
since 2016: Java channel editor at SitePoint
2014-2016: Java developer at Disy
2011-2014: Java developer at Fraunhofer ISI
until 2010: CS and Math at TU Dortmund
12-months: holytimeland (CC-BY-SA 2.0)
question-mark: Milos Milosevic (CC-BY 2.0)