Related
I read that it's a good convention to name functions that return a bool like IsChecksumCorrect(Packet), but I also read that it's a good convention to name boolean variables like IsAvailable = True
But the two rules are incompatible: I can't write:
IsChecksumCorrect = IsChecksumCorrect(Packet)
So what's the best way to name vars that store boolean values returned by such functions?
PS: Extra points if you can think of a way that doesn't depend on changing the case (some languages--like Delphi--are case-insensitive).
First of all, there can be difficulties only with functions that don't require arguments, in your example instead the variable should just be called IsPacketChecksumCorrect.
Even with functions with no arguments I think you would only have problems if you were just caching the result of the function, for performance's sake, and you could safely replace all instances of the variables with calls to the function if it weren't for the performance. In all other cases I think that you could always come up with a more specific name for the variable.
If you were indeed just caching, why not just call the variable Functionname_cache? It seems quite clear to me.
If you needed to use a lot this "technique" in your project and _cache seemed too long or you did not like it you could well settle on a convention of your own; as long as you are consistent you can adopt whatever works best for you, people new to the project just need to be explained the convention once and they will easily recognize it ever after.
By the way, there are various opinions on the conventions for the naming of booleans. Personally I prefer to put the subject first, which makes the Ifs more readable, e.g. ChecksumIsCorrect, ChecksumCorrect or ChecksumCorrectness. I actually prefer not to put the Is altogether, the name usually remains clear even if you omit it.
I'm surprised by a particular bit of syntax-sensitivity in Ruby. These all work:
var = method arg
var2 = (var1 = method arg)
method2(method1 arg)
But this does not:
method2(var = method1 arg)
Instead, I have to do either this, with extra parentheses:
method2(var = method1(arg))
..or this, which I find much more ambiguous than the version that fails:
method2 var = method1(arg)
I assume that this is either a specific design decision or the side effect of another one, and would appreciate any insight into those decisions.
Please note that I'm not looking for any opinions about style; I'm not asking what looks better, or what you think should or should not work. I will even stipulate that this particular construct would be clearer if split into two separate statements entirely. I'm just curious about the actual reasons why Ruby works this way, from anyone who might have that background information.
I assume that this is either a specific design decision or the side effect of another one, and would appreciate any insight into those decisions.
Ruby's syntax is ridiculously complex. And since most Ruby implementations use a parser generator like Bison, which however isn't actually powerful enough to parse such a ridiculously complex language, the parsers tend to be even more ridiculously complex. It's much more likely that it's two weird parsing corner cases interacting in an even weirder way than any sort of conscious design decision.
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.
As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 11 years ago.
Locked. This question and its answers are locked because the question is off-topic but has historical significance. It is not currently accepting new answers or interactions.
I've read some of the recent language vs. language questions with interest... Perl vs. Python, Python vs. Java, Can one language be better than another?
One thing I've noticed is that a lot of us have very superficial reasons for disliking languages. We notice these things at first glance and they turn us off. We shun what are probably perfectly good languages as a result of features that we'd probably learn to love or ignore in 2 seconds if we bothered.
Well, I'm as guilty as the next guy, if not more. Here goes:
Ruby: All the Ruby example code I see uses the puts command, and that's a sort of childish Yiddish anatomical term. So as a result, I can't take Ruby code seriously even though I should.
Python: The first time I saw it, I smirked at the whole significant whitespace thing. I avoided it for the next several years. Now I hardly use anything else.
Java: I don't like identifiersThatLookLikeThis. I'm not sure why exactly.
Lisp: I have trouble with all the parentheses. Things of different importance and purpose (function declarations, variable assignments, etc.) are not syntactically differentiated and I'm too lazy to learn what's what.
Fortran: uppercase everything hurts my eyes. I know modern code doesn't have to be written like that, but most example code is...
Visual Basic: it bugs me that Dim is used to declare variables, since I remember the good ol' days of GW-BASIC when it was only used to dimension arrays.
What languages did look right to me at first glance? Perl, C, QBasic, JavaScript, assembly language, BASH shell, FORTH.
Okay, now that I've aired my dirty laundry... I want to hear yours. What are your language hangups? What superficial features bother you? How have you gotten over them?
I hate Hate HATE "End Function" and "End IF" and "If... Then" parts of VB. I would much rather see a curly bracket instead.
PHP's function name inconsistencies.
// common parameters back-to-front
in_array(needle, haystack);
strpos(haystack, needle);
// _ to separate words, or not?
filesize();
file_exists;
// super globals prefix?
$GLOBALS;
$_POST;
I never really liked the keywords spelled backwards in some scripting shells
if-then-fi is bad enough, but case-in-esac is just getting silly
I just thought of another... I hate the mostly-meaningless URLs used in XML to define namespaces, e.g. xmlns="http://purl.org/rss/1.0/"
Pascal's Begin and End. Too verbose, not subject to bracket matching, and worse, there isn't a Begin for every End, eg.
Type foo = Record
// ...
end;
Although I'm mainly a PHP developer, I dislike languages that don't let me do enough things inline. E.g.:
$x = returnsArray();
$x[1];
instead of
returnsArray()[1];
or
function sort($a, $b) {
return $a < $b;
}
usort($array, 'sort');
instead of
usort($array, function($a, $b) { return $a < $b; });
I like object-oriented style. So it bugs me in Python to see len(str) to get the length of a string, or splitting strings like split(str, "|") in another language. That is fine in C; it doesn't have objects. But Python, D, etc. do have objects and use obj.method() other places. (I still think Python is a great language.)
Inconsistency is another big one for me. I do not like inconsistent naming in the same library: length(), size(), getLength(), getlength(), toUTFindex() (why not toUtfIndex?), Constant, CONSTANT, etc.
The long names in .NET bother me sometimes. Can't they shorten DataGridViewCellContextMenuStripNeededEventArgs somehow? What about ListViewVirtualItemsSelectionRangeChangedEventArgs?
And I hate deep directory trees. If a library/project has a 5 level deep directory tree, I'm going to have trouble with it.
C and C++'s syntax is a bit quirky. They reuse operators for different things. You're probably so used to it that you don't think about it (nor do I), but consider how many meanings parentheses have:
int main() // function declaration / definition
printf("hello") // function call
(int)x // type cast
2*(7+8) // override precedence
int (*)(int) // function pointer
int x(3) // initializer
if (condition) // special part of syntax of if, while, for, switch
And if in C++ you saw
foo<bar>(baz(),baaz)
you couldn't know the meaning without the definition of foo and bar.
the < and > might be a template instantiation, or might be less-than and greater-than (unusual but legal)
the () might be a function call, or might be just surrounding the comma operator (ie. perform baz() for size-effects, then return baaz).
The silly thing is that other languages have copied some of these characteristics!
Java, and its checked exceptions. I left Java for a while, dwelling in the .NET world, then recently came back.
It feels like, sometimes, my throws clause is more voluminous than my method content.
There's nothing in the world I hate more than php.
Variables with $, that's one extra odd character for every variable.
Members are accessed with -> for no apparent reason, one extra character for every member access.
A freakshow of language really.
No namespaces.
Strings are concatenated with ..
A freakshow of language.
All the []s and #s in Objective C. Their use is so different from the underlying C's native syntax that the first time I saw them it gave the impression that all the object-orientation had been clumsily bolted on as an afterthought.
I abhor the boiler plate verbosity of Java.
writing getters and setters for properties
checked exception handling and all the verbiage that implies
long lists of imports
Those, in connection with the Java convention of using veryLongVariableNames, sometimes have me thinking I'm back in the 80's, writing IDENTIFICATION DIVISION. at the top of my programs.
Hint: If you can automate the generation of part of your code in your IDE, that's a good hint that you're producing boilerplate code. With automated tools, it's not a problem to write, but it's a hindrance every time someone has to read that code - which is more often.
While I think it goes a bit overboard on type bureaucracy, Scala has successfully addressed some of these concerns.
Coding Style inconsistencies in team projects.
I'm working on a large team project where some contributors have used 4 spaces instead of the tab character.
Working with their code can be very annoying - I like to keep my code clean and with a consistent style.
It's bad enough when you use different standards for different languages, but in a web project with HTML, CSS, Javascript, PHP and MySQL, that's 5 languages, 5 different styles, and multiplied by the number of people working on the project.
I'd love to re-format my co-workers code when I need to fix something, but then the repository would think I changed every line of their code.
It irritates me sometimes how people expect there to be one language for all jobs. Depending on the task you are doing, each language has its advantages and disadvantages. I like the C-based syntax languages because it's what I'm most used to and I like the flexibility they tend to bestow on the developer. Of course, with great power comes great responsibility, and having the power to write 150 line LINQ statements doesn't mean you should.
I love the inline XML in the latest version of VB.NET although I don't like working with VB mainly because I find the IDE less helpful than the IDE for C#.
If Microsoft had to invent yet another C++-like language in C# why didn't they correct Java's mistake and implement support for RAII?
Case sensitivity.
What kinda hangover do you need to think that differentiating two identifiers solely by caSE is a great idea?
I hate semi-colons. I find they add a lot of noise and you rarely need to put two statements on a line. I prefer the style of Python and other languages... end of line is end of a statement.
Any language that can't fully decide if Arrays/Loop/string character indexes are zero based or one based.
I personally prefer zero based, but any language that mixes the two, or lets you "configure" which is used can drive you bonkers. (Apache Velocity - I'm looking in your direction!)
snip from the VTL reference (default is 1, but you can set it to 0):
# Default starting value of the loop
# counter variable reference.
directive.foreach.counter.initial.value = 1
(try merging 2 projects that used different counter schemes - ugh!)
In no particular order...
OCaml
Tuples definitions use * to separate items rather than ,. So, ("Juliet", 23, true) has the type (string * int * bool).
For being such an awesome language, the documentation has this haunting comment on threads: "The threads library is implemented by time-sharing on a single processor. It will not take advantage of multi-processor machines. Using this library will therefore never make programs run faster." JoCaml doesn't fix this problem.
^^^ I've heard the Jane Street guys were working to add concurrent GC and multi-core threads to OCaml, but I don't know how successful they've been. I can't imagine a language without multi-core threads and GC surviving very long.
No easy way to explore modules in the toplevel. Sure, you can write module q = List;; and the toplevel will happily print out the module definition, but that just seems hacky.
C#
Lousy type inference. Beyond the most trivial expressions, I have to give types to generic functions.
All the LINQ code I ever read uses method syntax, x.Where(item => ...).OrderBy(item => ...). No one ever uses expression syntax, from item in x where ... orderby ... select. Between you and me, I think expression syntax is silly, if for no other reason than that it looks "foreign" against the backdrop of all other C# and VB.NET code.
LINQ
Every other language uses the industry standard names are Map, Fold/Reduce/Inject, and Filter. LINQ has to be different and uses Select, Aggregate, and Where.
Functional Programming
Monads are mystifying. Having seen the Parser monad, Maybe monad, State, and List monads, I can understand perfectly how the code works; however, as a general design pattern, I can't seem to look at problems and say "hey, I bet a monad would fit perfect here".
Ruby
GRRRRAAAAAAAH!!!!! I mean... seriously.
VB
Module Hangups
Dim _juliet as String = "Too Wordy!"
Public Property Juliet() as String
Get
Return _juliet
End Get
Set (ByVal value as String)
_juliet = value
End Set
End Property
End Module
And setter declarations are the bane of my existence. Alright, so I change the data type of my property -- now I need to change the data type in my setter too? Why doesn't VB borrow from C# and simply incorporate an implicit variable called value?
.NET Framework
I personally like Java casing convention: classes are PascalCase, methods and properties are camelCase.
In C/C++, it annoys me how there are different ways of writing the same code.
e.g.
if (condition)
{
callSomeConditionalMethod();
}
callSomeOtherMethod();
vs.
if (condition)
callSomeConditionalMethod();
callSomeOtherMethod();
equate to the same thing, but different people have different styles. I wish the original standard was more strict about making a decision about this, so we wouldn't have this ambiguity. It leads to arguments and disagreements in code reviews!
I found Perl's use of "defined" and "undefined" values to be so useful that I have trouble using scripting languages without it.
Perl:
($lastname, $firstname, $rest) = split(' ', $fullname);
This statement performs well no matter how many words are in $fullname. Try it in Python, and it explodes if $fullname doesn't contain exactly three words.
SQL, they say you should not use cursors and when you do, you really understand why...
its so heavy going!
DECLARE mycurse CURSOR LOCAL FAST_FORWARD READ_ONLY
FOR
SELECT field1, field2, fieldN FROM atable
OPEN mycurse
FETCH NEXT FROM mycurse INTO #Var1, #Var2, #VarN
WHILE ##fetch_status = 0
BEGIN
-- do something really clever...
FETCH NEXT FROM mycurse INTO #Var1, #Var2, #VarN
END
CLOSE mycurse
DEALLOCATE mycurse
Although I program primarily in python, It irks me endlessly that lambda body's must be expressions.
I'm still wrapping my brain around JavaScript, and as a whole, Its mostly acceptable. Why is it so hard to create a namespace. In TCL they're just ugly, but in JavaScript, it's actually a rigmarole AND completely unreadable.
In SQL how come everything is just one, huge freekin SELECT statement.
In Ruby, I very strongly dislike how methods do not require self. to be called on current instance, but properties do (otherwise they will clash with locals); i.e.:
def foo()
123
end
def foo=(x)
end
def bar()
x = foo() # okay, same as self.foo()
x = foo # not okay, reads unassigned local variable foo
foo = 123 # not okay, assigns local variable foo
end
To my mind, it's very inconsistent. I'd rather prefer to either always require self. in all cases, or to have a sigil for locals.
Java's packages. I find them complex, more so because I am not a corporation.
I vastly prefer namespaces. I'll get over it, of course - I'm playing with the Android SDK, and Eclipse removes a lot of the pain. I've never had a machine that could run it interactively before, and now I do I'm very impressed.
Prolog's if-then-else syntax.
x -> y ; z
The problem is that ";" is the "or" operator, so the above looks like "x implies y or z".
Java
Generics (Java version of templates) are limited. I can not call methods of the class and I can not create instances of the class. Generics are used by containers, but I can use containers of instances of Object.
No multiple inheritance. If a multiple inheritance use does not lead to diamond problem, it should be allowed. It should allow to write a default implementation of interface methods, a example of problem: the interface MouseListener has 5 methods, one for each event. If I want to handle just one of them, I have to implement the 4 other methods as an empty method.
It does not allow to choose to manually manage memory of some objects.
Java API uses complex combination of classes to do simple tasks. Example, if I want to read from a file, I have to use many classes (FileReader, FileInputStream).
Python
Indentation is part of syntax, I prefer to use the word "end" to indicate end of block and the word "pass" would not be needed.
In classes, the word "self" should not be needed as argument of functions.
C++
Headers are the worst problem. I have to list the functions in a header file and implement them in a cpp file. It can not hide dependencies of a class. If a class A uses the class B privately as a field, if I include the header of A, the header of B will be included too.
Strings and arrays came from C, they do not provide a length field. It is difficult to control if std::string and std::vector will use stack or heap. I have to use pointers with std::string and std::vector if I want to use assignment, pass as argument to a function or return it, because its "=" operator will copy entire structure.
I can not control the constructor and destructor. It is difficult to create an array of objects without a default constructor or choose what constructor to use with if and switch statements.
In most languages, file access. VB.NET is the only language so far where file access makes any sense to me. I do not understand why if I want to check if a file exists, I should use File.exists("") or something similar instead of creating a file object (actually FileInfo in VB.NET) and asking if it exists. And then if I want to open it, I ask it to open: (assuming a FileInfo object called fi) fi.OpenRead, for example. Returns a stream. Nice. Exactly what I wanted. If I want to move a file, fi.MoveTo. I can also do fi.CopyTo. What is this nonsense about not making files full-fledged objects in most languages? Also, if I want to iterate through the files in a directory, I can just create the directory object and call .GetFiles. Or I can do .GetDirectories, and I get a whole new set of DirectoryInfo objects to play with.
Admittedly, Java has some of this file stuff, but this nonsense of having to have a whole object to tell it how to list files is just silly.
Also, I hate ::, ->, => and all other multi-character operators except for <= and >= (and maybe -- and ++).
[Disclaimer: i only have a passing familiarity with VB, so take my comments with a grain of salt]
I Hate How Every Keyword In VB Is Capitalized Like This. I saw a blog post the other week (month?) about someone who tried writing VB code without any capital letters (they did something to a compiler that would let them compile VB code like that), and the language looked much nicer!
My big hangup is MATLAB's syntax. I use it, and there are things I like about it, but it has so many annoying quirks. Let's see.
Matrices are indexed with parentheses. So if you see something like Image(350,260), you have no clue from that whether we're getting an element from the Image matrix, or if we're calling some function called Image and passing arguments to it.
Scope is insane. I seem to recall that for loop index variables stay in scope after the loop ends.
If you forget to stick a semicolon after an assignment, the value will be dumped to standard output.
You may have one function per file. This proves to be very annoying for organizing one's work.
I'm sure I could come up with more if I thought about it.
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
A colleague of mine states that booleans as method arguments are not acceptable. They shall be replaced by enumerations. At first I did not see any benefit, but he gave me an example.
What's easier to understand?
file.writeData( data, true );
Or
enum WriteMode {
Append,
Overwrite
};
file.writeData( data, Append );
Now I got it! ;-)
This is definitely an example where an enumeration as second parameter makes the code much more readable.
So, what's your opinion on this topic?
Boolean's represent "yes/no" choices. If you want to represent a "yes/no", then use a boolean, it should be self-explanatory.
But if it's a choice between two options, neither of which is clearly yes or no, then an enum can sometimes be more readable.
Enums also allow for future modifications, where you now want a third choice (or more).
Use the one that best models your problem. In the example you give, the enum is a better choice. However, there would be other times when a boolean is better. Which makes more sense to you:
lock.setIsLocked(True);
or
enum LockState { Locked, Unlocked };
lock.setLockState(Locked);
In this case, I might choose the boolean option since I think it's quite clear and unambiguous, and I'm pretty sure my lock is not going to have more than two states. Still, the second choice is valid, but unnecessarily complicated, IMHO.
To me, neither using boolean nor enumeration is a good approach. Robert C. Martin captures this very clearly in his Clean Code Tip #12: Eliminate Boolean Arguments:
Boolean arguments loudly declare that the function does more than one thing. They are confusing and should be eliminated.
If a method does more than one thing, you should rather write two different methods, for example in your case: file.append(data) and file.overwrite(data).
Using an enumeration doesn't make things clearer. It doesn't change anything, it's still a flag argument.
Remember the question Adlai Stevenson posed to ambassador Zorin at the U.N. during the cuban missile crisis?
"You are in the courtroom of world
opinion right now, and you can answer
yes or no. You have denied that [the missiles]
exist, and I want to know whether I
have understood you correctly.... I am
prepared to wait for my answer until
hell freezes over, if that's your
decision."
If the flag you have in your method is of such a nature that you can pin it down to a binary decision, and that decision will never turn into a three-way or n-way decision, go for boolean. Indications: your flag is called isXXX.
Don't make it boolean in case of something that is a mode switch. There is always one more mode than you thought of when writing the method in the first place.
The one-more-mode dilemma has e.g. haunted Unix, where the possible permission modes a file or directory can have today result in weird double meanings of modes depending on file type, ownership etc.
There are two reasons I've run into this being a bad thing:
Because some people will write methods like:
ProcessBatch(true, false, false, true, false, false, true);
This is obviously bad because it's too easy to mix up parameters, and you have no idea by looking at it what you're specifying. Just one bool isn't too bad though.
Because controlling program flow by a simple yes/no branch might mean you have two entirely different functions that are wrapped up into one in an awkard way. For instance:
public void Write(bool toOptical);
Really, this should be two methods
public void WriteOptical();
public void WriteMagnetic();
because the code in these might be entirely different; they might have to do all sorts of different error handling and validation, or maybe even have to format the outgoing data differently. You can't tell that just by using Write() or even Write(Enum.Optical) (though of course you could have either of those methods just call internal methods WriteOptical/Mag if you want).
I guess it just depends. I wouldn't make too big of a deal about it except for #1.
I think you almost answered this yourself, I think the end aim is to make the code more readable, and in this case the enum did that, IMO its always best to look at the end aim rather than blanket rules, maybe think of it more as a guideline i.e. enums are often more readable in code than generic bools, ints etc but there will always be exceptions to the rule.
Enums are better but I wouldn't call boolean params as "unacceptable". Sometimes it's just easier to throw one little boolean in and move on (think private methods etc.)
Booleans may be OK in languages that have named parameters, like Python and Objective-C, since the name can explain what the parameter does:
file.writeData(data, overwrite=true)
or:
[file writeData:data overwrite:YES]
Enums have a definite benefit, but you should't just go replacing all your booleans with enums. There are many places where true/false is actually the best way to represent what is going on.
However, using them as method arguments is a bit suspect, simply because you can't see without digging into things what they are supposed to do, as they let you see what the true/false actually means
[Edit for the current state in 2022]
In modern C#, or other languages that support this, the nicest way to do it is with named arguments:
var worker = new BackgroundWorker(workerReportsProgress: true);
If your language doesn't allow for named arguments, then you may find properties to be a reasonable solution as well
[Original Answer from 2008 left for posterity]
Properties (especially with C#3 object initializers) or keyword arguments (a la ruby or python) are a much better way to go where you'd otherwise use a boolean argument.
C# example:
var worker = new BackgroundWorker { WorkerReportsProgress = true };
Ruby example
validates_presence_of :name, :allow_nil => true
Python example
connect_to_database( persistent=true )
The only thing I can think of where a boolean method argument is the right thing to do is in java, where you don't have either properties or keyword arguments. This is one of the reasons I hate java :-(
I would not agree that it is a good rule. Obviously, Enum makes for a better explicit or verbose code at some instances, but as a rule it seems way over reaching.
First let me take your example:
The programmers responsibility (and ability) to write good code is not really jeopardized by having a Boolean parameter. In your example the programmer could have written just as verbose code by writing:
dim append as boolean = true
file.writeData( data, append );
or I prefer more general
dim shouldAppend as boolean = true
file.writeData( data, shouldAppend );
Second:
The Enum example you gave is only "better" because you are passing a CONST. Most likely in most application at least some if not most of the time parameters that are passed to functions are VARIABLES. in which case my second example (giving variables with good names) is much better and Enum would have given you little benefits.
While it is true that in many cases enums are more readable and more extensible than booleans, an absolute rule that "booleans are not acceptable" is daft. It is inflexible and counter-productive - it does not leave room for human judgement. They're a fundamental built in type in most languages because they're useful - consider applying it to other built-in-types: saying for instance "never use an int as a parameter" would just be crazy.
This rule is just a question of style, not of potential for bugs or runtime performance. A better rule would be "prefer enums to booleans for reasons of readability".
Look at the .Net framework. Booleans are used as parameters on quite a few methods. The .Net API is not perfect, but I don't think that the use of boolean as parameters is a big problem. The tooltip always gives you the name of the parameter, and you can build this kind of guidance too - fill in your XML comments on the method parameters, they will come up in the tooltip.
I should also add that there is a case when you should clearly refactor booleans to an enumeration - when you have two or more booleans on your class, or in your method params, and not all states are valid (e.g. it's not valid to have them both set true).
For instance, if your class has properties like
public bool IsFoo
public bool IsBar
And it's an error to have both of them true at the same time, what you've actually got is three valid states, better expressed as something like:
enum FooBarType { IsFoo, IsBar, IsNeither };
Some rules that your colleague might be better adhering to are:
Don't be dogmatic with your design.
Choose what fits most appropriately for the users of your code.
Don't try to bash star-shaped pegs into every hole just because you like the shape this month!
A Boolean would only be acceptable if you do not intend to extend the functionality of the framework. The Enum is preferred because you can extend the enum and not break previous implementations of the function call.
The other advantage of the Enum is that is easier to read.
If the method asks a question such as:
KeepWritingData (DataAvailable());
where
bool DataAvailable()
{
return true; //data is ALWAYS available!
}
void KeepWritingData (bool keepGoing)
{
if (keepGoing)
{
...
}
}
boolean method arguments seem to make absolutely perfect sense.
It depends on the method. If the method does something that is very obviously a true/false thing then it is fine, e.g. below [though not I am not saying this is the best design for this method, it's just an example of where the usage is obvious].
CommentService.SetApprovalStatus(commentId, false);
However in most cases, such as the example you mention, it is better to use an enumeration. There are many examples in the .NET Framework itself where this convention is not followed, but that is because they introduced this design guideline fairly late on in the cycle.
It does make things a bit more explicit, but does start to massively extend the complexity of your interfaces - in a sheer boolean choice such as appending/overwriting it seems like overkill. If you need to add a further option (which I can't think of in this case), you can always perform a refactor (depending on the language)
Enums can certainly make the code more readable. There are still a few things to watch out for (in .net at least)
Because the underlying storage of an enum is an int, the default value will be zero, so you should make sure that 0 is a sensible default. (E.g. structs have all fields set to zero when created, so there's no way to specify a default other than 0. If you don't have a 0 value, you can't even test the enum without casting to int, which would be bad style.)
If your enum's are private to your code (never exposed publicly) then you can stop reading here.
If your enums are published in any way to external code and/or are saved outside of the program, consider numbering them explicitly. The compiler automatically numbers them from 0, but if you rearrange your enums without giving them values you can end up with defects.
I can legally write
WriteMode illegalButWorks = (WriteMode)1000000;
file.Write( data, illegalButWorks );
To combat this, any code that consumes an enum that you can't be certain of (e.g. public API) needs to check if the enum is valid. You do this via
if (!Enum.IsDefined(typeof(WriteMode), userValue))
throw new ArgumentException("userValue");
The only caveat of Enum.IsDefined is that it uses reflection and is slower. It also suffers a versioning issue. If you need to check the enum value often, you would be better off the following:
public static bool CheckWriteModeEnumValue(WriteMode writeMode)
{
switch( writeMode )
{
case WriteMode.Append:
case WriteMode.OverWrite:
break;
default:
Debug.Assert(false, "The WriteMode '" + writeMode + "' is not valid.");
return false;
}
return true;
}
The versioning issue is that old code may only know how to handle the 2 enums you have. If you add a third value, Enum.IsDefined will be true, but the old code can't necessarily handle it. Whoops.
There's even more fun you can do with [Flags] enums, and the validation code for that is slightly different.
I'll also note that for portability, you should use call ToString() on the enum, and use Enum.Parse() when reading them back in. Both ToString() and Enum.Parse() can handle [Flags] enum's as well, so there's no reason not to use them. Mind you, it's yet another pitfall, because now you can't even change the name of the enum without possibly breaking code.
So, sometimes you need to weigh all of the above in when you ask yourself Can I get away with just an bool?
IMHO it seems like an enum would be the obvious choice for any situation where more than two options are possible. But there definitely ARE situations where a boolean is all you need. In that case I would say that using an enum where a bool would work would be an example of using 7 words when 4 will do.
Booleans make sense when you have an obvious toggle which can only be one of two things (i.e. the state of a light bulb, on or off). Other than that, it's good to write it in such a way that it's obvious what you're passing - e.g. disk writes - unbuffered, line-buffered, or synchronous - should be passed as such. Even if you don't want to allow synchronous writes now (and so you're limited to two options), it's worth considering making them more verbose for the purposes of knowing what they do at first glance.
That said, you can also use False and True (boolean 0 and 1) and then if you need more values later, expand the function out to support user-defined values (say, 2 and 3), and your old 0/1 values will port over nicely, so your code ought not to break.
Sometimes it's just simpler to model different behaviour with overloads. To continue from your example would be:
file.appendData( data );
file.overwriteData( data );
This approach degrades if you have multiple parameters, each allowing a fixed set of options. For example, a method that opens a file might have several permutations of file mode (open/create), file access (read/write), sharing mode (none/read/write). The total number of configurations is equal to the Cartesian products of the individual options. Naturally in such cases multiple overloads are not appropriate.
Enums can, in some cases make code more readable, although validating the exact enum value in some languages (C# for example) can be difficult.
Often a boolean parameter is appended to the list of parameters as a new overload. One example in .NET is:
Enum.Parse(str);
Enum.Parse(str, true); // ignore case
The latter overload became available in a later version of the .NET framework than the first.
If you know that there will only ever be two choices, a boolean might be fine. Enums are extensible in a way that won't break old code, although old libraries might not support new enum values so versioning cannot be completely disregarded.
EDIT
In newer versions of C# it's possible to use named arguments which, IMO, can make calling code clearer in the same way that enums can. Using the same example as above:
Enum.Parse(str, ignoreCase: true);
Where I do agree that Enums are good way to go, in methods where you have 2 options (and just two options you can have readability without enum.)
e.g.
public void writeData(Stream data, boolean is_overwrite)
Love the Enums, but boolean is useful too.
This is a late entry on an old post, and it's so far down the page that nobody will ever read it, but since nobody has said it already....
An inline comment goes a long way to solving the unexpected bool problem. The original example is particularly heinous: imagine trying to name the variable in the function declearation! It'd be something like
void writeData( DataObject data, bool use_append_mode );
But, for the sake of example, let's say that's the declaration. Then, for an otherwise unexplained boolean argument, I put the variable name in an inline comment. Compare
file.writeData( data, true );
with
file.writeData( data, true /* use_append_mode */);
It really depends on the exact nature of the argument. If it is not a yes/no or true/false then a enum makes it more readable. But with an enum you need to check the argument or have acceptable default behaviour since undefined values of the underlying type can be passed.
The use of enums instead of booleans in your example does help make the method call more readable. However, this is a substitute for my favorite wish item in C#, named arguments in method calls. This syntax:
var v = CallMethod(pData = data, pFileMode = WriteMode, pIsDirty = true);
would be perfectly readable, and you could then do what a programmer should do, which is choose the most appropriate type for each parameter in the method without regard to how it looks in the IDE.
C# 3.0 allows named arguments in constructors. I don't know why they can't do this with methods as well.
Booleans values true/false only. So it is not clear what it represent. Enum can have meaningful name, e.g OVERWRITE, APPEND, etc. So enums are better.