Any "Pretty" Code Out There? 658
andhow writes "Practically any time I hear a large software system discussed I hear "X is a #%@!in mess," or "Y is unmanageable and really should be rewritten." Some of this I know is just fresh programmers seeing their first big hunk o' code and having the natural reaction. In other cases I've heard it from main developers, so I'll take their word for it. Over time, it paints a bleak picture, and I'd be really like to know of a counterexample. Getting to know a piece of software well enough to ascertain its quality takes a long time, so I submit to the experience of the readership: what projects have you worked on which you felt had admirable code, both high-level architecture and in-the-trenches implementation? In particular I am interested in large user applications using modern C++ libraries and techniques like exception handling and RAII."
Firefox (Score:4, Funny)
Re:Firefox (Score:4, Interesting)
I only wish firefox was 10% as elegant and cruft free as postfix.
Re:Firefox (Score:5, Funny)
And don't forget that postfix is well-commented, and with superb documentation. Re the comments about qmail, I've kept lying around in my mailbox Linus' thoughts about qmail. Couple of interesting points in there.
On Sun, 6 Jun 2004, Kalin KOZHUHAROV wrote:
Well, not exactly sure about my reply, but let me try.
The other day I was debugging some config problems with my qmail instalation and I ended up doing:
# strace -p 4563 -f -F
[...] (deleted to bypass lameness filter)
qmail is a piece of crap. The source code is completely unreadable, and it
seems to think that "getpid()" is a good source of random data. Don't ask
me why.
It literally does things like
random = now() + (getpid() (two less than signs deleted) 16);
and since there isn't a single comment in the whole source tree, it's
pointless to wonder why. (In case you wonder, "now()" just does a
"time(NULL)" call - whee.).
I don't understand why people bother with it. It's not like Dan Bernstein
is so charming that it makes up for the deficiencies of his programs.
But no, even despite the strange usage, this isn't a performance issue.
qmail will call "getpid()" a few tens of times per connection because of
the wonderful quality of randomness it provides, or something.
This is another gem you find when grepping for "getpid()" in qmail, and
apparently the source of most of them:
if (now() - when (less than sign deleted) ((60 + (getpid() & 31)) (two less than signs deleted) 6))
Don't you love it how timeouts etc seem to be based on random values that
are calculated off the lower 5 bits of the process ID? And don't you find
the above (totally uncommented) line just a thing of beauty and clarity?
Yeah.
Anyway, you did find something that used more than a handful of getpid()
calls, but no, it doesn't qualify as performance-critical, and even
despite it's peyote-induced (or hey, some people are just crazy on their
own) getpid() usage, it's not a reason to have a buggy glibc.
Linus
Comments lie. Code never lies. (Score:3, Insightful)
In all fairness, nobody has ever cashed in on Bernstein's security guarentee. There have been some oopsies with postfix.
I think Bernstein's code is as nice as it gets. Course, Dan is polite to me too; so maybe I live in an alternative universe.
Re:Comments lie. Code never lies. (Score:4, Informative)
I'll comment (inline) as someone who has come to appreciate certain of qmail's strengths even while tolerating (to varying degrees) its weaknesses:
qmail code is pretty ugly when looked at closely enough, and can seem unnecessarily "different" from a more-distant perspective.
However, pull back far enough and look at it, and you might be able to appreciate that it is, in its own way, a work of art: a reliable, secure, powerful email system — just as pretty much any sufficiently large and beautiful work of art can look pretty flawed when scrutinized closely, especially without an awareness of the "big picture".
So if I wanted to play around with an email server and make it do all sorts of slick stuff, I wouldn't pick qmail.
But if I wanted to improve a mail server in some fashion while still being reasonably assured the resulting (modified) system wouldn't have remotely exploitable bugs in it, based on what I know right now, I wouldn't pick anything but qmail.
Re: (Score:3, Interesting)
You know, you could just code the thing in Java and eliminate this issue outright, as well as all possibility of buffer overruns... C is the worst possible language for Internet-facing servers.
Re: (Score:3, Insightful)
Moreso, the "bugs" describes above can be "features" to somebody else. I appreciate the brevity of Dan's code; C++ LongVariableNames make me throw up a little in my mouth.
What's wrong with replacing the Standard C Library? Now you know what you're dealing with. Exactly.
If your C program exits and doesn't deallocate memoru your O/S is broken.
Given the number of sites that run djbdns and qmail and the number of CERT advisories against th
Re:Comments lie. Code never lies. (Score:4, Interesting)
As my page (to which you link) notes, these bugs are likely exploitable only in theory.
And I've been hired (and paid well) to modify qmail code, including patching it to fix bugs as well as extending it, for years now, but nobody has even inquired as to what it'd take to fix the "Guninski" bugs that might theoretically be exploitable — at least, not so far.
I think that's a pretty sure indication that the qmail user base does not consider those bugs to be sufficiently worrisome to fix. (I did publish a simple fix to one of the first bugs Guninski found; that fix was incorporated into netqmail. But I did that gratis.)
I don't know offhand whether DJB has ever acknowledged any bugs in qmail. But, just as code doesn't lie while comments can, code that is reasonably well-specified, as qmail's components' interfaces are, cannot pretend bugs don't exist in it, even if authors or fanboys do, just as it can't pretend it has bugs even when claimed otherwise[*]. So I don't particularly miss djb's opinions and pronouncements on such issues, since I can read the code and decide for myself.
[*] There's a web page out there that claims "qmail-smtpd does not detect CR LF properly on packet boundaries", which strikes me as complete and utter — as well as easily demonstrable, by simply looking at the code — nonsense. Not that it can't happen, but it'd almost certainly be due to an OS, networking, or (non-qmail) library bug. Tellingly, despite the high likelihood such a bug would result in huge numbers of legitimate emails being rejected by many qmail servers worldwide, there's no information on this alleged bug beyond somebody supposedly reporting it. That's only marginally more persuasive than saying "qmail-smtpd dropped every third email on every server running it on March 17, 2001, between 11:45 and 12:15 UTC, according to a guy I overheard in a bar the other day." Color me unimpressed.
Re: (Score:3, Interesting)
These exploits can be performed by any user who owns such hardware, and can read. They are not theoretical. Many bugs have existed in linux kernels that only manifest themselves un
Re: (Score:3, Informative)
Re:Firefox (Score:5, Funny)
There's an interesting story about the difference between a Berkeley trained engineer and a Stanford trained engineer. The Stanford engineers typically finish college, and are downright shocked when they enter Dilbert Land, and for a while are unable to perform well. Berkeley grads don't seem to notice the transition, and get right to work.
Re: (Score:3, Interesting)
... /. this question has spent more time reading about writing code than he/she has spent actually writing code.
On another note, I'm willing to bet that the person asking
Why do you say that? And is that a bad thing?
I probably spend an equal chunk of time looking at code as I do writing it (then again, being an intern consultant/admin I'm always looking for a reason to write code and can never justify scratching an itch someone else, who is smarter than I, has already scratched sufficiently), I think I once spent a good chunk of time, that I should have been studying for my data structures final, reading the 2.6 kernel - and I probably take a peak at samba on every 2 w
Re: (Score:3, Insightful)
Re: (Score:3, Insightful)
And spending more time reading code can go a long way into impressing on somebody the importance of writing it clearly in a manner that makes it maintainable and easily understood.
So many programmers in the world need to have their keyboards substituted for a pair of reading glasses so they can learn some basic competence.
Re: (Score:3, Interesting)
PIDs are not random for any reasonable value of random. For low-grade random numbers use something like
Re:Firefox (Score:5, Informative)
Don't ever hard-code /dev/* into your program unless it's one of the devices specified by POSIX [opengroup.org]. Last time I checked, this limited it to /dev/null, /dev/console and /dev/tty.
Deadbeef Random Number Generator (Score:3, Interesting)
in the distance... (Score:3, Funny)
sure (Score:5, Funny)
Re: (Score:3, Funny)
Re:sure (Score:4, Funny)
Hello World (Score:5, Funny)
public void sendMessage();
}
public abstract class AbstractStrategyFactory {
public abstract MessageStrategy createStrategy(MessageBody mb);
}
public class MessageBody {
Object payload;
public Object getPayload() { return payload; }
public void configure(Object obj) { payload = obj; }
public void send(MessageStrategy ms) {
ms.sendMessage();
}
}
public class DefaultFactory extends AbstractStrategyFactory {
private DefaultFactory() {}
static DefaultFactory instance;
public static AbstractStrategyFactory getInstance() {
if (null==instance) instance = new DefaultFactory();
return instance;
}
public MessageStrategy createStrategy(final MessageBody mb) {
return new MessageStrategy() {
MessageBody body = mb;
public void sendMessage() {
Object obj = body.getPayload();
System.out.println(obj.toString());
}
};
}
}
public class HelloWorld {
public static void main(String[] args) {
MessageBody mb = new MessageBody();
mb.configure("Hello World!");
AbstractStrategyFactory asf = DefaultFactory.getInstance();
MessageStrategy strategy = asf.createStrategy(mb);
mb.send(strategy);
}
}
license (Score:5, Funny)
Hello World
Copyright 2002 MillionthMonkey
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 [apache.org]
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
You're welcome, "World"!
Re: (Score:2)
Re:Hello World (Score:5, Funny)
Re:Hello World (Score:5, Funny)
It is the Gang-of-four Job_Security_Strategy pattern. Only the author can figure out their own code like this, and if you get paid per volume of code, you get wealthy.
Re:Hello World (Score:5, Informative)
Ha ha, joke's on you, you dick- that "old joke" was written by me five years ago [slashdot.org] as part of a larger post and I was not at work- in fact it was way after hours and I was about to go home. I just started with the base concrete implementation and this is what it looked like after a few minutes of stuffing patterns into it- Singleton, Factory, and Strategy. I keep thinking one of these days I'll release a 2.0 version with Proxy and Bridge. Since I was the original author I retain the right to paste it wherever I want and to attach any license agreement I feel like attaching.
This has become the most famous code I've ever written which is the sort of thing that makes you reflect on your career. So far it has netted me about 20-30 karma points over the years (lord knows how much karma was gotten from pirated copies). I found it being examined in some software engineering papers and it even made its way into one of the patterns books [powells.com] (as an example of "Patterns Happy" code). When I found out about that, I made the guy send me a free copy and acknowledge me in print so I can maybe net some jobs unnecessarily screwing up simple code with GoF patterns which always pays well. Now that I released it under the terms of the Apache license he might come back for his book.
Re: (Score:3, Funny)
Re:Hello World (Score:4, Funny)
You're officially my hero.
Re: (Score:3, Funny)
And when that's working, I'd suggest adding to its power and flexibility by making it possible to pass a login id or possibly an email address to the code, and have it look up th
Re:Hello World (Score:5, Funny)
public class Hello_World {
public static void main(String
System.out.println(Hello_World.class.getSimpleNam
}
}
Hello World (Newer Version) (Score:5, Funny)
Here is a little teaser though
Re:Hello World (Newer Version) (Score:4, Interesting)
If I wrote this code in 2007 I would have used "setPayload()" instead of "configure()" so that MessageBody would follow standard JavaBean conventions. That would let me easily wire one up in a Spring XML file. Maybe I could even insert AOP pointcuts somewhere. After all Hello World is the sort of application that practically screams for aspect oriented programming.
Re:Hello World (Newer Version) (Score:5, Interesting)
Re: (Score:3, Informative)
New Law? (Score:5, Insightful)
Has someone created such a law before?
Re:New Law? (Score:5, Interesting)
I think you meant the cruftiness of source code is direcly proportional to the number of people working on it DIVIDED BY the amount of time spent working on it.
This explains why commercial source code produced by large teams of programmers under tight arbitrary deadlines tends to be sloppy. Source code produced by passionate hobbyists under the "we'll release it when it's done" deadline perspective tends to be cleaner.
Re:New Law? (Score:5, Funny)
Cruft is never present on code which hasn't had enough work. Cruft only appears on code which has been worked too long, by too many people.
Re: (Score:3, Interesting)
Re:New Law? (Score:5, Insightful)
Let's cue the scene...
An application's code is written by a competent developer and is nice and clean and pretty. He releases the application, and its a success. He gets moved to the next high profile project, and then the application's code gets handed to the maintenance droid, you know, the new guy on the team who shops *exclusively* at Whole Foods, listens to Nickelback, and has stacks of People magazine in his cubicle. He took a semester of VB while at Party U pursuing a liberal arts degree, and so he is a programmer too, you know!
Then, some PM or business manager who probably gets paid more than the original competent developer gets some bright ideas to make the application do things it never was intended to do. Let's say its a scheduling tool. Well, hey, they say, let's make it ALSO have an RSS feed! And a document repository! And a calculator! Can can you create some little project management software to work with it? A requirements document gets written, and a timeline is assigned.
Everyone does their little piece, totally oblivious to the steaming pile of dung spaghetti they are turning the application's code into.
Two years later, the original developer gets called to fix a problem that is simply beyond the dimwits holding the code. Poor guy doesn't even recognize his own application, and for him, it's like getting called to the morgue to ID the remains of a family member.
And that, friends, is why people complain about bad code.
Does this post make me sound cynical?
Amarok? (Score:3, Informative)
Also the Last.fm player seems fairly well done, though for both these programs I didn't look through the full code or change anything, so maybe I just happened to stumble across the only 2-3 human-readable source files?
Re: (Score:2, Interesting)
Next up on slashdot... (Score:2, Insightful)
Trends and tastes change. If any coder is 100% happy with a project, they're in the wrong field.
Re:Next up on slashdot... (Score:5, Insightful)
I couldn't agree more. As I grow older, I've learned there really is a time when something is "good enough" to satisfy known requirements. I find that many applications are over engineered to some pie in the sky version of what's right and good - usually at the expense of simplicity and stability. I've often heard Java folks talk about re-factoring code and that's fine if no one is using your app, but in the event that folks and money are dependent on it, then re-factoring really just increases risk to all involved. The best possible outcome is that no one will notice the changes.
It's definitely hard for more passionate developers to realize when time to value ratio has diminished to the point that your time is better spent on other projects. There's always one more thing to spruce up or optimize. Having been both a musician and developer, I like to think of my work as a reflection of me. Playing an instrument is similar in that there is always more to learn and practice on any given song, but sometimes you need to put it down and move along to other pieces. Even the best musicians play a variety of songs. I'm sure Eddie Van Halen could have perfected Eruption for the next 20 years after he recorded it, but he decided to spend his time on other works.
Maturity = Mess (Score:2, Insightful)
And on a related note - why rewrite? Can't people ever just go for cleaning something up? No cause then you are just doing mindless reformatting - while if you rewrite, you can claim you make it
Re:Maturity = Mess (Score:5, Insightful)
Now, I *have* rewritten a lot of the code on the project, but not because it was "ugly". We had quite a lot of "prototype" code still in the project. Since it was prototype code, it didn't check for or handle error conditions very well (not to mention the endless bugs that have been found due to the prototype code). We've had to rewrite a lot of the code because it was easier to do that than fix the bugs in the code. This usually allows for easier debugging in the future AND gets rid of any of the bugs that were found (the bugs were usually caused by a bad or even completely wrong approach to the implementation).
The difference is knowing when to clean up the code and when to rewrite it. If a developer just can't understand the code (because it needs cleanup or it's just very complicated), then it should be cleaned up and commented properly. Sure it's tedious, but everyone on the project loves you afterwards because they can suddenly understand the code! If there are bugs and it's obvious the implementation should have been done a different way (for speed, usability, modularity, whatever), then a rewrite might be in order.
(and of course, as you mention, as time goes on the code starts looking "bad" or "old" again - time for hopefully another cleanup rather than a rewrite)
Smell (Score:5, Funny)
A friend of mine used to say: "Source code is like shit, it stinks when it's not yours."
what? (Score:5, Funny)
I get that with reading the next line you get the context, but was I the only one taken aback at this seemingly blatant flame of our beloved X?
BOOST (Score:4, Informative)
Are you kidding? (Score:5, Insightful)
(1) It's impossible to debug. You can't read the code. The debugger can't unravel the templated variables and stuff in any meaningful way for you. You can't even step through code, that's doing a supposedly simple operation like memory allocation!
(2) Some compilers will choke on the code, or compile it wrong in subtle ways due to differing interpretations of some obscure section of the enormous C++ language spec.
(3) The error messages from the compiler are useless. You have to run them through a filter to even figure out what they mean.
(3) Bugs in the library are very difficult to fix. Template metaprograms are essentially programs written in a functional language, except one that has horrible syntax. This is not the stuff that normal C++ programs are made of.
Your mileage may vary. My day job is working on a game engine for an upcoming Xbox360 game. Engines are hard enough without impractical crap like template metaprogramming in them. Give me straight-line C/C++ code any day.
Re:Are you kidding? (Score:5, Insightful)
Even beyond that, Boost fills up the symbol table quick as hell, because of how templated it is. I worked on a project that used LuaBind, which requires Boost, extesnively. We eventually had to swap over from Visual Studio 2003 to 2005, because of Boost's templating filling up the symbol table. Visual Studio would just fail to compile. Lua's hard enough to debug as it is, but tossing Boost on top of it made it impossible.
filling up the symbol table (Score:3, Informative)
For those with a Linux/BSD/Solaris system, try running the "nm" command against a solidly Boost-infected project. You're likely to find function names that are THOUSANDS of characters long.
Think about what that means for program start-up, at least if you call into a library. The runtime linker has to chew through all that gunk. I've run a profiler on this kind of code, and sure enough the start-up time was dominated by looking up all those giant symbols.
Re: (Score:3, Informative)
I have not seen anything that template metaprogramming can do that can't be done using other "saner" (in my opinion) techniques. Perhaps the template metaprogramming approach can at times produce *terser* solutions, but I don't think that they are any better than more verbose non-template-metaprogramming-based solutions.
T
Re: (Score:3, Insightful)
1. The GP sounds like he understands template metaprogramming very well. Nothing about his post suggests that he either a) says that he is an "expert" (as you are suggesting he does), or b) *isn't* enough of an expert to have formed a valid opinion on the subject.
2. Clearly the GP used the word "impossible" to mean "very difficult". You're being pedantic by sugge
BOOST::Python, but you haven't seen the source??? (Score:5, Interesting)
I haven't looked either, but I happen to know that BOOT::Python often does NOT work. It has thread-related problems.
At for the rest of BOOST, I've looked at a good chunk. BOOST makes decent programmers cry. The other follow-up post by the Anonymous Coward Xbox developer has it all correct.
I'll add:
BOOST is full of butt-ugly hacks. Check out the, uh, template things, named _0 through _9 being used as stand-in dummy arguments. Eeeeeew!!!
BOOST looks easy to dumb-ass programmers, but these programmers leave bugs that are difficult for expert programmers to find.
BOOST makes compilers run very very slow, and often breaks the optimizer anyway.
Understanding != Writing Code (Score:4, Interesting)
Re: (Score:3, Insightful)
If you can't understand the code it's the author's fault. That is if you have mastered the syntax of the language of course.
I'm currently working with an embedded code base that was written for job security. Everything is somewhat elegantly organized, but nothing is commented and functions are usually 200 - 500 ELOC. There aren't any notes explaining module interactions w
Code prettyness only at module level (Score:2, Interesting)
Most projects have nice clean stable blocks which to look at you just know its right.
Other parts resemble a jungle and have no logical flow and are horrid.
Whenever I am building an algorithm, it goes through the numerous rebuilds, after initially getting it working each one has more and more order until it looks like it will win a race.
If the boss comes in and sees working code though, they don't understand this pre
Inconsistency (Score:5, Insightful)
Worse is when you don't even define a coding convention for the code you throw into the mix. Now you have libraries with inconsistent naming, and multiple developers all using their own favorite notation.
Additionally, their is inconsistency in the functioning of libraries. Some use function pointers, some work by inheritance, some (like glade) read the export list..
I'm not a huge Java fan, but I think they have maintainability down pat. Very consistent language, well defined coding convention, and a mature set of defacto tools (JUnit, javadoc, log4j, struts, spring, hibernate, etc..) make it a lot easier to jump into older code because everything feels familiar. In most other languages you have to spend quite a bit of time just decrypting the existing code, and then more time learning the particular API's they've chosen.
Re: (Score:2)
dicomlib (Score:2)
anything in BASIC (Score:5, Funny)
good source (Score:5, Interesting)
Re: (Score:3, Insightful)
NetBSD has got quite a good reputation. (Score:2)
Such a good reputation, in fact, that an entire book has been devoted to reading its source code [spinellis.gr]. It has a reputation for correctness and portability (duh) and seems an interesting starting point.
Since I am only getting started in C programming, though, I can't recommend this book. Or the NetBSD source, either.
libjpeg (Score:2, Interesting)
TeX (Score:4, Interesting)
Re: (Score:3, Interesting)
Yes, I understand that. I just think it is somewhat ironic that the implementation of TeX is much prettier than the language itself.
The linux kernel (Score:3, Informative)
damn good (Score:3, Informative)
There are useful well-written abstractions, without the typical obfuscating layers of abstraction fluff.
The code is written to run fast, while still being portable and readable.
Static checking is all over, but not in-your-face annoying. Some of it involves compile-time assertions. Some of it involves a lint-like tool called "sparse" which makes sure that people
Disgust (Score:3)
python (Score:4, Insightful)
the imposed indentation and clear language characteristics.
Amazing (Score:5, Funny)
I see those all the time as comments in my own code.
postfix (Score:3, Insightful)
There are different types of messes (Score:3, Interesting)
My current large project is LedgerSMB. This deals with an entirely different magnitude of mess. Essentially we forked from a codebase which we have come to understand is nearly unmaintailable and yet we *have* to replace all the code because we have lots of users on the software who rely on it. Hence we are refactoring with an axe.
The older codebase (SQL-Ledger/LedgerSMB 1.0/LedgerSMB 1.2) has a number of architectural limitations and issues, as well as a lot of evidence of an overall lack of architecture. If that weren't enough, the code is pretty problematic too. It could be worse (at least the codebase is reasonably readible if you put enough effort into it).
I think it hits about 75% of the software programming antipatterns mentioned on Wikipedia, and extends some of them in weird ways. For example instead of just magic strings, we have magic comments (comments which are actually part of the program code and which deletion causes problems). And we have function calls which pass by "reference-to-deferenced-reference." In perl terms \%$ref.
Hence we are moving everything to a new and *cleaner* architecture.
OpenSolaris (Score:5, Informative)
As large and old as it is, OpenSolaris [opensolaris.org] has fairly readable code. Plus, most of it has comments explaining why it's done the way it is.
Any app that doesn't need to be rewritten... (Score:3, Insightful)
A experiment (Score:5, Interesting)
Then I demonstrated that a bunch of code checked into our system looked like it had *already* been run through this tool. After the public shaming, a couple of the offenders cleaned up their acts for a while, but they're back to their old tricks.
These days I'm working on a project where all the devs are really, really serious about the formatting and naming conventions. Some of the rules suck, in my opinion, but there's a lot to be said for consistency.
[In the 80s, HyperCard team at Apple used to regularly run their sources through a Pascal formatter. The code, in a friend's words, "looked ironed." Unfortunately I haven't run across any good C++ formatters.]
Pretty code can be found here (Score:5, Insightful)
They made printer software that went into virtually every printer not made by HP at the time. Canon, Ricoh, Lexmark, or whoever would come out with new hardware and license the software from Phoenix. Yep, some of my code is in every Lexmark printer right now.
They had a couple hundred thousand lines of code that did PCL, GL, and Postscript for the consumer market, and it was the most readable and well developed code I have seen. Comments were explanatory, variables were well named, and execution paths were well defined and easy to follow.
They really had their act together for testing as well, with an elaborate and comprehensive regression suite that checked *every* aspect of all of the [printer] languages, and a team of QA people who would go over the results nightly. I'm not making this up - you would come in to work in the morning and there would be maybe 5 E-mails from QA outlining bugs which were either in your code or assigned to you for reasonable reasons.
We did the software for the first Lexmark printer. The first internal release gathered 900 bug reports from QA. When we went to market there were 7 remaining, all of which were deemed inconsequential.
When you are in the commercial market making fixed-program computers (dishwashers, printers, cell phones, VCRs) you don't have security updates and new versions, and a recall is usually out of the question. It's much cheaper to do all of your QA up front and ship a quality product.
In my opinion we've grown sloppy in the programming business. I've been a contractor for the past 30 years and I haven't seen anyone else who comes close to true quality procedures. Even FAA safety certified stuff is usually hokey and obscure. Thank god we've still got human pilots.
Having seen the procedures firsthand I have an appreciation of how easy and valuable it all is. No one else seems to understand that, and so everyone keeps running around putting out fires and slipping deadlines.
Bourne Shell (Score:5, Interesting)
The Bourne Shell [tuhs.org] must get some kind of mention here. What do you do if you prefer ALGOL to C? Why, #define your own syntax [tuhs.org], and thus turn boring old C code into a thing of beauty [tuhs.org].
Why Old Code isn't pretty (Score:3, Interesting)
Many pieces of old code aren't pretty for a fairly defined set of reasons:
1. a) Debugging Ensure you actually have an appropriate way of debugging the code. The systems I work with are embedded and run 7x24. People will say: it failed last week on Wednesday at 3:00 A.M., we got it working, but can you fix the problem? The problem may not actually be your code, it could be another piece of equipment. In any case, you need to figure this out from the logs. In my experience, many "pretty" programs are too small to justify extensive logging. After logging is included, the programs become less "pretty" but much more maintainable.
1. b) Refactoring after Debug Sometimes the results of the debug will show a major design error in the program. You now need to implement a major architectural change that really was not originally intended. You have good modular code when it can withstand these major design changes in a relatively smooth manner.
2. Failure to handle common areas of problems well These include:
2. a) Strings Does your program have the ability to smoothly handle unicode/UTF/HTML/locale specific strings? Every different language you port your application too, and every different program you talk with, will all have differing definitions of what is a string. My favorite test case is CNC (Computer Numerically Controlled) machinery. Some CNC machines expect embedded nulls inside the strings. The embedded null requirement affects a surprisingly large number of string libraries.
2. b) MessageBox() Invariably in a big program it will be unacceptable to allow it to hang on a modal dialog box like MessageBox(). How are you going to handle it? What if a library call executes a modal dialog box?
2. c) Handling Exceptions For a simple prototype program, handling exceptions is not a big deal. In a production application, all the exceptions must be handled appropriately and the program must be able to continue when exceptions occur. The error handling code often exceeds the size of the original program.
2. d) Third Party Libraries / Operating Systems (Windows) The amount of code devoted to covering up mistakes in other code is amazing. Unfortunately, unless coding on an open platform, one must accept the costs of the additional code. When starting a new project, I recommend thoroughly stress testing any new libraries that will be used. Thus one can find the killer bugs that significantly affect design decisions.
I would appreciate any feedback/additions to the items on this list.
Re: (Score:3, Interesting)
3) Failure to define the problem space/ failure to refactor
If you are using the agile programming approach in a haphazard way, or even if you are using a waterfall in a rapidly changing, unpredictable area of problems. You design your code to do what it needs to do in the most efficient way possible to do what needs to be done now, without worrying about what might happen in six months.
Sometimes six months later the basic assumptions you made
Donald Knuth once apparently said (Score:5, Interesting)
The MacPaint code was donated... (Score:5, Interesting)
It's just occurred to me you are Tim O'Reilly. Wow, there are still some important folks that still post on
Re: (Score:3, Informative)
And to apologize for that lame joke, here's some research:
The Computer History Museum has transcripts and interviews, but no source: http://search.computerhistory.org/search?q=macpain t&submit.x=0&submit.y=0&site=chm_collection&client =chm_collection&proxystylesheet=chm_collection&out put=xml_no_dtd [computerhistory.org]
Another interview with the original reference to putting MacPaint in there: http://www.pbs.org/cringel [pbs.org]
...and Knuth should know (Score:4, Insightful)
[1] mention also to Kernighan & Plauger's Software Tools.
We just published a book called Beautiful Code. (Score:5, Interesting)
Andy Oram, the editor, thought it would be poor form to make a post himself, but heck, I thought: this is very relevant. The table of contents for the book can be found at http://www.oreilly.com/catalog/9780596510046/toc.
It includes essays by Brian Kernighan, Jon Bentley, Tim Bray, Yukohiro Matsumoto, Simon Peyton-Jones, and many others. The code is intended not only to be beautiful but also instructive and in many cases re-usable.
We're hoping to build an ongoing site around the book so additional examples would be very welcome.
A chapter in "Beautiful Code" is on this topic... (Score:3, Informative)
pretty driver code... (Score:4, Informative)
The Modify I/O Address command does not cause a Command Complete Interrupt.
*/
if (OperationCode == BusLogic_ModifyIOAddress)
{
StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
if (StatusRegister.Bits.CommandInvalid)
{
BusLogic_CommandFailureReason = "Modify I/O Address Invalid";
Result = -1;
goto Done;
}
if (BusLogic_GlobalOptions.TraceConfiguration)
BusLogic_Notice("BusLogic_Command(%02X) Status = %02X: "
"(Modify I/O Address)\n", HostAdapter,
OperationCode, StatusRegister.All);
Result = 0;
goto Done;
}
Select an appropriate timeout value for awaiting command completion.
*/
switch (OperationCode)
{
case BusLogic_InquireInstalledDevicesID0to7:
case BusLogic_InquireInstalledDevicesID8to15:
case BusLogic_InquireTargetDevices:
TimeoutCounter = 60*10000;
break;
default:
TimeoutCounter = 10000;
break;
}
This is some seriously low-level stuff, and it reads like English text. It totally changed my ideas about what this kind of code should look like! It believe it was written by the late Leonard Zubkoff.
Young Programmers... (Score:4, Insightful)
Almost always without taking the time to understand what that old code does. Why? Because writing code is much easier than reading code. Reading code takes perseverance and ability to focus on large numbers of nit-picky details. Something our TV-age brains cannot easily do.
The result of throwing out the old code without understanding what it is accomplishing is not always positive from a business perspective.
Sure, sometimes crufty code is crap.
But sometimes, like on a terminal emulator project I worked on in the mid-90's, the cruft was a bunch of code, accumulated from 1985 to 1995, that actually emulated the bugs in the firmware of 10 different manufacturer's dumb terminals. The programmers who wrote the applications that ran on these dumb terminals relied upon these bugs in the firmware and when the bugs disappeared, the applications broke.
The company that tried to sell the "correct", "new", "elegant" terminal emulator hit a big solid brick wall called "market acceptance." The company that kept the cruft made roughly $4 million per year in profits and supported 25 employees' and their families for a decade while they developed new products.
So, before you look at code in a shipping product and say to yourself "this is crufty crap and should be re-written from scratch" ask yourself this question: "Do I really understand what this crufty crap is doing?"
Buy a book (Norvig, PAIP) (Score:3, Interesting)
It talks about AI because it was the 80s (92 by the time it hit shelves) and AI was cool---but the applications involved are now just what we call computing. It's not perfect: fifteen years have passed since it was written. In that time, C++'s STL and Boost have caught up with many features of Common Lisp. Java's come along and done well. Other interactive dynamic languages than Lisp exist: Python, for example. So you'll have to do some translating in your head---but for the same reason that Cicero is read by students of English rhetoric, Norvig should be read by C++ and Java programmers seeking mastery.
The Tandy CoCo (Score:5, Insightful)
I remember when that cute little home computer came out, and all the programs were just so. . , plinky.
Memory was a huge barrier, because you only had a small quantity of the stuff, and nobody understood the architecture of the system well enough to produce efficient programs.
But back then, there were no video card upgrades. No faster processors and mother boards being produces every three months. If you wanted higher speed and cooler graphics, you had to write your code in more ingenious ways.
And so that's what happened.
By the twilight years of the Color Computer, the games people were writing on that thing were unreal. I remember looking at a few and thinking to myself, "This is the same computer? Wow! Humans rock!"
When you reach the raw power limitations of your muscles but you still want to improve yourself in your combat skills, you take up Kung Fu. That's how it was in the old home computer days. Nowadays, though, (dang kids; I hadda walk fifty miles to school!) it seems that the bulk of improvement comes with the purchasing of increasingly large muscles.
This is not to say that there is no software innovation. Heck, id Software did some pretty amazing things with software ingenuity. But I do remember thinking during the first few years of the big PC revolution, after the 486 was reaching its twilight, "You know, all this hardware innovation is great and all. . , (big muscles are cool), but part of me wishes it would stop cold for six solid years just what would happen when the programmers were really pushed. --You know, to see what one of these machines is actually capable of doing.
-FL
Golden Code (Score:3, Informative)
The other problem with easy access to Golden Code is that it must be constantly maintained to remain... "golden." So even if someone were to post a great example online, they're probably not getting paid to do so, so it's probably going to lose its luster in a couple years. Companies who maintain Golden Code usually assign a particular product to be coded in a "golden" way and continuously maintained in that perfect state as an example to all. This requires a lot of money.
So the point is, if you want access to Golden Code, get hired at a big software company. There are a fair number of them out there if you look outside the most obvious markets. Enjoy.
OpenVPN, glib (Score:3, Informative)
Gled (Score:3, Interesting)
It certainly is not pretty the first time you look at it, that is probably true for any unique project, but if you look harder, you will see a strange tangle using ROOT, CINT the C++ interpreter, built-in C++ object dictionaries, elegant and fast network stack for object streaming and synchronization, and strangely effective remote procedure call interface. But my favourite is the auto-building FLTK gui.
While remotely involved, I do enjoy this code immensely.
Try building a new library for it and enjoy GUI-enabled objects in minutes... (There is even a scratch for a TA-like game in one of the demos, not yet playable.)
Re: (Score:2)
Re: (Score:2)
Re:im hesitant.. (Score:5, Insightful)
My take on C++ is that the best programs only use a fraction of the features. The language is so big it is dangerous. Just because a feature exists in the language, does not mean it is good for every application. I am very wary of operator overloading and templates too. You need to make your code sufficiently clear that you can be sure it works. if you cannot quickly understand your code, then chances are you made a mistake.
Re: (Score:3, Interesting)
And I think you're dead right. C++ is a hideously complex bitch of a language. Anyone trying to use all the C++ features will quickly drive themselves insane. I rarely use inheritance, I rarely make my
Re: (Score:3, Interesting)
While I don't write my own templates, I do use them extensively in the STL, and I'd really miss the typesafety of having them. It looks like Objective C is not nearly as obsessive about typesafety as I am.