Beautiful Code Interview 286
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."
Nothing to see here (Score:5, Funny)
Re:Nothing to see here (Score:5, Funny)
Re: (Score:3, Funny)
If we built our cars like we build our software, they would look great, they would have controls even a five-year-old could use, and every 65,536 miles they'd teleport you back to where you started.
Re:Nothing to see here (Score:5, Funny)
Re: (Score:2)
This just reminds me of my friend. (Score:5, Funny)
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"
Re: (Score:2, Funny)
Re:This just reminds me of my friend. (Score:5, Funny)
He should have removed one syllable from the last line; then he would have gotten "+1 haiku!"
Re: (Score:3, Interesting)
Re: (Score:3, Interesting)
the person just
gave
up
and decided to
B R EA K!
the lines arbitrarily.
Oh how dramatic. Likewise, you can't say
My car had a flat
tire, so I called around for
quotes for some new tires
and call it haiku. Well I suppose you could, but it's awful. Here's one I just found that I like:
* I kill an ant
* and realize my three children
Re: (Score:2)
On the other hand, our first year Java lecturer insisted that K&R was the One and Only Correct Brace Placement Style and marked us down if we used ANSI C++ style brace placement instead of K&R. 'Tard.
Re: (Score:3, Insightful)
The OpenBSD code is studly. (Score:3, Informative)
Re: (Score:3, Informative)
Now, there's some bit of wiggle room for OpenBSD, since NULL can be either:
or
(or something equivalent, like 0L, etc).
Anyway, I presume OpenBSD uses the first definition, because otherwise a diagnostic is required when void* is assigned to a char. If NULL is defined as 0, an unfortunate coincidence allows it to b
Re: (Score:2)
True. AFAIK this code is not meant to be portable to other libraries or operating systems which is why it is in the OpenBSD CVS (they maintain the code in their CVS repositories.)
Re:The OpenBSD code is studly. (Score:5, Funny)
People hate my gotos (Score:2, Insightful)
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:
Re: (Score:2)
Re: (Score:2)
0x05 dollars says that "break (loop-label)" and "goto (post-loop-label)" compile to almost identical opcodes.
Re: (Score:3, Interesting)
Goto has been a feature of almost every programming language for a reason. It is useful. If it weren't useful then nobody would ever use it and then we c
Re: (Score:3, Informative)
BTW, I met a guy whose biggest dissapointment with VB.Net was that they did away with GOSUB. I shot him.
Re:People hate my gotos (Score:4, Insightful)
Break's and goto's are very different, and I am surprised to see so many people say that they are essentially the same. When I am reading code and I see a break statement, I know where the flow goes. When I see a goto statement, I have no idea where the flow goes unless the label is withing a few lines. That is the difference.
Re: (Score:3, Interesting)
Sure because it's really difficult to see where 'goto end_loop_foo' goes..
There are three common idioms where goto are useful: breaking nested loops, going to a return error section at the end of a function or to code a state machine, in the first two case that's perfectly valid to use goto and labelled break or exception doesn't bring much, but it's true that
Re: (Score:3, Insightful)
Indeed. As does "for", "while", "repeat" or whatever else your HLL gives you.
Re: (Score:2)
Re: (Score:2, Insightful)
bool continue_loop = true;
for (loop1 && continue_loop) {
for (loop2) {
if (termination condition == true) {
continue_loop = false;
break;
}
do_inner_loop_work();
}
Beware the raptors ... (Score:5, Funny)
That is all.
People hate my returns. (Score:2)
for (loop 1)
{ for (loop 2)
{ if (some condition)
{ return;
}
do work;
}
}
Re: (Score:2)
Re: (Score:2)
You may think that things like break + a boolean flag might
Re: (Score:2)
Seriously though, IMHO gotos should be used just like that -- to handle function-local exception conditions. Gotos should be avoided when they make code hard to follow, but why avoid them when they make the code easier to read? On the other hand, "open classes" as Ruby calls them -- *cough*COMEFROM*cough* -- they are pure evil.
Re: (Score:2)
Re: (Score:2, Interesting)
i=0;
while (not condition that makes me want to bail) {
j=0;
while (not condition that makes want to bail) {
inner loop
}
outer loop
Re:People hate my gotos (Score:4, Insightful)
Re:People hate my gotos (Score:5, Interesting)
If goto were not useful or necessary then languages would have dropped it years ago when CS profs started to dread it because they couldn't teach their students properly and got tired of spitting out idiot programmer after idiot programmer who tortured them with goto-ridden spaghetti code.
Telling people to NEVER use goto is like saying "never use a chainsaw because if you attempt to cut down a weed you'll just end up with a big mess". So what, we use a hand saw to cut down an oak tree ? There are far more elegant solutions for a lot of things that can be accomplished with goto. Conversely, there are occasions where goto makes for a more elegant solution.
At the very least, as you put it "beauty is in the eye of the beholder". Using your own philosphy I opt for giving programmers all of the necessary tools that they may find useful, and deciding for themselves which ones to use. After all, there are some programmers out there who could write code that is 100 x more efficient and elegant using ONLY gotos in C with main as the only function than I ever could using goto-free, well designed and thought-out object oriented Java, for example.
No matter what you do, the end result will always be the same anyway. Exceptional programmers will continue to produce exceptional code and pasta chefs will continue to produce spaghetti.
Re: (Score:2)
Any crap programmer can write spaghetti code with or without the use of 'goto'.
translates to:
"I can write bad code in any language!"
... which is one of my fav. responses to language wars.
Re: (Score:2)
However just because there are programmer who can use it well, doesn't mean that they will, or that there aren't plenty more who can't use it to save their life. It takes expertise, and it's still usually harder to code that does things by jumping around.
To use your own analogy if you were teaching people to cut weeds, you'd never start with the damn chainsaw. You'd teach them to cut weeds and when they were proficient progress them to bringing down trees wit
We all use goto, we just call it something else (Score:4, Interesting)
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.
Re: (Score:2)
Re: (Score:3, Informative)
for (i = 0; not bail_condition; i++) {
for (j = 0; not bail_condition; j++) {
inner loop
}
outer loop
}
Re: (Score:2)
Re: (Score:2)
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.
I don't think so. A break is clearly defined, there's no ambiguity over where control will go, while goto requires a separate dangling label that can become misplaced, deleted, etc.
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.
Re: (Score:3, Insightful)
Re: (Score:2)
Only if you raise structured programming to the status of a religion.
Gotos tend to cause problems by tying code into incomprehensible (and thus undebuggable) knots. The main battle in programming is to limit the scope you must think about simultaneously to the cardinality of your short-term memory. Gotos tend to suck in side-effects from all over the place and create a mental overflow.
Limiting yourself to concatenation, alt
Re: (Score:2)
Computers do just fine with spaghetti code. it's the humans that don't. Structured programming is one way to make it easier for people to write and understand programs, by severely limiting the kinds of software structures you are allowed to create. But I'm sure there are other, less restrictive ways waiting to be invented. I hold out hope that nested boxes isn't the be-all, end-all of programming.
Re: (Score:2)
Adds function overhead (which the compiler may not be able to optimize away).
May require ugly return value status coding.
Error escapes from multiple depths can require additional layers of functions.
The problem with the book... (Score:5, Funny)
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
Re: (Score:2, Funny)
Re: (Score:2)
beautiful code (Score:5, Funny)
Beer b = (Beer)getBeer();
drinkBeer(b);
belch(BelchType.LOUDLY);
}
Re: (Score:2, Funny)
Re: (Score:2)
Dangers of binge drinking (Score:2)
Re: (Score:3, Funny)
Nope. drinkBeer(b) frees the beer instance.
(But there may be a memory leak in the PROGRAMMER after enough iterations.)
Re: (Score:3, Funny)
getBeer() may be using the flyweight pattern, and reusing previous beer instances (presumably after their
Re: (Score:2, Funny)
Most code is beautiful at one point in time (Score:4, Insightful)
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.
Re: (Score:2)
You've just described why reusable code, and simplicity, is so important.
You started off hitting the nail on the head. Applications need to be designed so that they can grow with grace and retain their elegance. However, it is impossible to predict the future and I've seen so many projects where
No. That is not a trick, that's doom. (Score:2)
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
Re: (Score:2)
For myself, the learning curve went something like this:
1) Was tight on time, decided to copy/paste code and not design in flexibility for things I thought could probably use it. Ended up taking more time than I probably would have otherwise and turning out some poor inflexible code. At this point, I swore to design everything up-front first.
2) Next time around decided that I will design, design and design. End up spending
I've become jaded (Score:5, Insightful)
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.
Re: (Score:2, Insightful)
I have seen examples where a person knows langiage A but is working with language B. And by God he WILL try to make language B work like language A, come hell or high water.
This is where you get "clever code". Which is un-maintainable.
Re: (Score:2)
Re: (Score:2)
Or, how about this: OO code is beneficial when you're trying to solve an inherently OO problem, but not all problems are OO. Some are procedural, some are functional, etc., and you're better off using the appropriate paradigm for the task.
Stupid frameworks. (Score:5, Insightful)
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.
Re: (Score:2)
You know, this seems to work both ways. Ever worked with a homebrew framework that didn't have good exception-handling or some type of passable tracing? The other end of the spectrum from these IBM Java guys are the people who still hardcode strings everywhere in the system and hand-code ALL of their stored procs and data access layer.
There are actually two problems here
From the top, Javaheads like your above description are trapped in the Enterprise
Re: (Score:3, Interesting)
The end result is you end up with what should be a fairly simple task (like OO-relational mapping) have 400 page manuals because...
OR mapping frameworks require complex configuration only when you have to express complicated things about the relationships between the entities and the tables. There's no way to eliminate that without eliminating the relationship!
Sensible OR mapping frameworks use sensible defaults, however, so that for simple classes simple configuration is required. For example, using Hibernate with a class with no associations with other classes, all you have to do is annotate it with @Entity and annotate the primary
Re: (Score:2)
Need to use multiple database vendors with one code base? Fine, use stored procedures, standard SQL, o
Re: (Score:3, Interesting)
AKA write multiple implementations, one for each vendor.
standard SQL,
AKA cripple your program to the lowest common denominator. You'll spend hours working around the fact that different vendors do even basic things like giving a record a unique identifier in different ways.
or abstract the difference away.
Which is precisely what frameworks like Hibernate do.
Re: (Score:2)
I find it like a halfway house between PreparedStatements and Hibernate. Works fine with existing schemas.
Re: (Score:2)
In fact the first chapter includes code which pretty much meets your criteria... The chapter is written by Brian Kernighan and it's about a small piece of code written by Rob Pike.
Next time your complaint about broad generalizations which don't apply to their intended targets shouldn't itself be a broad generalization which doesn't apply to its intended target
Re: (Score:3, Interesting)
Re: (Score:3, Interesting)
I have no experience of Struts, but if you have this problem with Spring MVC, you're using it wrong. Seriously. Spring MVC has helped me write some of the simplest, most maintainable web code I've ever worked with. Almost everything is automated: all I have to do in most situations for a common database view/query/updat
The most beautiful code I've ever seen... (Score:5, Interesting)
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.
Re: (Score:2, Informative)
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 r
Re: (Score:3, Insightful)
Visually and Logically Beautiful (Score:2)
I think getting code to be logically beautiful is much harde
Re:Visually and Logically Beautiful (Score:4, Insightful)
Re: (Score:2)
Re: (Score:2)
mathematician vs. physicist (Score:3, Interesting)
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.
Obligatory comment that 90% of programmers' (Score:2)
Re: (Score:2)
Poetic Code (Score:3, Interesting)
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() [slashdot.org]
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 [wikipedia.org]. Or Spenser's Faerie Queene.
Re:Have to say... (Score:5, Funny)
I, too, am the only one I know who writes decent code.
Re: (Score:2)
Re:Have to say... (Score:4, Interesting)
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.
Re:Have to say... (Score:5, Insightful)
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.
Re: (Score:3, Interesting)
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. :)
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 writi
Re: (Score:2)
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.
Re: (Score:2)
Re: (Score:2)
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 tellin
Re: (Score:2)
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 int
Re:Have to say... (Score:4, Insightful)
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.
Re: (Score:2)
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 wha
Re: (Score:2)
Re: (Score:2)
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 co
Re: (Score:2)
Re: (Score:2)
Perhaps in chapters 6 and 7?
Re: (Score:3, Informative)
Huh? Are you looking at the same site as me? I count 10 articles, of which:
1 is about the design of a core Java API
1 is about implementing a library in C
3 are completely language independent
1 is about a development environment called "Subtext" which has its own language
1 is about Haskell
1 is about the book discussed
2 are about object-oriented design, and use Java in example code (but the text of the article applies equally to any object-oriented language)
That do