Is it a good practice to add extra checks in disabled GUI options? - user-interface

I'm referring to the following:
void setup_gui()
{
if (some_condition)
some_button.disable();
...
}
void some_button_click()
{
// Is this a good practice?
if (some_condition)
return;
...
}
Adding that check ensures that the program won't run the operation, but it can also be seen as hiding a bug (some_button_click() must not have run at all).
So, what do you think about it? Is it a safe coding practice or hiding a bug?

Defensive programming is as reasonable as defensive driving.
It may be helpful to think of this in terms of separate concerns. One concern is the presentation. Another may be a set of business rules. It is reasonable to make the same check in both places.
You want to make the check in the presentation layer to communicate to the user.
You may also want to make the check below the presentation layer:
To defend against present and future mistakes in the presentation layer.
In case the code underneath the presentation layer is re-used elsewhere.
[From mvds's comment] In case the condition may change since the control was enabled or disabled.
Edit: David Heffernan's DRY concern below can be addressed trivially by defining the condition exactly once, and accessing it elsewhere.
void setup_gui()
{
some_button.setEnabled( context.isThisActionAvailable() );
...
}
void some_button_click()
{
if ( context.isThisActionAvailable() )
return;
...
}

I don't take this belt and braces approach. The problem is that you have violated the DRY principle with the double use of some_condition. It's all to easy to change this in one place and not the other.
Of course some_condition is quite simple in this made-up example but in reality it's often be much more complex.
If you can't trust your GUI framework to block actions when you request them to be blocked, then you need to fix the framework.

It can be considered safe coding, it can also be considered hiding a bug. This is the time when perhaps you should re-evaluate your program logic. Code redundancy is something that is always best to avoid if possible. It would be better if your program could be structured in such a way that it would not need to check twice, by making sure the actual logic of the program works properly and as intended.
Sure, if you're in a rush this is a quick fix and it works, but it reeks of poor design and/or logic elsewhere in the program.

The silent return in some_button_click() potentially hides a bug. I would either don't do the check at all, or crash loud and violently.

Related

How to cope with bad code [closed]

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 4 years ago.
Improve this question
One of the most unpleasant (and unfortuantely most frequent) situations I am confronted with in my all day life as a developer is that I have to fix bugs or add features into code that is badly designed. Now as a good craftsman I would like to leave the code in a better state than I found it. Often new features can not be implemented if I do not refactor the design. Well - they could, but that would make the code even worse.
Unfortunately this is exactly what I tend to have a hard time with. I feel that if there is one thing that is hard, it is to refactor bad code, especially when you have deadlines. Touching bad and complex code that more or less works is scary. As a result I introduce even more clutter when I hack a new feature into the code without modifiying existing code.
Now my question is How can I learn to cope with bad code? How can I learn to understand huge codebases and then refactor parts of it without breaking stuff that already worked and without exceeding the deadline? Is there any literature you can recommend? Do you have any general tips for me?
General tip:
if (it is working)
Do (not touch it);
else
{
Make (as few modifications as possible)
Or (it will stop working at all);
}
This is experience of generations.
Michael Feathers wrote a good book about this subject exactly.
Working Effectively with Legacy Code.
Another great book is by Martin Fowler, Kent Beck and others:
Refactoring: Improving the Design of Existing Code.
Refactoring needs the safety harness of a unit test suite to remove that "Have I broken it?" feeling. Covering the bad code in a blanket of tests will help you whilst you strive for good clean code.
Pex is a tool that I find useful (if you are in the .NET world) for creating tests for legacy code.
Legacy code == code without tests!
When I have to deal with adding functionality to bad code, my usual approach is:
Write automated tests for every important feature that must work (as most bad code doesn't have any tests).
Do code changes.
Make sure the tests are still working.
That give you at least some confidence that you didn't break everything. As for how to learn coping with bad code, I guess it's just about experience.
Well, if you're going to refactor large amounts of code in a project I'd recommend using some decent version control, so you can branch and fall back easily. Given, this is probably is an open door, but crucial imo.
Furthermore, before you start getting in to complex OO, try breaking methods and functions into smaller ones. Ensuring some level of atomicity in each of the functions, which makes the code alot easier to maintain, read and manage.
It's all about the small stuff, break it down into logical units of operation, I'm doing a refactor action on a 1k lines method. It does al sorts of fancy stuff.
My first goal is to get as much stuff out of it in smaller pieces, when that's done I'll start thinking about a better OO design, which is much easier because I've a much better grasp on things.
Aspirin works good too.
I am currently in this situation. My approach is to answer some questions before touching the code:
Is the code really that bad? If yes, what are the common errors? ==> maybe concentrate on those first
What is the main runtime flow in the code? Maybe you can discard quite a few constructs from it.
Try to layer/modularize the code without changing it. This leads to some reduction of interdependencies
Try to poke the code with tests. If the code base is entangled beyond hope: use something like PowerMock to simulate objects that are not (yet) in need of change
Have an integration environment available, in which you can test changes in a production near environment.
Don't shy away to rewrite parts of the code base. But try to not implement too much new stuff in it
Try to team up, discuss designs, principles, solutions
This is tough work, and nobody will thank you for it. Be proud of small improvements and enjoy a good work done :)
I think that it is always good to have a general idea of how everything works in the software you are developing/improving. That's where the design documents and other documents made after or during the development process come in. I believe that if someone before you has not done proper documentation, then at least you should write a couple of lines somewhere about what you experience throughout your development process. I usually use OneNote or other stuff to write notes about what I encounter, and usually keep listing things which I feel would require refactoring. And if there is some downtime during the project, I usually go back to that list and try to improve things bit by bit.
So basically, if someone before you hasn't done it right, it would be good if at least you could help reduce the problems for any other developer who would come across the same code.
Refactoring: Improving the Design of Existing Code
It depends on number of factors but the most important is if you have authority to modify it.
In case you do, refactor it. For example, rename classes/functions/variables. Extract and generalize functionalities. See Refactoring: Improving the Design of Existing Code (Bible for the subject).
Before you begin doing that ensure that code is in a proper version control (VC) and have a good set of test cases. VC let you roll back and test cases help catching unexpected side-effects.
I suggest Distributed Version Control like Mercurial/Bazaar and Git because it is very refactoring is not exactly structured like adding features.
If there were no tests (common), you must create them. Read Working Effectively With Legacy Code. Especially about "Seal point" (not about Siamese cat :p).
In case you don't create a wrapper API that is cleaner.
For example:
Old code ====================
const ACT_SHOW = 'show';
const ACT_HIDE = 'hide';
function int DoThing(Object $Obj, Stirng $Action, Object $Param1, Object $Param1) {
....;
}
Added code ==================
enum Actions {
show, hide;
};
class ActionDoer {
private obj;
ActionDoer($Object) {
this.obj = $Object;
}
function int act(Actions $Action, $Param1, $Param1) {
this.act($Action.toString(), $Param1, $Param1) ;
}
function int act(String $Action, $Param1, $Param1) {
DoThing(this.obj, $Action, $Param1, $Param1) ;
}
function int show() {
this.act(Actions.show, null, null);
}
function int hide(Color $ToBGColor, long $FadeTime) {
this.act(Actions.hide, $ToBGColor, $FadeTime);
}
}
This way, the old code is not touched and the extension can be done using the new code. Good example of this method is jQuery where the old (default) way of accessing DOM is painful.
Hope this helps.

Coding-style: How to improve coding-styles and standards at a company

What are the best ways to improve the standards of coding-styles at a company? Let's use C# as an example here.
I guess there are many differences between developers that need to be taken into consideration. The concrete ones could be education, experience and past programming-languages.
How does one justify that something is right over something else?
One person may say "I move my body to the place where I earn my money with my 4-wheeled vehicle". So why is it more "right" to say "I drive to work in my car"?
Some people might like code more explicit with more lines of code. Some might like more tight code.
// Explicit
string text = defaultValue;
if (string.IsNullOrEmpty(text)) {
text = fallbackValue;
}
// Tighter
string text = defaultValue ?? fallbackValue;
Or the old protective programming-style, where you check for error-cases in the beginning and not wrap the whole method body inside a positive if-clause:
public string ChangeText(string text)
{
if (!string.IsNullOrEmpty(text))
{
// Do a lot of stuff
}
else {
throw new Exception();
}
}
// vs.
public string ChangeText(string text)
{
if (string.IsNullOrEmpty(text)) {
throw new Exception();
}
// Do a lot of stuff
}
Is the old "I'm having troubles reading this code" valid here? It's the same situation that was when Generics was introduced to C#, people had an initial trouble reading it.
Where is the line drawn between unreadable code and code that some developers are not used to?
Which part of Phil Haacks "7 Stages of new language keyword grief" has valid points here?
Are there any easy ways to set coding-standards and uphold them in a company?
UPDATE: Take in consideration things like variable-naming, that can't really be defined in a document. Or can it?
The easiest way to set coding-standards at a company:
Create a Standards Document and enforce it.
...people love to complain about code quality, but few will sit down and take the time to create a standards document. It's worth the effort and as long as you can enforce it (code reviews, etc.) then you're bound to notice an improvement in your code.
You always can use free tools like StyleCop from Microsoft.
You can disable or modify rules you don't like
There are two main sides of coding style:
"Where do I put the opening brace?" type issues - These are usually unimportant, i.e. there are no real reasons to prefer one style over the other.
Actual coding rules, like do we use return's in the middle of a function.
The way I see it, for #1 type issues, there is no point in any debate. Just set a standard in a standards document, and enforce it (more on this later).
As for the second issue, I'm honestly not sure whether it should be regulater. I personally love sprinkling functions with return values to check for error conditions, and I know some people who cringe at the practice. But at the end of the day, we can usually read each other's code just fine. These kinds of issues are much more about how you prefer expressing yourself, what is easier for you to write, and I wouldn't want a company making rules that get to this level.
As for how to enforce things, standards documents are good, but in my experience, are just never read or followed closely, and are soon forgotten. The best way is to have some kind of automated tool which tells you that you're violating the standard.
For example, even as a completely new Java programmer, I knew when to uppercase/lowercase my identifiers, simply because Eclipse let me (quietly, unobtrusively) know what the standard is.
First, you will always have to enforce the coding styles - there will never be a consent.
That's, why I would try to automate the check for consistency. Depending on your language you can use StyleCop (for .Net) or something like indent under linux.
Every developer can work with his own code style in his environment (the reformat can be very easy, depending on your environment), but all checked-in code has to be of the company's style.
Which style do you choose? Well, often there are already popular styles - depending on the language. For your example (C#) I would choose the Microsoft style. At last: only the project manager (senior programmer) has the right to adjust it.
Most companies use Coding-Style-Guidelines/Conventions. These are documents telling that you should always do braces around the if body even for one command, that you should indent with tabs/spaces, and so on.
There are a lot of tools for (automatically) check and enforce the coding-style. (An example for the java-world is checkstyle, which can be integrated into eclipse and also in a continuous integration solution like 'hudson'.)
How does one justify that something is
right over something else?
Easy: just don't. Pick a coding style, communicate it, and enforce it.
I think consistency is important here. There's not a lot of point in getting into a semantic debate over which way is better than the other unless the current methodology is particularly bad.
What is important is that the team writes their code consistently so that if someone resigns or gets hit by a bus then his/her colleagues know what is going on with the code when they are forced to work with it.

Is it possible to write good and understandable code without any comments?

Can any one suggest what is the best way to write good code that is understandable without a single line of comments?
I once had a professor when I was in college tell me that any good code should never need any comments.
Her approach was a combination of very precise logic split out into small functions with very descriptive method/property/variable names. The majority of what she presented was, in fact, extremely readable with no comments. I try to do the same with everything I write...
Read Code Complete, 2nd Edition cover to cover. Perhaps twice.
To give some specifics:
Making code readable
Eliminating code repetition
Doing design/architecture before you write code
I like to 'humanise' code, so instead of:
if (starColour.red > 200 && starColour.blue > 200 && starColour.green > 200){
doSomething();
}
I'll do this:
bool starIsBright;
starIsBright = (starColour.red > 200 && starColour.blue > 200 && starColour.green > 200);
if(starIsBright){
doSomething();
}
In some cases - yes, but in many cases no. The Yes part is already answered by others - keep it simple, write it nicely, give it readable names, etc. The No part goes to when the problem you solve in code is not a code problem at all but rather domain specific problem or business logic problem. I've got no problem reading lousy code even if it doesn't have comments. It's annoying, but doable. But it's practically impossible to read some code without understanding why is it like this and what is it trying to solve. So things like :
if (starColour.red > 200 && starColour.blue > 200 && starColour.green > 200){
doSomething();
}
look nice, but could be quite meaningless in the context of what the program is actually doing. I'd rather have it like this:
// we do this according to the requirement #xxxx blah-blah..
if (starColour.red > 200 && starColour.blue > 200 && starColour.green > 200){
doSomething();
}
Well written code might eliminate the need for comments to explain what you're doing, but you'll still want comments to explain the why.
If you really want to then you would need to be very detailed in your variable names and methods names.
But in my opinion, there is no good way to do this. Comments serve a serious purpose in coding, even if you are the only one coding you still sometimes need to be reminded what part of the code you're looking at.
Yes, you can write code that doesn't need comments to describe what it does, but that may not be enough.
Just because a function is very clear in explaining what it does, does not, by itself, tell you why it is doing what it does.
As in everything, moderation is a good idea. Write code that is explanatory, and write comments that explain why it is there or what assumptions are being made.
I think that the concept of Fluent Interfaces is really a good example of this.
var bob = DB.GetCustomers().FromCountry("USA").WithName("Bob")
Clean Code by Robert C. Martin contains everything you need to write clean, understandable code.
Use descriptive variable names and descriptive method names. Use whitespace.
Make your code read like normal conversation.
Contrast the use of Matchers in Junit:
assertThat(x, is(3));
assertThat(x, is(not(4)));
assertThat(responseString, either(containsString("color")).or(containsString("colour")));
assertThat(myList, hasItem("3"));
with the traditional style of assertEquals:
assertEquals(3, x);
When I look at the assertEquals statement, it is not clear which parameter is "expected" and which is "actual".
When I look at assertThat(x, is(3)) I can read that in English as "Assert that x is 3" which is very clear to me.
Another key to writing self-documenting code is to wrap any bit of logic that is not clear in a method call with a clear name.
if( (x < 3 || x > 17) && (y < 8 || y > 15) )
becomes
if( xAndYAreValid( x, y ) ) // or similar...
I'm not sure writing code that is so expressive that you don't need comments is necessarily a great goal. Seems to me like another form of overoptimization. If I were on your team, I'd be pleased to see clear, concise code with just enough comments.
In most cases, yes, you can write code that is clear enough that comments become unnecessary noise.
The biggest problem with comments is there is no way to check their accuracy. I tend to agree with Uncle Bob Martin in chapter 4 of his book, Clean Code:
The proper use of comments is to compensate for our failure to express ourself in
code. Note that I used the word failure. I meant it. Comments are always failures. We must
have them because we cannot always figure out how to express ourselves without them,
but their use is not a cause for celebration.
So when you find yourself in a position where you need to write a comment, think it
through and see whether there isn’t some way to turn the tables and express yourself in
code. Every time you express yourself in code, you should pat yourself on the back. Every
time you write a comment, you should grimace and feel the failure of your ability of
expression.
Most comments are either needless redundancy, outright fallacy or a crutch used to explain poorly written code. I say most because there are certain scenarios where the lack of expressiveness lies with the language rather than the programmer.
For instance the copyright and license information typically found at the beginning of a source file. As far as I'm aware no known construct exists for this in any of the popular languages. Since a simple one or two line comment suffices, its unlikely that such a construct will be added.
The original need for most comments has been replaced over time by better technology or practices. Using a change journal or commenting out code has been supplanted with source control systems. Explanatory comments in long functions can be mitigated by simply writing shorter functions. etc.
You usually can turn your comment into a function name something like:
if (starColourIsGreaterThanThreshold(){
doSomething();
}
....
private boolean starColourIsGreaterThanThreshold() {
return starColour.red > THRESHOLD &&
starColour.blue > THRESHOLD &&
starColour.green > THRESHOLD
}
I think comments should express the why, perhaps the what, but as much as possible the code should define the how (the behavior).
Someone should be able to read the code and understand what it does (the how) from the code. What may not be obvious is why you would want such behavior and what this behavior contributes to the overall requirements.
The need to comment should give you pause, though. Maybe how you are doing it is too complicated and the need to write a comment shows that.
There is a third alternative to documenting code - logging. A method that is well peppered with logging statements can do a lot to explain the why, can touch on the what and may give you a more useful artifact than well named methods and variables regarding the behavior.
If you want to code entirely without comments and still have your code be followable, then you'll have to write a larger number of shorter methods. Methods will have to have descriptive names. Variables will also have to have descriptive names. One common method of doing this is to give variables the name of nouns and to give methods the names of verbal phrases. For example:
account.updateBalance();
child.givePacifier();
int count = question.getAnswerCount();
Use enums liberally. With an enum, you can replace most booleans and integral constants. For example:
public void dumpStackPretty(boolean allThreads) {
....
}
public void someMethod() {
dumpStackPretty(true);
}
vs
public enum WhichThreads { All, NonDaemon, None; }
public void dumpStackPretty(WhichThreads whichThreads) {
....
}
public void someMethod() {
dumpStackPretty(WhichThreads.All);
}
Descriptive names is your obvious first bet.
Secondly make sure each method does one thing and only one thing. If you have a public method that needs to do many things, split it up into several private methods and call those from the public method, in a way that makes the logic obvious.
Some time ago I had to create a method that calculated the correlation of two time series.
To calculate the correlation you also need the mean and standard deviation. So I had two private methods (well actually in this case they were public as they could be used for other purposes (but assuming they couldn't then they would be private)) for calculating A) the mean, B) the standard deviation.
This sort of splitting up of function into the smallest part that makes sense is probably the most important thing to make a code readable.
How do you decide where to break up methods. My way is, if the name is obvious e.g. getAddressFromPage it is the right size. If you have several contenders you are probably trying to do too much, if you can't think of a name that makes sense you method may not "do" enough - although the latter is much less likely.
I don't really think comments are a good idea in most cases. Comments don't get checked by the compiler so they so often are misleading or wrong as the code changes over time. Instead, I prefer self documenting, concise methods that don't need comments. It can be done, and I have been doing it this way for years.
Writing code without comments takes practice and discipline, but I find that the discipline pays off as the code evolves.
It may not be comments, but, to help someone better understand what it going on you may need some diagrams explaining how the program should work, as, if a person knows the big picture then it is easier to understand code.
But, if you are doing something complex then you may need some comments, for example, in a very math intensive program.
The other place I find comments useful and important, is to ensure that someone doesn't replace code with something that looks like it should work, but won't. In that case I leave the bad code in, and comment it out, with an explanation as to why it shouldn't be used.
So, it is possible to write code without comments, but only if you are limited in what types of applications you are writing, unless you can explain why a decision was made, somewhere, and not call it a comment.
For example, a random generator can be written many ways. If you pick a particular implementation it may be necessary to explain why you picked that particular generator, as the period may be sufficiently long for current requirements, but later the requirements may change and your generator may not be sufficient.
I believe it's possible, if you consider the fact that not everybody likes the same style. So in order to minimize comments, knowing your "readers" is the most important thing.
In "information systems" kind-of software, try using declarative sentence, try to approximate the code line to a line in english, and avoid "mathematical programming" (with the i,j and k for index, and the one-liners-to-do-a-lot) at all costs.
I think code can be self-documenting to a large degree, and I think it's crucial, but reading even well-written code can be like looking at cells of the human body with a microscope. It sometimes takes comments to really explain the big picture of how pieces of the system fit together, especially if it solves a really complex and difficult problem.
Think about special data structures. If all that computer scientists had ever published about data structures were well-written code, few would really understand the relative benefit of one data structure over another -- because Big-O runtime of any given operation is sometimes just not obvious from reading the code. That's where the math and amortized analysis presented in articles come in.

What is your personal approach/take on commenting?

Duplicate
What are your hard rules about commenting?
A Developer I work with had some things to say about commenting that were interesting to me (see below). What is your personal approach/take on commenting?
"I don't add comments to code unless
its a simple heading or there's a
platform-bug or a necessary
work-around that isn't obvious. Code
can change and comments may become
misleading. Code should be
self-documenting in its use of
descriptive names and its logical
organization - and its solutions
should be the cleanest/simplest way
to perform a given task. If a
programmer can't tell what a program
does by only reading the code, then
he's not ready to alter it.
Commenting tends to be a crutch for
writing something complex or
non-obvious - my goal is to always
write clean and simple code."
"I think there a few camps when it
comes to commenting, the
enterprisey-type who think they're
writing an API and some grand
code-library that will be used for
generations to come, the
craftsman-like programmer that thinks
code says what it does clearer than a
comment could, and novices that write
verbose/unclear code so as to need to
leave notes to themselves as to why
they did something."
There's a tragic flaw with the "self-documenting code" theory. Yes, reading the code will tell you exactly what it is doing. However, the code is incapable of telling you what it's supposed to be doing.
I think it's safe to say that all bugs are caused when code is not doing what it's supposed to be doing :). So if we add some key comments to provide maintainers with enough information to know what a piece of code is supposed to be doing, then we have given them the ability to fix a whole lot of bugs.
That leaves us with the question of how many comments to put in. If you put in too many comments, things become tedious to maintain and the comments will inevitably be out of date with the code. If you put in too few, then they're not particularly useful.
I've found regular comments to be most useful in the following places:
1) A brief description at the top of a .h or .cpp file for a class explaining the purpose of the class. This helps give maintainers a quick overview without having to sift through all of the code.
2) A comment block before the implementation of a non-trivial function explaining the purpose of it and detailing its expected inputs, potential outputs, and any oddities to expect when calling the function. This saves future maintainers from having to decipher entire functions to figure these things out.
Other than that, I tend to comment anything that might appear confusing or odd to someone. For example: "This array is 1 based instead of 0 based because of blah blah".
Well written, well placed comments are invaluable. Bad comments are often worse than no comments. To me, lack of any comments at all indicates laziness and/or arrogance on the part of the author of the code. No matter how obvious it is to you what the code is doing or how fantastic your code is, it's a challenging task to come into a body of code cold and figure out what the heck is going on. Well done comments can make a world of difference getting someone up to speed on existing code.
I've always liked Refactoring's take on commenting:
The reason we mention comments here is that comments often are used as a deodorant. It's surprising how often you look at thickly commented code and notice that the comments are there because the code is bad.
Comments lead us to bad code that has all the rotten whiffs we've discussed in the rest of this chapter. Our first action is to remove the bad smells by refactoring. When we're finished, we often find that the comments are superfluous.
As controversial as that is, it's rings true for the code I've read. To be fair, Fowler isn't saying to never comment, but to think about the state of your code before you do.
You need documentation (in some form; not always comments) for a local understanding of the code. Code by itself tells you what it does, if you read all of it and can keep it all in mind. (More on this below.) Comments are best for informal or semiformal documentation.
Many people say comments are a code smell, replaceable by refactoring, better naming, and tests. While this is true of bad comments (which are legion), it's easy to jump to concluding it's always so, and hallelujah, no more comments. This puts all the burden of local documentation -- too much of it, I think -- on naming and tests.
Document the contract of each function and, for each type of object, what it represents and any constraints on a valid representation (technically, the abstraction function and representation invariant). Use executable, testable documentation where practical (doctests, unit tests, assertions), but also write short comments giving the gist where helpful. (Where tests take the form of examples, they're incomplete; where they're complete, precise contracts, they can be as much work to grok as the code itself.) Write top-level comments for each module and each project; these can explain conventions that keep all your other comments (and code) short. (This supports naming-as-documentation: with conventions established, and a place we can expect to find subtleties noted, we can be confident more often that the names tell all we need to know.) Longer, stylized, irritatingly redundant Javadocs have their uses, but helped generate the backlash.
(For instance, this:
Perform an n-fold frobulation.
#param n the number of times to frobulate
#param x the x-coordinate of the center of frobulation
#param y the y-coordinate of the center of frobulation
#param z the z-coordinate of the center of frobulation
could be like "Frobulate n times around the center (x,y,z)." Comments don't have to be a chore to read and write.)
I don't always do as I say here; it depends on how much I value the code and who I expect to read it. But learning how to write this way made me a better programmer even when cutting corners.
Back on the claim that we document for the sake of local understanding: what does this function do?
def is_even(n): return is_odd(n-1)
Tests if an integer is even? If is_odd() tests if an integer is odd, then yes, that works. Suppose we had this:
def is_odd(n): return is_even(n-1)
The same reasoning says this is_odd() tests if an integer is odd. Put them together, of course, and neither works, even though each works if the other does. Change it a bit and we'd have code that does work, but only for natural numbers, while still locally looking like it works for integers. In microcosm that's what understanding a codebase is like: tracing dependencies around in circles to try to reverse-engineer assumptions the author could have explained in a line or two if they'd bothered. I hate the expense of spirit thoughtless coders have put me to this way over the past couple of decades: oh, this method looks like it has the side effect of farbuttling the warpcore... always? Well, if odd crobuncles desaturate, at least; do they? Better check all the crobuncle-handling code... which will pose its own challenges to understanding. Good documentation cuts this O(n) pointer-chasing down to O(1): e.g. knowing a function's contract and the contracts of the things it explicitly uses, the function's code should make sense with no further knowledge of the system. (Here, contracts saying is_even() and is_odd() work on natural numbers would tell us that both functions need to test for n==0.)
My only real rule is that comments should explain why code is there, not what it is doing or how it is doing it. Those things can change, and if they do the comments have to be maintained. The purpose the code exists in the first place shouldn't change.
the purpose of comments is to explain the context - the reason for the code; this, the programmer cannot know from mere code inspection. For example:
strangeSingleton.MoveLeft(1.06);
badlyNamedGroup.Ignite();
who knows what the heck this is for? but with a simple comment, all is revealed:
//when under attack, sidestep and retaliate with rocket bundles
strangeSingleton.MoveLeft(1.06);
badlyNamedGroup.Ignite();
seriously, comments are for the why, not the how, unless the how is unintuitive.
While I agree that code should be self-readable, I still see a lot of value in adding extensive comment blocks for explaining design decisions. For example "I did xyz instead of the common practice of abc because of this caveot ..." with a URL to a bug report or something.
I try to look at it as: If I'm dead and gone and someone straight out of college has to fix a bug here, what are they going to need to know?
In general I see comments used to explain poorly written code. Most code can be written in a way that would make comments redundant. Having said that I find myself leaving comments in code where the semantics aren't intuitive, such as calling into an API that has strange or unexpected behavior etc...
I also generally subscribe to the self-documenting code idea, so I think your developer friend gives good advice, and I won't repeat that, but there are definitely many situations where comments are necessary.
A lot of times I think it boils down to how close the implementation is to the types of ordinary or easy abstractions that code-readers in the future are going to be comfortable with or more generally to what degree the code tells the entire story. This will result in more or fewer comments depending on the type of programming language and project.
So, for example if you were using some kind of C-style pointer arithmetic in an unsafe C# code block, you shouldn't expect C# programmers to easily switch from C# code reading (which is probably typically more declarative or at least less about lower-level pointer manipulation) to be able to understand what your unsafe code is doing.
Another example is when you need to do some work deriving or researching an algorithm or equation or something that is not going to end up in your code but will be necessary to understand if anyone needs to modify your code significantly. You should document this somewhere and having at least a reference directly in the relevant code section will help a lot.
I don't think it matters how many or how few comments your code contains. If your code contains comments, they have to maintained, just like the rest of your code.
EDIT: That sounded a bit pompous, but I think that too many people forget that even the names of the variables, or the structures we use in the code, are all simply "tags" - they only have meaning to us, because our brains see a string of characters such as customerNumber and understand that it is a customer number. And while it's true that comments lack any "enforcement" by the compiler, they aren't so far removed. They are meant to convey meaning to another person, a human programmer that is reading the text of the program.
If the code is not clear without comments, first make the code a clearer statement of intent, then only add comments as needed.
Comments have their place, but primarily for cases where the code is unavoidably subtle or complex (inherent complexity is due to the nature of the problem being solved, not due to laziness or muddled thinking on the part of the programmer).
Requiring comments and "measuring productivity" in lines-of-code can lead to junk such as:
/*****
*
* Increase the value of variable i,
* but only up to the value of variable j.
*
*****/
if (i < j) {
++i;
} else {
i = j;
}
rather than the succinct (and clear to the appropriately-skilled programmer):
i = Math.min(j, i + 1);
YMMV
The vast majority of my commnets are at the class-level and method-level, and I like to describe the higher-level view instead of just args/return value. I'm especially careful to describe any "non-linearities" in the function (limits, corner cases, etc) that could trip up the unwary.
Typically I don't comment inside a method, except to mark "FIXME" items, or very occasionally some sort of "here be monsters" gotcha that I just can't seem to clean up, but I work very hard to avoid those. As Fowler says in Refactoring, comments tend to indicate smally code.
Comments are part of code, just like functions, variables and everything else - and if changing the related functionality the comment must also be updated (just like function calls need changing if function arguments change).
In general, when programming you should do things once in one place only.
Therefore, if what code does is explained by clear naming, no comment is needed - and this is of course always the goal - it's the cleanest and simplest way.
However, if further explanation is needed, I will add a comment, prefixed with INFO, NOTE, and similar...
An INFO: comment is for general information if someone is unfamiliar with this area.
A NOTE: comment is to alert of a potential oddity, such as a strange business rule / implementation.
If I specifically don't want people touching code, I might add a WARNING: or similar prefix.
What I don't use, and am specifically opposed to, are changelog-style comments - whether inline or at the head of the file - these comments belong in the version control software, not the sourcecode!
I prefer to use "Hansel and Gretel" type comments; little notes in the code as to why I'm doing it this way, or why some other way isn't appropriate. The next person to visit this code will probably need this info, and more often than not, that person will be me.
As a contractor I know that some people maintaining my code will be unfamiliar with the advanced features of ADO.Net I am using. Where appropriate, I add a brief comment about the intent of my code and a URL to an MSDN page that explains in more detail.
I remember learning C# and reading other people's code I was often frustrated by questions like, "which of the 9 meanings of the colon character does this one mean?" If you don't know the name of the feature, how do you look it up?! (Side note: This would be a good IDE feature: I select an operator or other token in the code, right click then shows me it's language part and feature name. C# needs this, VB less so.)
As for the "I don't comment my code because it is so clear and clean" crowd, I find sometimes they overestimate how clear their very clever code is. The thought that a complex algorithm is self-explanatory to someone other than the author is wishful thinking.
And I like #17 of 26's comment (empahsis added):
... reading the code will tell you exactly
what it is doing. However, the code is
incapable of telling you what it's
supposed to be doing.
I very very rarely comment. MY theory is if you have to comment it's because you're not doing things the best way possible. Like a "work around" is the only thing I would comment. Because they often don't make sense but there is a reason you are doing it so you need to explain.
Comments are a symptom of sub-par code IMO. I'm a firm believer in self documenting code. Most of my work can be easily translated, even by a layman, because of descriptive variable names, simple form, and accurate and many methods (IOW not having methods that do 5 different things).
Comments are part of a programmers toolbox and can be used and abused alike. It's not up to you, that other programmer, or anyone really to tell you that one tool is bad overall. There are places and times for everything, including comments.
I agree with most of what's been said here though, that code should be written so clear that it is self-descriptive and thus comments aren't needed, but sometimes that conflicts with the best/optimal implementation, although that could probably be solved with an appropriately named method.
I agree with the self-documenting code theory, if I can't tell what a peice of code is doing simply by reading it then it probably needs refactoring, however there are some exceptions to this, I'll add a comment if:
I'm doing something that you don't
normally see
There are major side effects or implementation details that aren't obvious, or won't be next year
I need to remember to implement
something although I prefer an
exception in these cases.
If I'm forced to go do something else and I'm having good ideas, or a difficult time with the code, then I'll add sufficient comments to tmporarily preserve my mental state
Most of the time I find that the best comment is the function or method name I am currently coding in. All other comments (except for the reasons your friend mentioned - I agree with them) feel superfluous.
So in this instance commenting feels like overkill:
/*
* this function adds two integers
*/
int add(int x, int y)
{
// add x to y and return it
return x + y;
}
because the code is self-describing. There is no need to comment this kind of thing as the name of the function clearly indicates what it does and the return statement is pretty clear as well. You would be surprised how clear your code becomes when you break it down into tiny functions like this.
When programming in C, I'll use multi-line comments in header files to describe the API, eg parameters and return value of functions, configuration macros etc...
In source files, I'll stick to single-line comments which explain the purpose of non-self-evident pieces of code or to sub-section a function which can't be refactored to smaller ones in a sane way. Here's an example of my style of commenting in source files.
If you ever need more than a few lines of comments to explain what a given piece of code does, you should seriously consider if what you're doing can't be done in a better way...
I write comments that describe the purpose of a function or method and the results it returns in adequate detail. I don't write many inline code comments because I believe my function and variable naming to be adequate to understand what is going on.
I develop on a lot of legacy PHP systems that are absolutely terribly written. I wish the original developer would have left some type of comments in the code to describe what was going on in those systems. If you're going to write indecipherable or bad code that someone else will read eventually, you should comment it.
Also, if I am doing something a particular way that doesn't look right at first glance, but I know it is because the code in question is a workaround for a platform or something like that, then I'll comment with a WARNING comment.
Sometimes code does exactly what it needs to do, but is kind of complicated and wouldn't be immediately obvious the first time someone else looked at it. In this case, I'll add a short inline comment describing what the code is intended to do.
I also try to give methods and classes documentation headers, which is good for intellisense and auto-generated documentation. I actually have a bad habit of leaving 90% of my methods and classes undocumented. You don't have time to document things when you're in the middle of coding and everything is changing constantly. Then when you're done you don't feel like going back and finding all the new stuff and documenting it. It's probably good to go back every month or so and just write a bunch of documentation.
Here's my view (based on several years of doctoral research):
There's a huge difference between commenting functions (sort of a black box use, like JavaDocs), and commenting actual code for someone who will read the code ("internal commenting").
Most "well written" code shouldn't require much "internal commenting" because if it performs a lot then it should be broken into enough function calls. The functionality for each of these calls is then captured in the function name and in the function comments.
Now, function comments are indeed the problem, and in some ways your friend is right, that for most code there is no economical incentive for complete specifications the way that popular APIs are documented. The important thing here is to identify what are the "directives": directives are those information pieces that directly affect clients, and require some direct action (and are often unexpected). For example, X must be invoked before Y, don't call this from outside a UI thread, be aware that this has a certain side effect, etc. These are the things that are really important to capture.
Since most people never read full function documentations, and skim what they do read, you can actually increase the chances of awareness by capturing only the directives rather than the whole description.
I comment as much as needed - then, as much as I will need it a year later.
We add comments which provide the API reference documentation for all public classes / methods / properties / etc... This is well worth the effort because XML Documentation in C# has the nice effect of providing IntelliSense to users of these public APIs. .NET 4.0's code contracts will enable us to improve further on this practice.
As a general rule, we do not document internal implementations as we write code unless we are doing something non-obvious. The theory is that while we are writing new implementations, things are changing and comments are more likely than not to be wrong when the dust settles.
When we go back in to work on an existing piece of code, we add comments when we realize that it's taking some thought to figure out what in the heck is going on. This way, we wind up with comments where they are more likely to be correct (because the code is more stable) and where they are more likely to be useful (if I'm coming back to a piece of code today, it seems more likely that I might come back to it again tomorrow).
My approach:
Comments bridge the gap between context / real world and code. Therefore, each and every single line is commented, in correct English language.
I DO reject code that doesn't observe this rule in the strictest possible sense.
Usage of well formatted XML - comments is self-evident.
Sloppy commenting means sloppy code!
Here's how I wrote code:
if (hotel.isFull()) {
print("We're fully booked");
} else {
Guest guest = promptGuest();
hotel.checkIn(guest);
}
here's a few comments that I might write for that code:
// if hotel is full, refuse checkin, otherwise
// prompt the user for the guest info, and check in the guest.
If your code reads like a prose, there is no sense in writing comments that simply repeats what the code reads since the mental processing needed for reading the code and the comments would be almost equal; and if you read the comments first, you will still need to read the code as well.
On the other hand, there are situations where it is impossible or extremely difficult to make the code looks like a prose; that's where comment could patch in.

What types of coding anti-patterns do you always refactor when you cross them?

I just refactored some code that was in a different section of the class I was working on because it was a series of nested conditional operators (?:) that was made a ton clearer by a fairly simple switch statement (C#).
When will you touch code that isn't directly what you are working on to make it more clear?
I once was refactoring and came across something like this code:
string strMyString;
try
{
strMyString = Session["MySessionVar"].ToString();
}
catch
{
strMyString = "";
}
Resharper pointed out that the .ToString() was redundant, so I took it out. Unfortunately, that ended up breaking the code. Whenever MySessionVar was null, it wasn't causing the NullReferenceException that the code relied on to bump it down to the catch block. I know, this was some sad code. But I did learn a good lesson from it. Don't rapidly go through old code relying on a tool to help you do the refactoring - think it through yourself.
I did end up refactoring it as follows:
string strMyString = Session["MySessionVar"] ?? "";
Update: Since this post is being upvoted and technically doesn't contain an answer to the question, I figured I should actually answer the question. (Ok, it was bothering me to the point that I was actually dreaming about it.)
Personally I ask myself a few questions before refactoring.
1) Is the system under source control? If so, go ahead and refactor because you can always roll back if something breaks.
2) Do unit tests exist for the functionality I am altering? If so, great! Refactor. The danger here is that the existence of unit tests don't indicate the accuracy and scope of said unit tests. Good unit tests should pick up any breaking changes.
3) Do I thoroughly understand the code I am refactoring? If there's no source control and no tests and I don't really understand the code I am changing, that's a red flag. I'd need to get more comfortable with the code before refactoring.
In case #3 I would probably spend the time to actually track all of the code that is currently using the method I am refactoring. Depending on the scope of the code this could be easy or impossible (ie. if it's a public API). If it comes down to being a public API then you really need to understand the original intent of the code from a business perspective.
I only refactor it if tests are already in place. If not, it's usually not worth my time to write tests for and refactor presumably working code.
This is a small, minor antipattern but it so irritates me that whenever I find it, I expunge it immediately. In C (or C++ or Java)
if (p)
return true;
else
return false;
becomes
return p;
In Scheme,
(if p #t #f)
becomes
p
and in ML
if p then true else false
becomes
p
I see this antipattern almost exclusively in code written by undergraduate students. I am definitely not making this up!!
Whenever I come across it and I don't think changing it will cause problems (e.g. I can understand it enough that I know what it does. e.g. the level of voodoo is low).
I only bother to change it if there is some other reason I'm modifying the code.
How far I'm willing to take it depends on how confident I am that I won't break anything and how extensive my own changes to the code are going to be.
This is a great situation to show off the benefits of unit tests.
If unit tests are in place, developers can bravely and aggressively refactor oddly written code they might come across. If it passes the unit tests and you've increased readability, then you've done your good deed for the day and can move on.
Without unit tests, simplifying complex code that's filled with voodoo presents a great risk of breaking the code and not even knowing you've introduced a new bug! So most developers will take the cautious route and move on.
For simple refactoring I try to clean up deeply nested control structures and really long functions (more than one screen worth of text). However its not a great idea to refactor code without a good reason (especially in a big team of developers). In general, unless the refactoring will make a big improvement in the code or fix an egregious sin I try to leave well enough alone.
Not refactoring per-say but just as a matter of general housekeeping I generally do this stuff when I start work on a module:
Remove stupid comments
Comments that say nothing more than the function signature already says
Comments that are pure idiocy like "just what it looks like"
Changelogs at the top of the file (we have version control for a reason)
Any API docs that are clearly out-of-sync with the code
Remove commented-out chunks of code
Add version control tags like $Id$ if they are missing
Fix whitespace issues (this can be annoying to others though because your name shows up for a lot of lines in a diff even if all you did was change whitespace)
Remove whitespace at the end of the lines
Change tabs->spaces (for that is our convention where I work)
If the refactor makes the code much easier to read, the most common for me would be duplicate code, e.g. an if/else that only differs by the first/last commands.
if($something) {
load_data($something);
} else {
load_data($something);
echo "Loaded";
do_something_else();
}
More than (arguably) three or four lines of duplicate code always makes me think about refactoring. Also, I tend to move code around a lot, extracting the code I predict to be used more frequently into a separate place - a class with its own well-defined purpose and responsibilites, or a static method of a static class (usually placed in my Utils.* namespace).
But, to answer your question, yes, there are lot of cases when making the code shorter does not necessarily mean making it well structued and readable. Using the ?? operator in C# is another example. What you also have to think about are the new features in your language of choice - e.g. LINQ can be used to do some stuff in a very elegant manner but also can make a very simple thing very unreadable and overly complex. You need to weigh these two thing very carefully, in the end it all boils down to your personal taste and, mostly, experience.
Well, this is another "it depends" answer, but I am afraid it has to be.
I almost always break >2 similar conditionals into a switch... most often with regards to enums. I will short a return instead of a long statement.
ex:
if (condition) {
//lots of code
//returns value
} else {
return null;
}
becomes:
if (!condition)
return null;
//lots of code..
//return value
breaking out early reduces extra indents, and reduces long bits of code... also as a general rule I don't like methods with more than 10-15 lines of code. I like methods to have a singular purpose, even if creating more private methods internally.
Usually I don't refactor the code if I'm just browsing it, not actively working on it.
But sometimes ReSharper points out some stuff I just can't resist to Alt+Enter. :)
I tend to refactor very long functions and methods if I understand the set of inputs and outputs to a block.
This helps readability no end.
I would only refactor the code that I come across and am not actively working on after going through the following steps:
Speak with the author of the code (not always possible) to figure out what that piece of code does. Even if it is obvious to me as to what the piece of code is doing, it always helps to understand the rationale behind why the author may have decided to do something in a certain way. Spending a couple of minutes talking about it would not only help the original author understand your point of view, it also builds trust within the team.
Know or find out what that piece of code is doing in order to test it after re-factoring (A build process with unit tests is very helpful here. It makes the whole thing quick and easy). Run the unit tests before and after the change and ensure nothing is breaking due to your changes.
Send out a heads up to the team (if working with others) and let them know of the upcoming change so nobody is surprised when the change actually occurs
Refactoring for the sake of it is one of the roots of all evil. Please don't ever do it. (Unit tests do somewhat mitigate this).
Is vast swaths of commented out code an antipattern? While not code specifically, (it's comments) I see a lot of this kind of behaviour with people who don't understand how to use source control, and who want to keep the old code around for later so they can more easily go back if a bug was introduced. Whenever I see vast swaths of code that are commented out, I almost always remove them in their entirety.
I try to refactor based on following factors:
Do I understand enough to know whats happening?
Can I easily revert back if this change breaks the code.
Will I have enough time to revert the change back if it breaks the build.
And sometimes, if I have enough time, I refactor to learn. As in, I know my change may break the code, but I dont know where and how. So I change it anyways to find out where its breaking and why. That way I learn more about the code.
My domain has been mobile software (cell phones) where most of the code resides on my PC and wont impact others. Since I also maintain the CI build system for my company I can run a complete product build (for all phones) on the refactored code to ensure it doesnt break anything else. But thats my personal luxury which you may not have.
I tend to refactor global constants and enumerations quite a bit if they can be deemed a low refactor risk. Maybe it's just be, but something like a ClientAccountStatus enum should be in or close to the ClientAccount class rather than being in a GlobalConstAndEnum class.
Deletion/updating of comments which are clearly wrong or clearly pointless.
Removing them is:
safe
version control means you can find them again
improves the quality of the code to others and yourself
It is about the only 100% risk free refactoring I know.
Note that doing this in structured comments like javadoc comments is a different matter. Changing these is not risk free, as such they are very likely to be fixed/removed but not dead certain guaranteed fixes as standard incorrect code comments would be.

Resources