Andrew Warner - Beware the Siren Song of Comments [tekst, tłumaczenie i interpretacja piosenki]

Wykonawca: Andrew Warner
Gatunek: Tech

Twórz Groove z nami!
Wyślij okładkę tej piosenki!
Wysyłany plik musi być typu: png lub jpg. Żaden plik nie został wysłany. Dziękujemy za wysłanie okładki.

Tekst piosenki

Developers love comments! Everyone who writes a comment thinks that they're making a pareto improvement to the codebase, when in fact it's quite the opposite. Comments are especially dangerous because there are many situations where it seems like a comment will help, but beware the siren's call.

I hate reading articles that make abstract arguments, so enough bloviating, let's check out some examples. Here are some concrete uses of comments that I've seen a lot, and how they can be easily avoided.

Explaining some codeYou might want to write a comment to explain some code that isn't 100% intuitive. Let's take a practical example from the Genius codebase:

class Artist < ActiveRecord::Base
before_save :set_canonical_name_changed

private

def set_canonical_name_changed
self.canonical_name_changed = !!canonical_name.try(:name_changed?)
nil # return nil because if canonical_name is unchanged, it'll return false, which halts save!
end
end
That comment helpfully explains that ActiveRecord will halt saving a model if one of the callbacks returns false. So, we have to return nil instead. Whenever you're tempted to comment your code to explain what's going on, the code isn't clear enough. Your goal should be to make the code readable on its own. So how can we make this section clearer without a comment? Why not just write a helpful method which explains what's going on, and can be easily reused?

ActiveRecord::Base.class_eval do
def without_halting_save
yield
nil
end
end

class Artist < ActiveRecord::Base
before_save :set_canonical_name_changed

private

def set_canonical_name_changed
without_halting_save do
self.canonical_name_changed = !!canonical_name.try(:name_changed?)
end
end
end
Now we have the same amount of information, and a reusable method that explains its intent. Plus, now if ActiveRecord changes its behavior, and returning nil suddenly starts halting save, we can change this method and lift all boats.

Explaining some performance hackMost of the time you can write readable code without worrying about performance, but sometimes performance actually matters. When you have to write a performance hack, you might have an urge to write a comment explaining why. The instinct to want to document your performance hack is the right one, but a comment is the wrong place. Why? Because the hacky code might get modified, removed, or moved somewhere else, and the person who does that has to remember to update the comment too. (Spoiler alert: they're not going to do it.) The comment will never "break" and force someone to fix it if the behavior of the hack changes, it will just stick around to confuse future programmers.

The right place to document hacks is a commit message. A commit message is easily accessible to programmers wanting to edit the code, but it doesn't clog up the code and make it harder to read. git blame allows you to see the commit message for any line that you're looking at. Unlike comments, commit messages will never become out of date, because if the line that they're modifying gets deleted or modified, the commit message gets automatically "removed" from your view in git blame.

On any long-running project, your source control is your documentation. Disciplined development teams strive to write code that, as much as possible, is self-documenting. When some code doesn't speak for itself, they leave their notes in commit messages. If there is any additional discussion over some implementation detail or code design in a pull request, it should be easy to find it right from source control. git getpull allows you to find the GitHub pull request that merged the commit you're looking at, so you can quickly look for any technical discussion about some implementation.

When I'm writing a performance hack, I typically wrap it in a method explaining that it's a hack, and then write a more detailed explanation in the commit message. For example, let's say I've written some fast array compare based on some specific knowledge of a data structure:

def some_complex_calculation_method(input_array)
if compare_input_with_stored_values_performance_hack(self.stored_array, input_array)
# ... something ...
end
end

def compare_input_with_stored_values_performance_hack(stored_array, input_array)
# here be dragons
end
All I need to do is to give the reader some clue that it's a performance hack, and then they can read more in the commit message if they want.

Reminder / TODOWriting TODO or FIXME somewhere in the codebase creates a bit of a bystander effect. It seems like the intent of the TODO is that "someone will surely see this code and proactively delete it", but in reality that will never happen. Every time someone goes into that section of the code, they're in there for some other purpose and they're going to ignore your TODO. This is especially true on bigger teams.

Example:

require 'mylibrary/railtie' if defined?(Rails) # TODO: older rails support!
Realistically, when is that TODO ever going to get done? A better solution would be to use some project management tool to prioritize different features or fixes. If you have to keep your TODOs in the code, use the doby library, or roll your own expiring todos.

TODO 'older rails support!', '2014-09-01'
require 'mylibrary/railtie' if defined?(Rails)
This method sets a specific due date for the TODO, and, unlike a regular comment, it actually gets executed and blows up if you haven't removed it before the due date. (Buyer beware: you probably only want this behavior in dev.)

Old code you "want to keep around" in case you need itThis is by far the worst commenting infraction! You might see a comment like:

# def reslug_all_tag_pages
# Tag.find_each { |t| t.regenerate_slug! }
# end

def something_else_thats_actually_being_used
...
end
"Keeping around old code you might want to use later" is exactly what source control is for. If you want to resurrect some old code, you can do so easily with git as long as you can remember some part of the code. Let's say you want to resurrect this reslug_all_tag_pages method. Just use:

$ git log -Sreslug_all_tag_pages
and that will find all commits that added or deleted a line including that string. Simple!

Automatically generated commentsIt's less common in the world of dynamic languages, but the most popular IDEs for compiled languages tend to pepper the codebase with these useless automatically generated strings. They generate these comments to remind programmers to document their APIs, but I've frequently seen developers commit the automatically generated documentation on a method or class without modification. Some examples:

public class MyList extends ArrayList {

private int myVar;

/**
* @return the myVar
*/
public int getMyVar() {
return myVar;
}

/**
* @param myVar the myVar to set
*/
public void setMyVar(int myVar) {
this.myVar = myVar;
}

/* (non-Javadoc)
* @see java.util.ArrayList#addAll(java.util.Collection)
*/
@Override
public boolean addAll(Collection extends E> collection) {
// something
}

}
The generated comments do nothing but clutter up the code, making it more difficult for the reader to scroll through the class and figure out what the code is doing.

Is there ever a reason to write a comment?To be clear, I don't have a problem with all comments. If you're writing a public API for a library that's getting exported to the world, or to a bunch of developers at your company, it may be easiest to maintain the documentation for that API in code comments. In other words, if you're making a conscious decision to document a library thoroughly, you might find that it's most convenient to keep that documentation close to the code. In that case, you should have some kind of process for making sure that the documentation remains up to date when you make breaking API changes. You should also be able to easily generate structured documentation from those code comments. (RDoc for Ruby is one simple example)

Leave 'em outComments decay. They aren't compiled, and they'll never get executed at runtime. If they become out of date or incorrect, no test is going to fail and no user is going to complain. Programmers work around them out of fear that "somebody might need this comment or it might provide some value in the future", pushing them along far after they're useful (if you can even argue that they were useful in the first place).

Writing a comment to explain your code is the easy way out. It is more difficult to write expressive code than it is to write a paragraph explaining it, but taking the time to write code that speaks for itself pays huge dividends in the long run.

So now that I've covered all of these examples, you don't have any excuse to write comments. Give these methods a try, and I promise you'll have a cleaner codebase that's easier to maintain. Is there a good reason to write a comment that I've missed? Let me know in the comments!

Tłumaczenie piosenki

Nikt nie dodał jeszcze tłumaczenia do tej piosenki. Bądź pierwszy!
Jeśli znasz język na tyle, aby móc swobodnie przetłumaczyć ten tekst, zrób to i dołóż swoją cegiełkę do opisu tej piosenki. Po sprawdzeniu tłumaczenia przez naszych redaktorów, dodamy je jako oficjalne tłumaczenie utworu!

+ Dodaj tłumaczenie

Wyślij Niestety coś poszło nie tak, spróbuj później. Treść tłumaczenia musi być wypełniona.
Dziękujemy za wysłanie tłumaczenia.
Nasi najlepsi redaktorzy przejrzą jego treść, gdy tylko będzie to możliwe. Status swojego tłumaczenia możesz obserwować na stronie swojego profilu.

Interpretacja piosenki

Dziękujemy za wysłanie interpretacji
Nasi najlepsi redaktorzy przejrzą jej treść, gdy tylko będzie to możliwe.
Status swojej interpretacji możesz obserwować na stronie swojego profilu.
Dodaj interpretację
Jeśli wiesz o czym śpiewa wykonawca, potrafisz czytać "między wierszami" i znasz historię tego utworu, możesz dodać interpretację tekstu. Po sprawdzeniu przez naszych redaktorów, dodamy ją jako oficjalną interpretację utworu!

Wyślij Niestety coś poszło nie tak, spróbuj później. Treść interpretacji musi być wypełniona.

Lub dodaj całkowicie nową interpretację - dodaj interpretację
Wyślij Niestety coś poszło nie tak, spróbuj później. Treść poprawki musi być wypełniona. Dziękujemy za wysłanie poprawki.
Najpopularniejsze od Andrew Warner
Beware the Siren Song of Comments
311
{{ like_int }}
Beware the Siren Song of Comments
Andrew Warner
Explanation of song lyric annotation limitations
211
{{ like_int }}
Explanation of song lyric annotation limitations
Andrew Warner
Komentarze
Polecane przez Groove
we can’t be friends (wait for your love)
5,3k
{{ like_int }}
we can’t be friends (wait for your love)
Ariana Grande
HILL BOMB
264
{{ like_int }}
HILL BOMB
Guzior
FRI(END)S
2k
{{ like_int }}
FRI(END)S
V (뷔) / BTS
NIE OBIECAM
420
{{ like_int }}
NIE OBIECAM
Małach & Rufuz
Nadziei Słowa
111
{{ like_int }}
Nadziei Słowa
KęKę (PL)
Popularne teksty
Siedem
51,7k
{{ like_int }}
Siedem
Team X
34+35
42,4k
{{ like_int }}
Love Not War (The Tampa Beat)
25,5k
{{ like_int }}
Love Not War (The Tampa Beat)
Jason Derulo
SEKSOHOLIK
161,6k
{{ like_int }}
SEKSOHOLIK
Żabson
Snowman
74,6k
{{ like_int }}
Snowman
Sia