Reading great code

  • Thread starter Thread starter gt8887b
  • Start date Start date
That assumes a design process which comes strictly ahead of the real
code. With TDD, although you need the high level architecture ahead of
time, the design of the public contract often emerges as you try to
write tests which use the production class in the easiest way. Guessing
exactly what will be easy to use ahead of time is often very hard
indeed - and a waste of time, IMO, when writing tests can get you to
the end result faster, and with demonstrably working code.

The term "guessing exactly"applies more to the long odds of winning a
lottery than any sort of true application/system design. The whole
purpose of the design stage is to eliminate much if not all of the
guess work. The last D in TDD stands for development which encompasses
much more than trying to write production code. A great deal of coding
and testing can/should be done during the design process. The
validation of a particular design is the production of a functional
proof of concept. Granted more time is taken for the design phase but
development difficulties are front-loaded into the process. The
production phase is simplified as the programmers have fewer issues to
consider and fewer questions to ask.

regards
A.G.
 
Kevin said:
Well, if all this debate, each person making some excellent points, and
almost all at odds with one another over those very points, doesn't point up
the greatest difficulty of mastering programming, I don't know what will.

I can't help thinking that this difficulty is because code isn't great
in isolation, it's great in relation to its purpose. My line is
mission-critical applications (my interest in C# is as a hobbyist,
though I'm keeping a professional eye on spec#), and the greatest
mission-critical code I've ever seen has been spectacularly dull,
vanilla coding. If I could post any of the code here, most folks would
just shrug and say "so what?" What made it great was the design work
that had gone into getting to the point where the coding was really
/really/ simple, and the willpower of the coders who resisted the
temptation to do any fancy tricks to make it more "elegant" or add
unnecessary bells and whistles (such as trying to make code reuseable:
software re-use has led to some major incidents, so although the
mission-critical community does use reuse -- every time the programmer
tells the compiler to allocate an array they're using re-use at some
level -- they do treat it with a great deal of caution).
 
unnecessary bells and whistles (such as trying to make code reuseable:
software re-use has led to some major incidents, so although the
mission-critical community does use reuse -- every time the programmer
tells the compiler to allocate an array they're using re-use at some
level -- they do treat it with a great deal of caution).

Do you use the Common Language Runtime Library? Then you use reusable code.
Unless you write your own MSIL, you're using a *lot* of reusable code.

--
HTH,

Kevin Spencer
Microsoft MVP
Chicken Salad Shooter
http://unclechutney.blogspot.com

A man, a plan, a canal, a palindrome that has.. oh, never mind.
 
Yes, it definitely is a balancing act. However, the "constrained by time
and money" argument is one I've heard far too many times over the years.
In practice it doesn't wash however because one is always restrained by
resources in every endeavour in life.

I'm glad you don't have bosses that give you unreasonable deadlines, and
plenty of help. Either that, or you write extremely small applications, well
back from the bleeding edge of software technology, with few features.
Personally, in over a dozen years of programming, I've always had to "fish
or cut bait" at some point, some point that requires me to refactor a good
bit less than I'd like to.

--
HTH,

Kevin Spencer
Microsoft MVP
Chicken Salad Shooter
http://unclechutney.blogspot.com

A man, a plan, a canal, a palindrome that has.. oh, never mind.
 
Thank you all very much for your replies and insight.

Let me pitch in on what the definition of "great" is. In my opinion
"geat code" has these important characteristics:

1. It works - fulfills requirements and has no defects(bugs) that
affect its usefullness
2. It is elegant - uses consistent design pattern and coding style
3. It is maintainable - it is easy to understand what code does, how it
works, and make changes to it

As far as using "tricks" and writing "clever code"... I've seen far
too many examples where such efforts become counter-productive.

One of the biggest pitfalls is using "clever" code to make code faster.
Much too often this results in writing convoluted and error-prone code
to optimize some part of the program that does not need to be optimized!
 
Registered User said:
The term "guessing exactly"applies more to the long odds of winning a
lottery than any sort of true application/system design. The whole
purpose of the design stage is to eliminate much if not all of the
guess work.

Requirements change. It's a fact of life, unfortunate as it is. How are
you going to eliminate that? You can *guess* the areas where it will
change, and design accordingly, but that will always be guesswork.
The last D in TDD stands for development which encompasses
much more than trying to write production code. A great deal of coding
and testing can/should be done during the design process. The
validation of a particular design is the production of a functional
proof of concept. Granted more time is taken for the design phase but
development difficulties are front-loaded into the process. The
production phase is simplified as the programmers have fewer issues to
consider and fewer questions to ask.

Well, I'm not a fan of the big up-front design. Architecture, yes - but
when you get to the point of individual classes, I think a bit of
"just-in-time" design is fine.
 
Kevin said:
Do you use the Common Language Runtime Library? Then you use reusable code.
Unless you write your own MSIL, you're using a *lot* of reusable code.
I use it as a hobbyist. As I said, professionally I don't use C#. I'm
not aware of any mission-critical applications that use .NET (or Mono),
and the more critical applications use specialist operating systems (and
compilers, and libraries) or no operating system at all (except perhaps
as a loader), for just the reason you've spotted.
 
I'm glad you don't have bosses that give you unreasonable deadlines, and
plenty of help. Either that, or you write extremely small applications,
well back from the bleeding edge of software technology, with few
features. Personally, in over a dozen years of programming, I've always
had to "fish or cut bait" at some point, some point that requires me to
refactor a good bit less than I'd like to.

You're situation is the norm, not the exception. One can still write
reasonably clean code even in a sweatshop. You can cut corners and still do
a clean job of it. Nobody has the luxury of working in a think tank with an
unlimited amount of time on their hands. We all face the same pressures yet
most of the bad code you encounter in the real world has little to do with
tight deadlines. The mess you see masquerading as software in most companies
became that way because the people who wrote it were novices. You can
clearly see it in their code. The pervasive sloppiness and poor design and
outright mechanical mistakes had little to do with deadlines. You don't see
the same problems in code written by those have mastered their craft
however. They face the very same deadlines yet their code remains reasonably
robust and extensible. It stands the test of time. It's the key to
successful software and those who don't follow it now always pay a heavy
price for it later.
 
Jon Skeet said:
Registered User <[email protected]> wrote:
Well, I'm not a fan of the big up-front design. Architecture, yes - but
when you get to the point of individual classes, I think a bit of
"just-in-time" design is fine.
<snip>

I agree, and here's why: Software design, like software development, is (or
should be) an iterative process, in which certain design features suggest
themselves during the development process. A well-structured, well-defined
"10,000- foot" architecture is very important, but below that point there
should be "wiggle-room" to allow for crative insights to occur as the
software takes shape. In fact, most software companies, Microsoft included,
implement ideas from beta testers during that phase of the process, which
seems to support some aspect of this idea.

Again, it's all a rather complex balancing act.

--
HTH,

Kevin Spencer
Microsoft MVP
Chicken Salad Shooter
http://unclechutney.blogspot.com

A man, a plan, a canal, a palindrome that has.. oh, never mind.
 
I use it as a hobbyist. As I said, professionally I don't use C#. I'm not
aware of any mission-critical applications that use .NET (or Mono), and
the more critical applications use specialist operating systems (and
compilers, and libraries) or no operating system at all (except perhaps as
a loader), for just the reason you've spotted.

I'm afraid you're just plain wrong here. First of all, if you use *any*
programming language above the Assembler level (which is, in fact, a library
of reusable machine code), you use various libraries (DLLs), as well as your
own custom code. The C language, for example, can't be used without at the
very least the stdio library. C++ has the MFC library. Java has the J2SE
library. The .Net platform is no different.

Second, there are *lots* of mission-critical applications out there written
with the .Net platform. It is not a prototyping platform, any more than Java
is a prototyping platform.

The only truly non-reusable code is machine code.

--
HTH,

Kevin Spencer
Microsoft MVP
Chicken Salad Shooter
http://unclechutney.blogspot.com

A man, a plan, a canal, a palindrome that has.. oh, never mind.
 
Kevin said:
I'm afraid you're just plain wrong here. First of all, if you use *any*
programming language above the Assembler level (which is, in fact, a library
of reusable machine code), you use various libraries (DLLs), as well as your
own custom code. The C language, for example, can't be used without at the
very least the stdio library. C++ has the MFC library. Java has the J2SE
library. The .Net platform is no different.

None of those languages is used for the sort of application I am dealing
with, at least not at the higher criticalities. Nor are their associated
libraries. And even when the languages used do have code libraries
available, those libraries are generally not used unless they have been
specifically designed with mission-critical applications in mind.
Second, there are *lots* of mission-critical applications out there written
with the .Net platform. It is not a prototyping platform, any more than Java
is a prototyping platform.

I'm not suggesting that .net is a prototyping platform; I know it's
better than that. There's a distinction between real-world applications
in general and mission-critical applications in particular. I'm dealing
with applications that can kill a few hundred people at a time if they
go wrong (and I work with people who are dealing with applications that
can kill a few thousand people at a time). I'm not aware of .net being
in used that sort of application, and I'd be very worried if it were,
not because there's anything wrong with .net but because that's not what
..net is designed to be good at. There's a lot of complexity in .net and
in MS Windows which gives the richness that AFAICS is a great help in
the cost-effective development of commercial-strength applications but
which is a problem for mission-critical. The hazards can't be completely
eliminated, but the more of them that are taken out of the system the
better.

Yes, as soon as I use a compiler I'm doing some code reuse courtesy of
the compiler's code generator. I was careful not to say that there was
no reuse, just that it's treated with a great deal of caution. Oh, and
on the more critical projects I've worked on, the I/O routines /have/
been custom-written in assembler. Before you ask, the correctness of
the microprocessor is a continuing issue, but it's a question of
eliminating unnecessary risks and being aware of (and managing) the
risks that are left.
 
On Mon, 16 Oct 2006 07:30:52 +0100, Jon Skeet [C# MVP]

- snippage -
Requirements change. It's a fact of life, unfortunate as it is. How are
you going to eliminate that? You can *guess* the areas where it will
change, and design accordingly, but that will always be guesswork.
The relationship between project owners and project managers is
bizarre. My experiences indicate the project manager ends up writing
the requirements document and submits it for the project owner's
approval. Too few project owners are able to provide cognizant details
with out much prodding and poking. "Is this what you mean?" is an
oft-asked question during these interrogations.

What to do when the requirements change midstream? The first thing to
do is determine if the change is indeed a requirement. Project owners
generally are not aware of the differences between requirements,
features and chrome. Pointing to the calendar and its made up
deadlines can often turn a new requirement into a feature for the next
version.

-more snippage -
Well, I'm not a fan of the big up-front design. Architecture, yes - but
when you get to the point of individual classes, I think a bit of
"just-in-time" design is fine.

I agree there will always be some need for JIT tweaking but not every
programmer has the required skills and mindset. Understanding
abstraction and thinking abstractly represent two different levels.

Thank you for the enjoyable exchange of ideas and opinions.

regards
A.G.
 
..Net is used by the U.S. Military. Is that mission-critical enough for you?

--
HTH,

Kevin Spencer
Microsoft MVP
Chicken Salad Shooter
http://unclechutney.blogspot.com

A man, a plan, a canal, a palindrome that has.. oh, never mind.
 
That's true - *if* you use the general functionality. It is usually
harder to understand the general functionality than specific
functionality. That's fine if you actually use it - but if you're only
ever going to use the code in one particular way, there's not a lot of
point in making it hugely flexible.

So true. Generalization for the sake of generalization is plain stupid. I
can't tell you how many times I've seen eager beavers trying to build base
classes to derive from and just ending up with a jumble of stuff that
doesn't work very well, barely hangs together and many times has a design
that doesn't even make sense. Keeping it simple is so hard for some people
and yet it is the only way to build code that works and that is robust and
safe.
Of course, when you then find yourself doing something similar,
*that's* the time to refactor the previous code and build the more
general functionality.

Iteration and refactoring is a big part of writing good code. It might not
be good today, but it will be tomorrow!

This is a very interesting and refreshing discussion.
 
The relationship between project owners and project managers is
bizarre. My experiences indicate the project manager ends up writing
the requirements document and submits it for the project owner's
approval. Too few project owners are able to provide cognizant details
with out much prodding and poking. "Is this what you mean?" is an
oft-asked question during these interrogations.

Easily summed up by "Ask them what they want, but give them what they
need".
 
Tim said:
None of those languages is used for the sort of application I am dealing
with, at least not at the higher criticalities. Nor are their associated
libraries. And even when the languages used do have code libraries
available, those libraries are generally not used unless they have been
specifically designed with mission-critical applications in mind.

Ada ?
I'm not suggesting that .net is a prototyping platform; I know it's
better than that. There's a distinction between real-world applications
in general and mission-critical applications in particular. I'm dealing
with applications that can kill a few hundred people at a time if they
go wrong (and I work with people who are dealing with applications that
can kill a few thousand people at a time). I'm not aware of .net being
in used that sort of application, and I'd be very worried if it were,
not because there's anything wrong with .net but because that's not what
.net is designed to be good at. There's a lot of complexity in .net and
in MS Windows which gives the richness that AFAICS is a great help in
the cost-effective development of commercial-strength applications but
which is a problem for mission-critical. The hazards can't be completely
eliminated, but the more of them that are taken out of the system the
better.

Indeed the Java license contains:

"You acknowledge that Licensed Software is not designed or
intended for use in the design, construction, operation or maintenance
of any nuclear facility."

I don't know if MS has a similar clause for .NET ...

Arne
 
Tim said:
A safe subset of Ada is a common choice, yes.

Ada is actually a nice language.

Arne

PS: I don't know whether you are aware of it, but you can
use Ada and .NET together via mgnat.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Back
Top