Saturday, February 24, 2007

Do DRY Programming

I would like to share this informative article which explains programming in simple and effective way. This is part of an IEEE article.

Some people feel that “getting” object-oriented programming is a difficult,time-consuming process. But does it need to be that hard? And is the difficulty even specific to OO programming? Many of the cornerstones of OO programming benefit other programming paradigms as well. Even if you’re writing shell scripts or batch files, you can use these techniques to great advantage.

What’s good code?

There are many aspects to writing good code, but most of these hinge on a single underlying quality: flexibility. Flexibility means that you can change the code easily, adapt it to new and revised circumstances, and use it in contexts other than those originally intended.

Why does code need to be flexible? It’s largely because of us humans. We misunderstand communications (be they written or oral). Requirements change. We build the right thing the wrong way, or if we manage to build something the right way, it turns out to be the wrong thing by the time we’re done.

Despite our fondest wishes, we’ll never get it right the first time. Our mistakes lie in continually assuming that we can and in searching for salvation in new programming languages, better processes, or new IDEs. In-stead, we need to realize that software must be soft: it has to be easy to change because it will change despite our misguided efforts otherwise.

Capers Jones, in his book Software Assessments, Benchmarks, and Best Practices (Addi-son-Wesley, 2000), showed that requirements change at a rate of about 2 percent per month(which really starts to add up after a year or two). But the problem with changes to projects is by no means limited to the common scape-goat of “requirements,” nor is it limited to the software industry.

According to a study of building construction in the UK (“Rethinking Construction,”Construction Task Force report to the Deputy Prime Minister, 1998), some 30 percent of rework isn’t due to requirements changes at all. It’s due to mistakes: plain, old human errors, such as cutting a joist 2 inches too short. Using the wrong kind of nail. Cutting the window in the wrong wall. It’s just human nature that we’ll get some things wrong,so what differentiates software quality is how well—and how quickly we can fix or change something. Flexible code can be changed easily and cheaply, regardless of whether the change is necessitated by volatile requirements or our own misunderstanding.

Most of the important lessons to be learned about object technology—how to avoid many common mistakes and keep code flexible—can be summed up in one sentence: “Keep it DRY, keep it shy, and tell the other guy.” Let’s take a look at what that means and how you can apply these lessons to all good code, not just OO code.

Keep it DRY

Our DRY (Don’t Repeat Yourself)principle deals with knowledge representation in programs (see The Pragmatic Programmer, Addison-Wesley,2000). It’s a powerful idea that states:

Every piece of knowledge must have a single, unambiguous, and authoritative representation within a system.

In other words, you should represent any idea, any scrap of knowledge,in a system in just one place. You might end up with physical copies of code for various reasons (middle ware and data-base products could impose this restriction, for instance). But only one of these physical representations is the authoritative source. Ideally, you’d be able to automatically generate or pro-duce the non authoritative sources from the single authoritative source.

Why go to all this trouble? So that when a code change is required, you only have to make it in one place. Any-thing else is a recipe for disaster, introducing inconsistencies and potentially hard-to-find bugs.

DRY applies to code but also to every other part of the system and to developers’ daily lives—build processes,documentation, database schema, code reviews, and so on.

Keep it shy

The best code is very shy. Like a four-year old hiding behind a mother’s skirt, code shouldn’t reveal too much of itself and shouldn’t be too nosy into others affairs.

But you might find that your shy code grows up too fast, shedding its demure shyness in favor of wild promiscuity. When code isn’t shy, you’ll get unwanted coupling; these axes of ill-advised coup-ling include static, dynamic, domain, and temporal.

Static coupling exists when a piece of code requires another piece of code to compile. This isn’t a bad or evil thing far from it. Even the canonical“Hello World” program requires the standard I/O library and such. But you have to be aware of accidentally dragging in more than you need.

Inheritance is infamous for dragging in a lot of excess baggage. Often it’s more efficient, more flexible, and safer to use delegation instead of inheritance(which should be reserved for true is a relationships, not has-a or uses-a). Shy people don’t talk to strangers, and shy code should be equally wary of other code that wants to come along for the ride.

Dynamic coupling occurs when apiece of code uses another piece of code at runtime. This can get seriously out offhand using a style we call the “train wreck” .

To get the state for an order, this code has to have detailed knowledge of an address, a customer, and an order—and rely on these three components’ implied hierarchal structure. If any-thing in that mix changes, we’re introuble; this code will break. Shy code only talks to code it deals with directlyand doesn’t daisy-chain through tostrangers as in the previous example.

Domain coupling takes place whenbusiness rules and policies become em-bedded in code. Again, that’s not neces-sarily a bad thing unless mirroring real-world changes becomes difficult. If thereal world is particularly volatile, putthe business rules in metadata, either ina database or property file. Keep thecode shy by not being too nosy aboutthe details: the code can act as an en-gine for the business rules. The rulescan change at whim, and the code willmerrily process them without anychange to the code itself. Small inter-preters work well for this (reallysmall—like a case statement, not a largeyacc/lex endeavor).

Temporal coupling appears whenyou have a dependency on time—eitheron things that must occur in a certainorder, at a certain time, by a certaintime, or worse, at the same time. Al-ways plan on writing concurrent codebecause the odds are good that it willend up that way anyhow, and you’ll geta better design as a fringe benefit. Yourcode shouldn’t care about what elsemight be happening at the same time; itshould just work regardless.

Code shouldn’t be nosy. I used tohave a neighbor who would peerhawklike over her kitchen sink out thefront window and keep track of everyneighbor’s comings and goings. Her lifehung at the mercy of every whim of theentire neighborhood; it wasn’t ahealthy position for her to be in, and itisn’t a healthy position for your codeeither. A big part of not being nosy liesin our next item.

Tell the other guy

One of our favorite OO principles is“Tell, Don’t Ask” (see IEEE Software,Jan./Feb. 2003, p. 10).

To recap briefly: as an industry, we’vecome to think of software in terms offunction calls. Even in OO systems, we view an object’s behavioral interface as aset of function calls. That’s really not ahelpful metaphor. Instead of calling soft-ware a function, view it as sending amessage.

“Sending a message” to an objectconveys an air of apathy. I’ve just sentyou an order (or a request), and I don’treally care who or what you are or (es-pecially) how you do it. Just get itdone. This service-oriented, operation-centric viewpoint is critical to goodcode. Apathy toward the details, in thiscase, is just the right approach. You tellan object what to do; you don’t ask itfor data (too many details) and attemptto do the work yourself.

By “telling the other guy” in thisway, you ensure an imperative codingstyle that keeps your code from be-coming too nosy and from getting in-volved in details that it shouldn’t careabout. Such involvement would makeyour code much more vulnerable tochange. To make this work in a sys-tem, you’ll need to preserve the com-monsense semantics of commands(that is, every object that has a printmethod should behave similarly whencalled).

This isn’t an OO-specific tech-nique either. Even shell scripts canbenefit from this approach. In fact, acommon Linux command employspolymorphism at the command line.The command fsck (which is not acartoon swear word—really) per-forms a file system check. When youinvoke fsck, it determines the file sys-tem type and then runs a delegate,such as fsck.ext2, fsck.msdos,or fsck.vfat, that performs the ac-tual tests for that kind of file system.But you, as the requester, don’t care.You tell the system to check the diskvia an fsck command and it just doesit. It’s just the right amount of apathy.

So remember to “keep it DRY, keepit shy, and tell the other guy.”

No comments:

Post a Comment