2008-01-29

Reading code.

I think that reading other people's code has been the one thing that has
furthered my ability to program the most in the shortest timeframes.

I have learned something from every (non-trivial) collection of code
that I have read that was not written by myself.

Particularily, I feel that I have gained the most from deciphering
what I would consider to be bad code - it shows you what types of
patterns lead to writing unmaintainable code. Of course, the question
of what makes a particular program _bad_ or _poorly_written_ is a bit
subjective at best.

I would argue here that bad code is code that is
hard to understand, even with a firm knowledge of the language that it
has been written in, and an appropriate amount of time to brush up on
any domain-specific knowledge you may need to know to understand the code.

There are a few more subjective terms in the definition given here for
bad code, but I'd be delving into philosophy that doesn't really relate
to the point at hand. The point is that if I know language X well enough
to feel comfortable writing a fairly complex program in it, and I have a
few weeks (at the very most, for most things) to read up on domain-
specific knowledge, and I can't understand what someone else's code,
I consider it bad code.

It could be argued that there are cases in which someone could be thrown
off by the use of a design pattern that they haven't read yet, but I think that's
a bit of a bullshit argument. For one thing, if someone is really interested
in being able to express their programs better (in order to write better
programs, or in order to be able to write and manage complicated programs),
they will run into the concept of design patterns fairly quickly. For
another thing, if the code is well written, it will either still be
obvious what's going on. If the code is well-commented, there will be
easily searchable ideas to help the reader get a clue what's going on,
and the readers reaction will be something like "Oh, well that's a good
way to do that."

So saying someone could be thrown off by seeing use of a design pattern before
being familiar with it is true, but the probability of it being true decreases
as the readers experience increases (assuming that the reader is actively
studying the "art of programming"), and also decreases if the code is well-written.

I do not make these cases from code that I have written, but from code that
I have read, and understood. Code that was well-commented, especially in
code that dealt with domain-specific knowledge was incredibly helpful in
figuring out what was going on. Code that was structured in such a way that
methods did more or less one cohesive action, and objects represented one
cohesive group of data and the methods associated with it made the understanding
of code that had many complex relationships much easier to handle. Code that
had only one of these qualities was harder to understand, and code that
had none of these qualities was even harder to understand - sometimes I would
have to map out execution with a lot of logging, or with pencil and paper to
be able to obtain a grasp of how the system operated as a whole.

I should note that I would include variable and method names as being a
form of comment - the computer couldn't care less what characters make up
the variable or method name, they only serve as a reminder to yourself and to
other programmers of what the variable or methods purpose is.

Good code is just the opposite of bad code - it's very clear. Variables and
methods have meaningful names. Even without extensive knowledge of the domain
that the program is written for, it is possible to search online for the
specific knowledge needed to be able to make modifications to the source.

Writing good code is a lot of work - and it's not easy at first. It could be
argued that it's never easy. It is magnitudes harder than just writing code
"that works," at least for me, however I find that having a long design phase
before I start coding decreases the amount of work that it takes.

What I consider to be "the best" code I've read has never been something that
appeared that it was written off the top of someone's head. It always seemed
apparant that whoever had written it had taken into account that other people
would be reading it - possibly themselves at a later date. It also always seemed
like the way that the code worked, the ways that the object represented were
defined, and the ways in which they interacted with each other made sense.

Duh, I guess, and you can pick up on all these things by reading good code.

I said earlier that I thought that I had gained more from reading poorly written
code - and that's true. Poorly written code has shown me that even if you can
hold a problem entirely in your head when you write the code for it, you may not
be able to remember all the details of that problem when you go to look at it a
few months down the road. It's shown me that idioms that may be entirely clear
to me may not be clear to someone else - and vice versa.

Reading poorly written code (as well as well-written code, but less often) has
also pushed my knowledge of a language into the darker "relying on quirks" part
of it. For example:

Q: What happens if you cast the result of trying to take the sqrt of a negative
number to int in C++?

A: You get negative maxint minus one.

This may be really common knowledge among people who use C++ a lot. I haven't
used it a whole lot for years - I ran into this translating some C++ into python
for a client. The code was using this result in a less-than comparison, and
relied on this behaviour as a type of error-filtering. This is not the correct
way to handle this.

Anyhow, if you're looking to increase your ability to program, you should read
other people's code. Often. Regardless of if it's well or poorly
written. Actually, you should _understand_ other people's code - and that may
not involve just reading it. Don't have any code to read? Pull the source for an
open source app you use a lot, especially if you've had an idea that you think
would make it better. Modify it, and submit your contributions.

2008-01-02

Locking a section of text in emacs

Today, I was talking to a friend about things that would be useful for text editors. One feature that we thought was missing was the ability to select a region of text, and lock it so as to prevent accidental editing without unlocking it.

This was rather trivial to add to emacs:


(defun lock ()
"Make a section of text read-only, and add an overlay so
it's apparent"
(interactive)
(let ((start (region-beginning))
(end (region-end)))
(overlay-put (make-overlay start (+ 1 end)) 'face
'(:background "light slate gray"))
(put-text-property start end 'read-only t)))

(defun unlock ()
"Unlock a region of text, and remove its overlay"
(interactive)
(let ((inhibit-read-only t)
(start (region-beginning))
(end (region-end)))
(remove-overlays start (+ 1 end))
(remove-text-properties start end '(read-only))))


Just bind lock and unlock to some keys, and there you go - makes a region of text uneditable, and adds an overlay to it.