Beautiful Code Interview
An anonymous reader writes "Safari Books Online has just posted an interview with Andy Oram and Greg Wilson, the two editors who put together the recent O'Reilly book, Beautiful Code. "Beautiful Code" features 33 different case studies about challenging coding scenarios from some of today's most high-profile developers and OS project leaders. There's also a new Beautiful Code web site based on the book where many of the authors are blogging about their work and coding practices."
Yeah, thats about the amount of beautiful code I expect to see in my life time.
I still have more fans than freaks. WTF is wrong with you people?
I find it amusing that TFA has tons of html errors.
His introduction to C++ teacher told him throughout the class that his code was not "pretty" because he wasn't properly commenting. The code always worked flawlessly, but still she marked "-1 code not pretty"
//Look at my flower,
//my pretty pretty flower.
//Now my code is pretty
On the final project he spent a good portion of time properly commenting all of his code and ended with a commented ascii flower and the following:
He was marked off "-1 Sarcasm not appreciated"
If you haven't looked at it already, you should glance through the OpenBSD source code. It's truly remarkable how well-written it is. But I wouldn't consider it "beautiful". I think studly is a better word. It's rugged, strong, and built to handle the toughest of the tough.
But I find goto is often as beautiful as it gets:
for (loop 1) {
for (loop 2) {
if (something happens that makes me want to bail on both loops) {
goto loop_done;
}
do_inner_loop_work;
}
}
loop_done:
Free Conference Call -- No Spam, High Quality
Programmer - You are sooo beautiful. My masterpiece. My pies de resistance!
[ Kisses screen and compiles code into native instruction set ]
CPU - Hmm. Where have I seen your fugly face before?
I hope, when they die, cartoon characters have to answer for their sins.
Anyone else have laugh when they looked at the cover of the book?
A Flock of Birds?
To symbolize beautiful code?
Flock-of-Birds-style code is the UGLIEST code out there!
Used only by those who haven't learned to use case statements, build databases, or define arrays.
Is this beautiful code???
if(something==interesting)
if(somethingelse==goodcode)
if(somethingother==blahblahblah)
if(somestupidbookcover=birds)
doSomethingUseful();
else
else
else
else
if(somethingelse==goodcode)
if(somethingother==blahblahblah)
if(somestupidbookcover=birds)
doSomethingUseful();
else
else
else
end if
I have yet to see a really good example other than my own.
I, too, am the only one I know who writes decent code.
I struggle with this. When I was in school, my instructors drilled into me the importance of documentation and comments. Now that I've been in the real world, I have to say that I don't agree.
The problem with comments is that you now have two things to maintain, the code and the comments. Often time this is OK for a single developer but for someone coming in to maintain a piece of code, often times they are hesitant to touch the comments especially if they are wrong.
I find that (for me at least) I have the greatest success with short, composed methods that do one thing and one thing well all backed up by unit tests that test behavior and requirements, not simply that foo() returns 15.
You might be thinking that I'm contradicting myself here because now I have to maintain both code and tests. However, I feel that the tests provide much more value in that once a test for a piece of code works, you now have confidence in that piece of code. If you miss something with the test, its a simple matter of adding a new test for that case.
Now that I've been in the real world, I have to say that I don't agree.
I have to respectfully say that if you believe this, you haven't written 1) enough code, and 2) complex enough code, to have filled up your brain sufficiently to where you can't remember what the hell you were thinking at that time. When you've reached that level of programmer maturity, THEN you will understand the importance of comments. :)
Never mind trying to blaze the trail for programmers that come after you. I also predict that you haven't tried to unravel another programmer's crappy code.
The problem with comments is that you now have two things to maintain, the code and the comments
Yes. People who change code but don't update the comments should be flayed appropriately.
I find that (for me at least) I have the greatest success with short, composed methods that do one thing and one thing well all backed up by unit tests that test behavior and requirements, not simply that foo() returns 15.
Testing and commenting are two different subjects. Comments are not to tell you that "foo() returns 15", comments are to tell you the *context* of code, how it fits in with the overall goal of the subroutine.
Sometimes it's best to just let stupid people be stupid.
while (1){
Beer b = (Beer)getBeer();
drinkBeer(b);
belch(BelchType.LOUDLY);
}
Yeah? Well I think you're overrated too.
Most code is beautiful at one point in time - namely, when it's first written. A decent programmer can produce some decent code that performs the task at hand elegantly. With a little work this can become beautiful. Most applications I write start out very elegant, beautiful, commented, clever, etc. - It's only after the project grows and I'm working on a file named "main4.3.a.iii.bak2.worksithink.c" that the comments turn into "// why is this here?" and the variables go from "nDBEntryCount" to "temp" and the code becomes an ugly mess.
The real trick is DESIGNING the application in such a way that it can grow gracefully, and STAY beautiful. And that's really tough - knowing what sorts of features and requirements the future will hold is difficult. A big part of this is the language itself - I love assembly languages, and I could write some really clever and beautiful assembly code. But when the requirements change and the code needs a new feature? There goes all the carefully timed loops and cycle counts!
Beautiful code is as much beautiful, expandable, future-proof design as it is beautiful implementation.
I don't know why you'd single out open source, this applies to code at large. I think it's just one of those '90% percent of everything is crap' things.
In a fair world, refrigerators would make electricity.
http://xkcd.com/292/
That is all.
I've been webcoding sice around '01. I've recently had to go back and do some work on a site I haven't touched in around five years. The thing I found was really ugly code and almost no comments - ok I was using dreamweaver at the time and have graduated to hand coding since. It was bloody hard to do even quite basic alterations. I was half tempted to do a complete re-design using css and w3c standards. As it stands at the moment I'm pretty embarrased that I ever set such ugly code into the wild
I don't know why you'd single out open source, this applies to code at large. I think it's just one of those '90% percent of everything is crap' things.
I agree that a lot of closed source code is crappy as well, but there's at least a chance of institutional standards that can be enforced. There's also a higher proportion of professionals that believe in good code, whereas you have a higher proportion of amateurs for OSS (because anyone can work on an OSS, but not everyone can manage to be hired at a company).
Sometimes it's best to just let stupid people be stupid.
Is anyone else jaded by these books that go on and on about why a particular techique or code snippet or methodology is "right" or "beautiful" or "the way forward"?
...then there's some of the frameworks and methodologies out there that are generally worshiped as God's own code, but which when you try to use them turn out to be cumbersome, horrible, unintuitive messes. Years later this is suddenly "discovered" (EJBs I'm thinking of you!!!) and a whole new set of horrible frameworks goes through several iterations (Hibernate 1 vs 2 vs Spring persistence, Struts vs Spring MVC) where nothing is allowed to mature for long enough to have the major bugs ironed out.
I look at some of the code mentioned and yes it's neat. Some of the code snippets from these books (not just this one specifically) is either really obvious or makes me want to blow chunks because it's an over-complication or over-simplification just to demonstrate a technique which you know will be over-applied and end up in some set of corporate standards that sees it being misused.
Perhaps I'm just getting old but I'm really getting tired of all this. You want to know what makes code beautiful?
1) It does the job 100% correctly as intended.
2) It does it as simply as possible - not so simple it doesn't work, and no more complex than it absolutely needs to be...building everything in but the kitchen sink just in case is a fool's game.
3) It's readable and well documented enough that anyone who knows the language (or better yet a programmer familiar with a similar framework but not this one) understands it.
4) Its easy and quick to make changes as requirements change - that means GUI tools for GUI development (What ever happened to RAD tools being the norm in the industry!? It can take a week to make significant changes to a web page in Struts or Spring MVC, where it use to take about a day to do it for the clients developed with the RAD tools of the late 90s!)
5) It fits in well with the rest of the system. A module that works beautifully in isolation but doesn't fit in with the system can ruin the system.
All the rest is just a bunch of consultants trying to bilk you for cash.
Yes patterns can help, but they can also hurt.
Yes externalizing code into config files can make a system more flexible (but you'll pay for it in readability and tracability/debugability).
Yes aspects of the agile methodology - continual integration and test driven coding - can help but they're not the only way and there's a cost associated.
Yes Object oriented code offers things that procedural does not, but again there's a cost and your developers better understand the language constructs.
You need to look at each of the above as tools in your arsenal, not religious doctrine.
Note that my recent experience is with Java/J2EE so that's where my examples come from but I've worked on dozens of languages and frameworks.
These posts express my own personal views, not those of my employer
Don't feel bad, I've used FrontPage and designed IE only sites before... now it's all proper xhtml and css. The best thing about making mistakes is learning from them.
Mr. Universe: "They can't stop the signal, Mal. They can never stop the signal."
Again, I think that this is where the importance of short, composed methods really shines through. If every method you're looking at is 5 - 10 lines long, its a lot easier to grasp what a block of code is doing. Of course, one could get carried away and get "delegation happy" but thats what a good debugger is for :)
Never mind trying to blaze the trail for programmers that come after you. I also predict that you haven't tried to unravel another programmer's crappy code.I have and its unpleasant. At my previous job, I worked with some poor developers who happened to be non-native English speakers. When comments are written in English and the person writing them does not have a solid command of the language, it can get ugly.
I'm young in my career and time could certainly change my attitude but for the time being, I stand by my original post.
So, you would rather write code and tests rather than code and comments?
Sounds to me like more work and less information available for the poor fool who has to maintain that code after you leave.
And WTF do tests have to do with writing and maintaining code? You have to test everything regardless of how pretty or informative your code is.
All of the programmers (I wouldn't call any of them "software engineers") whom I've worked with the past 25 years thought that writing comments to their code was for wimps. (Much like the pickup truck drivers who think their balls will shrink if they turn on the headlights on a rainy day.)
Frankly, they just don't want to be bothered writing maintainbale code because it takes time and requires some intelligence. (I'm talking about you, Bob, Ron, John, Dan or whoever's left at FAPD.)
Fata viam invenient.
Sure, you can figure out what the code is doing, but in order to know why the code is doing it you still need comments.
"[Regarding the 'cloud,'] ownership was what made America different than Russia." -- Woz
There is a memory leak in your code. Or maybe it's a feature?
It is much easier to get hired at a company than to produce open source code that anyone other than you will ever either use or look at.
--
WHO ATE MY BREAKFAST PANTS?
...looked like this:
not exp log srand xor s qq qx xor
s x x length uc ord and print chr
ord for qw q join use sub tied qx
xor eval xor print qq q q xor int
eval lc q m cos and print chr ord
for qw y abs ne open tied hex exp
ref y m xor scalar srand print qq
q q xor int eval lc qq y sqrt cos
and print chr ord for qw x printf
each return local x y or print qq
s s and eval q s undef or oct xor
time xor ref print chr int ord lc
foreach qw y hex alarm chdir kill
exec return y s gt sin sort split
Simply elegant! My younger brother sent it to me; not sure where he got it. It's Perl, by the way.
MCSE? No, sir...I don't do Windows. Yes, I am an idealist. What's your point?
Ugh, Java frameworks.
Somebody needs to drag the people who make these things in a room, erase their memories, and make them use what they have created. Perhaps then they can start to feel how asinine they can be sometimes. It is as if they get off on how many design patterns, random XML config files, and other "best practices" they can cram into a single framework. "We're switching to using a BuilderFactoryGatewayStrategyFacade." Thanks for the heads-up guys, we were all dying to know exactly how you implemented it! (Don't forget to scatter pattern names all over your code. People have to know you're using them!) All I want to do is integrate such and such framework in with my program. But, no, I have to read the documentation that describes the problem and how exactly to use the framework. Inevitably, they begin spouting off about how "elegant" it is that you can configure exactly which IntFactory to use by hard-coding the classname in a mandatory configuration file that is prone to getting lost at deployment time. (Remember, making objects with just the new operator is a classic beginner's mistake, don't fall prey!)
The end result is you end up with what should be a fairly simple task (like OO-relational mapping) have 400 page manuals because it ends up doing every little thing that people want to do. In the time it takes you to choose the right framework, download and install the binaries, wade through the required config files, sift through the quickstart, and actually get familiar with how it is done, you could have just written and tested the tedious JDBC code to load and unload an object from the database.
But, why do that? There's no hype around that! You're not REALLY an enterprise architect until you have twenty different config files that need to be present just to run your product! If it is an enterprise product, it shouldn't be simple to configure!
All of these products do serve legitimate needs. But the obsessive over-engineering that surrounds them and the religious fervor by which they are declared Good (despite violating the principle of least surprise at every turn) point to fear. A fear that the code you're writing just isn't good enough somehow. The fear that your code is too simple, too straightforward. A worry that that requirement you're meeting is mission-critical, and, mishandled, could threaten the stability of the entire system. This isn't usually the case. It would seem that Java's simplicity sort of drives its hardcore users mad after awhile. What it lacks in expressiveness, people try to make up for by inane configuration and extensibility instead of just sitting down and Getting The Damn Thing Done. Sure, the code is boring. The best code is anything but glamorous.
I think there are two kinds of beauty in code: visual and logical. Visually beautiful code is code that is formatted well, easy to skim through, and easy to read. This includes things like defining useful variable/function names and writing understandable comments. Logically beautiful code is code that is designed to fit together well, makes a lot of sense, and leaves no confusion. It expresses its intent in the simplest and cleanest way possible.
I think getting code to be logically beautiful is much harder of the two. It takes a lot of insight to see a simpler and cleaner way of expressing the same thing. To use a math analogy, a coder might get his code to work with this:
F = (0.25 * m * x * a * 4) / x
but not realize that it can be simplified to this:
F = m * a
You can teach people how to be visually beautiful with their code, but when it comes to logical beauty, they either have it, or they don't.
Respect the laws of physics, for the laws of physics have no respect for you.
I usually put the loops in a method and do it like this. People don't like my returns in the middle of a loop either.
for (loop 1)
{ for (loop 2)
{ if (some condition)
{ return;
}
do work;
}
}
code sucks but I (and the 90% of programmers who make this claim) are in the remaining elite 10% that are coding Gods.
Tests can be a form of documentation too. A proper suite of unit tests will show exactly what a method does. If the method does something different than expected then the tests will fail.
We all know what to do, but we don't know how to get re-elected once we have done it
When you're done designing your application in a way that it will grow gracefully and stay beautifully, come see me, because you'll be out of a job for not shipping the product on time.
You say that knowing the future requirements is difficult. That's the key insight: you just don't know. And unless you know, or have a good likely-to-happen general idea, you should not design it in any way other than as simple as it needs to be for right now. And if you guess, you are likely to end up with flexibility in all the wrong places.
The trick is to design simple for what you need now (easy), and then be able to expand your design to stay simple (hard).
This is difficult to accomplish because changing existing code is a no-no in software dev corps. "If it ain't broke, don't fix it" mentality dooms your project and causes you to accumulate massive design debt because of the hacks and not-simple solutions that do not touch existing code.
This design debt grows to mountain proportions, at which point everyone throws their hands up and assert that a complete rewrite is required.
The cure is to perform test-driven development, so that you are not afraid to change existing code. I can't emphasize how liberating it is to be able to come in and uproot some inflexible crap (which was good enough for a long time, but is not anymore), put in an improved design, and then know that you didn't break anything. You can roll with the punches and not waste your time designing in unnecessary flexibility.
87362 38726 88872 61726 67672 88872 13102 91228
77798 77798 15882 13232 54060 54060 18577 00000
You fucktard! That string caused Windows to send an "I dump you" IM to my significant other.
Table-ized A.I.
Coming to that realization was the hardest thing I've ever had to do.
</kidding>
The problem with comments is that you now have two things to maintain, the code and the comments.
The problem with NO comments is that debugging can not determine wither code is correct - it can only find whether two representations of a solution are equivalent. "The code is the documentation" means the only thing that can be tested is the compiler.
This is because what is correct varies, depending on what the job is. (You may have written a bug free version of "cat". But it's very badly broken if you intended to write "ls".)
So a good programmer writes TWO versions of his program - in representations as different as possible. (Preferably one optimized for automated translation, one for human readability.) That way he's thinking in different mindsets, greatly reducing the likelihood of making identical errors in both representations.)
Bantam Dominique roosters crow a four-note song. Once you've heard it as "Happy BIRTHday" you can't NOT hear it that way
I purchased the book after reading this recent slashdot thread, where I believe Mr. O' Reilly mentioned it himself. My degrees are literature and poetry, so I probably have a slightly different aesthetic than most programmers. I'm leisurely working my way through the book and enjoying it. Most the examples provided don't strike me as breathtakingly beautiful so much as intelligent solutions to interesting problems.
3 /aat/a_diop.html#diophant
One example I do find beautiful, after reading some of the explications of it, was this one mentioned a while back on slashdot:
Origin of Quake3's Fast InvSqrt()
I also find the algorithm here beautiful insofar as it elegantly solves a challenging problem that I was working on commonly faced by accountants:
http://www.geocities.com/SiliconValley/Garage/332
By the way, for truly poetic code, see the works of Kay Ryan. Or Spenser's Faerie Queene.
Innovation makes enemies of all those who prospered under the old regime... -- Machiavelli
Tests can be a form of documentation too. A proper suite of unit tests will show exactly what a method does.
This is silly. 1) Instead of reading reasonable comments, I'm supposed to dig out the module test and read the source code to see what that does, to tell me what a module does? 2) A test suite tells me nothing about how a method is used in the overall context of the program -- the whole point of comments. 3) Method comments are only one type of comment. I full expect methods within the code telling me exactly how it's doing what it's supposed to do.
Sometimes it's best to just let stupid people be stupid.
It's the same in pretty much every mainstream language out there. You've hit one nail in the head when you point out the lack of syntactic abstraction problem. There's a couple of additional lack of abstraction problems, though: you can't use functions as values, which is another way of abstracting looping logic, using higher order functions like map or filter; also, the language doesn't provide high-level flow control, like combinations or such.
I usually program in Scheme, and I suspect that the way I'd do whatever GP is doing is by using explicit continuation-passing style. The functions in question would take as an argument a function that does the thing that's supposed to happen when the condition fails: the "failure continunation." Then you do your looping using tail recursion:
Yeah, the word "continuation" sounds scary, but this is not using call-with-current-continuation or anything that complicated. All you're doing is using tail call optimization to implement the nested loops and the break with nothing other than conditionals and tail calls.
Are you adequate?
(define (outer-loop loop-state failure-continuation)
;; The failure-continuation argument is just a function that gets
;; called if the condition that breaks the loop is met.
;; The function inner-loop will call us back in tail position.
;; Since tail calls compile down to gotos, this will be the same
;; native code as any low-level loop.
(if (end-condition? loop-state)
loop-state
(inner-loop loop-state failure-continuation)))
(define (inner-loop loop-state failure-continuation)
(cond ((end-condition? loop-state)
;; If we come to the condition that ends the inner loop, we
;; tail-call the outer loop (our "success continuation")
(outer-loop loop-state failure-continuation))
((break-condition? loop-state)
;; If the break condition is met, we just call the failure
;; continuation, which "exits the loop." Since this is a
;; tail-call, again, this compiles down to a goto into the
;; code for failure-continuation
(failure-continuation loop-state))
(else
;; If neither condition is met, then we just use tail
;; recursion to loop.
(inner-loop (produce-next-state loop-state)))))
Are you adequate?
- it's easy to verify that they are correct (if the test suite runs, they are correct)
- they provide a wealth of examples of how to use a piece of code, likely moreso than any comment will
The things that you can't capture in code or tests is semantics. Who cares what the syntax of a function is, if I don't understand its purpose? Someone's inline comments aren't going to do that. It's going to be a combination ofIf you were using python, you could do something like:
while not wannabreak:
for j in range(0, jmax):
# inner loop
if wannabreak:
break
else:
# outer loop
But really, breaks are worse than a goto used in this context anyway.
A break is just a goto without an easy to find label, so the goto makes
it easier to read.
Who cares about identical errors, you're screwed either way then. The big problem is when the "documentation" and the "code" don't match ... you have no idea which one is wrong.
As the old saying goes: "The man who has a watch knows what time it is, the man who has two is never sure." ... of course the man who has one watch and a big pile of unit tests which prove it's keeping the right time is doing the best of all :).
I've been at this for a pretty long time now, and I've found very little use for "comments explaining what the code does" ... but a lot of use for "comments explaining why". And personally, I've gone back to code I've written over 5 years ago and could see what it was doing instantly ... and on the bad side I've read code I wrote a year or so ago and not understood why it was doing something (to be fair, after thinking about it a bit it became "obvious" ... but then I wrote a comment explaining it anyway :).
Yes, I've read others peoples code that (in theory) would have been easier to understand if it had been heavily commented ... but it would have been even easier to read if they'd just been any good at what they were doing and written the code well.
ustr: Managed string API with ave. 44% overhead over strdup(), for 0-20B
The real problem with comments (and tests unless you run continuous integration) is that they break easily ie. you can easily change the code without changing the comments.
You really need all 3 to have a decent system maintainable by a group:
1) Good neat code with well named identifiers
2) Comments
3) Tests
Yes that's 3 times the work and 3 times the maintenance. You get nothing for nothing.
So how can you minimize the work?
Good choice of granularity when commenting and testing.
For commenting always comment what isn't obvious from the well written code. You don't need a comment telling you that the method String getPersonsName() returns a string. The return type is staring you in the face. If the return type changes it's easy to accidentally miss the comment when modifying the code, particularly if you're making big changes. The method calculateTaxRate(...) shouldn't have a comment stating that you calculate the tax rate. It should explain the method used and refer to an external document if that explanation is too long. Asinine development standards would insist that we comment these. That's BS.
For tests, lets say you have a business layer and a data layer, and the business layer trivially calls the data layer. Do you really need a test at every layer? Perhaps a data layer test is enough if you're certain the business layer isn't likely to break. If it is, perhaps the business layer can do both. Half the code you have to write and maintain, but twice as much relying on that one test, so get it right.
These posts express my own personal views, not those of my employer
It's the same as initialising some counter before a while-loop: moving the loop without the initialiser breaks the code, so that's why you use a for-loop for those instead, which keeps things tidy.
True confidence comes not from realising you are as good as your peers, but that your peers are as bad as you are.
But you only need a goto because your programmig language can not break out of inner loop. See:
r ol#loop_with_condition_in_the_middle
http://en.wikibooks.org/wiki/Ada_Programming/Cont
As you can see in Ada loops have (optional) names and with that name the exit statement can break from any lool no matter how deeply nested they are.
But if I where to use a lesser language like C or C++ I would do it the very same way - just use a goto.
Martin
["Beautiful Code" features 33 different case studies about challenging coding scenarios from some of today's most high-profile developers and OS project leaders.]
OS as in Open Source or Operating System...
obviously the first, but still.. quite ambiguous.
I'm not surprised at all, some bits of my code are out there.
This site's primary concern seems to be java. Like the GOF, they seem to want to monopolize what is good and beautiful about it and most of all, how to do it. All fine and dandy if you're looking at ambitious eighteen year olds (ambitious to become faceless programmer droids, that is), but there seems to be an awful lack of discussion going on. Besides, currently my concern in _not_ java - so tell me again why this site would bother me ?
Religion is what happens when nature strikes and groupthink goes wrong.
Which is presumably why languages like Pascal, Java, Python, Ruby, etc. all support goto.
But how many of the above languages support...
goto is like assembly language: it's a flexible tool, but very primitive. Just as higher level languages are more expressive than assembly, meaning we rarely have reason to write raw assembly any more, so higher level languages have developed more expressive versions of goto, meaning we rarely have to write a raw goto any more.
I think someone needs to write a new article, called “Dogmatic structured programming considered harmful”. While block structure with the sequence, iteration and decision operations has proven a useful model for describing algorithms, other powerful abstractions for control and data flow exist. Functional programming tends to use recursion rather than iteration, for example, and many functional languages don't really model sequence in the classical sense either. Almost all modern, general purpose programming languages support the concept of exceptions, which are just a more systematic form of goto. In some programming languages, there is no explicit concept of control flow at all.
I don't see many people who understand these extended or alternative models complaining about how we should go back to doing everything with block-structured, procedural code. We just have to learn to use different models effectively, as functional programmers found before they realised the importance of tail recursion, as OO programmers found before they learned to control stack unwinding. This is called “progress”, and is what happens with experience... unless you adhere dogmatically to the way things are done at the moment, regardless of any objective merit an alternative may have.
If you disagree, post your argument. (-1, Overrated) isn't your personal censorship tool for views you don't like.
Heh. You're right, I did. As others have pointed, out a break is really the best.
;)
And we're initializing counters for while loops cause he wanted to use a for. You generally need a for when you want to run something n number of times. A while controlled by a counter does the same thing.
And as for whether I write avionics or life support software: hey, look, it's Slashdot, here. I wrote that post in under 30 seconds. What do you expect? But, as it were, I don't write such software...I just write stupid little applets in Python for doing things like controlling printers, but you could probably tell that from my link.
My blog
If you have short and myriad number of methods with no comments, it'll be fine as long as your company keeps you around, hire the elite 10% of developers that can read them or have programmers that only have the capacity to work with a small portion of the code base at a time. With many undocumented short methods, the way to understand code, is to procedurally spaghetti through lots and lots of methods and class files just to see how one thing gets done. Very often, adding some complexity in the local level can simplify the overall complexity at the global level (number of methods, inheritance levels and class files). If this approach combines with non-descriptive method names, reading code will be like reading the alphabet soup. Some code needs to be together and duplicated *gasp* when it makes sense, it is better for performance when it is fine tune-able for each implementation and not cause grief when people have to code around the shared utilities.
The most beautiful code in the world is that block of code that finally gets the shit to compile and build yes yes yes ohhhh thank you thank you god i can go home now wait hold it jesus fuck fucking wait what time is it the clock says its wednesday i thought it was tuesday fucking shit whatever oh shit oh shit shit shit oh shit i didn't call julie again shit shit shit shit shit well thats fucking great ive been here for the last 46 hours and now im finally able to go home to my pissed off wife who will ultimately deny me sex again and make me sleep on the goddamn couch like a goddamn dog. fucking beautiful.
One man's constant is another man's variable.
I think you're talking about what is commonly described as "self-documenting" or "self-commenting" code. You're absolutely right that well-designed and well-written code reduces the need for comments dramatically. If each element of your program has a single, clear responsibility, and the names and interfaces reflect those responsibilities, then yes, it's quite possible that you can write many functions with few or any comments needed.
However, the more experienced programmers who are disagreeing with you to an extent also have a point. While the "self-documenting" approach removes the need for comments that describe what is being done — the code itself documents that — someone coming along later to fix a bug, or finding their way around an unfamiliar large system, will rarely be able to determine why something is done as it is just from reading the implementation. This is the time when one good comment is worth a dozen class diagrams and flow charts.
You don't mention how experienced you are, so perhaps you've been here already, but if you've yet to read some of the classic general programming books like Code Complete, I highly recommend them. You'll find a lot of thought-provoking ideas in there if you're an interested but so far relatively inexperienced programmer.
If you disagree, post your argument. (-1, Overrated) isn't your personal censorship tool for views you don't like.
Fortunately, the programming community is just one big, happy family. In fact, in a recent survey, 99% of programmers agreed that 99% of programmers can't program for ****.
If you disagree, post your argument. (-1, Overrated) isn't your personal censorship tool for views you don't like.
Variables and functions can have names, and they should be meaningful. There are functions, classes, etc. to divide code into manageable parts. A part should do only one thing and do it well. Put parts with similar function in a group with a proper name. This is called self documenting code
Use comments to explain non-obvious solutions to a problem, for example if you had to work around a bug in an external library. Don't explain in a comment what is already concisely expressed in code.
Document interfaces. If you want other programmers to use your code, you should document the classes and functions they call. This will save them a lot of time and make your code more valuable, but it's a rather boring task. Not every project has such an interface.
Atari games contain very ugly code, but how many people can say they wrote code that sold over 100,000 units at a penny per byte?
I totally agree - the one example I always give when I meet a "self-documenting code" programmer is the case of implementing a standard.
/* Not allowing other formats, as per section 3.27.1.55.3 of the standard */ is all it takes.
You accept one form of floating point, but reject another - the code is crystal clear, but the customer wants to be able to write 3.8e+8 and you don't allow it. Another programmer goes into the code and quickly changes it to allow that 3.8e+8 format. Next thing a test fails (the test that makes sure that 3.8e+8 will not be accepted). The programmer thinks "ah, that's a bad test, it doesn't allow all possible floating points formats, probably someone was day-dreaming" and quickly changes the test not to fail.
So far, so good - the code was clear, the test was clear, but someone, somewhere will have a very big problem with the "numbers separated by the character 'e'" case as described in the standard.
A comment
It may sound like an advertisement, but db4o (www.db4o.com) is so simple that puts Hibernate to shame. All you have to do is ...save your objects in the database. Your objects is the schema. It's amazing. And it has no external config files!
A test doesn't replace documentation. Documentation describes what the code does. A test verifies that, in the case covered by the test, the code does, in fact, do what it is intended to do. But you can't infer the information in good documentation from an (undocumented) test suite, because while the test cases will specify behavior in specific conditions, you can't (generally) unambiguously infer what behavior is expected in other conditions, particularly when the task being tested is nontrivial. A test is always a specific case of an operationalization of a specification, even if no one has ever reduce the specification to writing. But it would be good if they did. Its true that good documentation isn't always worth the effort, but its equally true, I think, that it is almost always more worth the effort than it would seem intuitively at the time the code is written, so if the impression at the time of first developing the code is the guide to documentation, code always ends up underdocumented which tends to cause problems down the road.
Unlike mathematicians, physicists almost never distinguish between "f(x0) equals y" and "the limit of f(x) as x approaches x0 is y." (I am not saying that there are no cases where the distinction is made, e.g. degeneracies in QM.)
You'd be amazed at the hideous things physicists do with the Dirac delta function.
We all know what to do, but we don't know how to get re-elected once we have done it
I've tried writing code using OpenSSL's libraries recently, I tell you it's horrible.
.pod format I had to google for.
...
First off, their documentation on their site is permanently marked [STILL INCOMPLETE]; this meens the most I can do with their documentation is connect to some host using SSL/TLS, read/write, and close. I can't check any certificates or anything. I check their documentation that was download with the source code, and it's all in some foreign
So I gave up on that, and I thought looking at their code directly would be a good idea. No, it wasn't.
Check this one out:
static int do_cmd(LHASH *prog, int argc, char *argv[])
{
FUNCTION f,*fp;
int i,ret=1,tp,nl;
if ((argc <= 0) || (argv[0] == NULL))
{ ret=0; goto end; }
where the end label stipulates:
end:
return(ret);
}
Why have ret=0; goto end; at all? They have it on one line to begin with, they could make it one statement with return 0.
And no-where in this badly indented, spaghetti code is their useful comments/documentation (ok, now that I had a good look, I see there is a function or two that has a comment or two).
The whole problem with putting a return statement in the middle of a function is that when you do so, you actually have to read the code carefully to figure out what the control flow is. Try reading code in a language without return statements: you can figure out the control flow much faster, just from the syntax of the code you're reading. (Lisp variants are pretty good in this regard, as are most functional languages.)
Are you adequate?