Why do you hate bad design so much?

Bad design is “everywhere”… 

My old microwave oven had one control, a dial. Just put the food in and turn it. The whole dial represented 12 minutes, so just estimate how far to turn it. My new microwave has 22 buttons. I forget which is which. I have to turn on the lights and get my glasses. 

The previous owner installed vertical blinds on the double hung windows. Think about that. Impossible to have open windows without endless noise and movement. 

An office where I work is near an airport. They have a key card system that beeps with a successful swipe. So you can’t hear the beep when an airplane is passing overhead (every 5 minutes) and have to wait until it’s gone to get into the building. 

Another office has “gone green” and installed motion sensors everywhere to turn off lights not being used. Good luck finishing up in the restroom if you’ve been sitting too long. 

Some of my software asks “Save before exit?” whether I’ve changed anything or not. I got so tired of trying to remember if I had updated or only viewed, I just click “Yes” every time. Pointless. 

Every time the garbage truck drops the dumpster back down next door, 3 car alarms go off. No one ever responds, because they assume that it’s a false alarm. Not that big a deal until the garbage truck shows up at 4:00 a.m. on Saturday.

My TV remote has 33 buttons. So they’re so small, you have to stop and look at it to hit “Mute” or “Last Channel”, the only 2 buttons I ever use. Who designed this thing, a munchkin? 

The airports in Orlando, Philadelphia, San Jose, and Miami put the restaurants (not counting junk food) “outside” of security. So you have to wonder, “Do I have enough time to eat and then get through the line?” (Pittsburgh, Tampa, and Chicago Midway did it right.) 

The trunk release and gas cap release levers in my car are next to each other but not visible. It’s hard to pull one without the other. Seems like my gas cap door is always open. 

A theater we went to the other night only had aisles on the sides with 50 seats in between. Do your really want that great seat in the center knowing you may have to climb over 25 people if you need the restroom before the movie is over? 

Intersections that gridlock because of traffic from the next light. Too many to mention. 

Microsoft Windows. 


What’s the best way to assign ID’s?

The “Name” issue isn’t that much different from the “SKU” issue. (SKU is short for Stock Keeping Unit, aka Part Number or Product Number). I have had to deal with this everywhere that has SKUs. No one does it well, but by slowing down and thinking about it, there’s almost always a decent solution. 

There are 2 ways to assign SKUs, sequentially (start with “1” and increment 1 for every new SKU) or not sequentially. I have never seen anyone do it sequentially. (Although some excellent systems keep 2 SKUs, one of which “is” sequential and is used as the primary key and for all indexing. This is the best way I’ve ever seen to handle SKUs that change, but that’s another story.)

Almost everyone wants a smart or semi-smart SKU. So that by simply looking at the SKU, anyone can tell what it is without reading the description. You know, the first digit is Commodity Code, 1 for shoes, 2 for pants, etc. Then another digit for color, another for size, etc. This works well until you have ten colors; then you need 2 digits or alphas. 

But wait, there’s more. Let’s put hyphens (or some other delimitter) between the product descriptors and the vendor data, manufacturer data, and customer data. 

So now you’ve covered any possible product with your super slick smart SKU naming system. 

Until something comes along that isn’t covered. (Now we have military items with 14 other considerations.) So we come up we a second totally different scheme. Then a third. Then a 4th, etc. So now you can tell anything about an item “if you know which scheme” it falls under. 

But wait, there’s more. You should be able to enter any SKU into a form field “regardless of Smart SKU scheme”. (If the first digit is “9”, then use Smart Scheme 3. If there’s a hyphen in position 3, then use Smart Scheme 8, etc.) Your form logic should be able to intelligently guide the user based on the rules of the template or scheme. 

I have built apps where users can design and build their own Smart SKU templates, which are then used to enforce compliance and guide operators. These have generally worked pretty well. 

Is there some way to do the same thing for human names? I dunno, but now you got me to thinking about it. A combination of standard templates and custom templates oughta cover most possibilities. Some basic logic with optional pop-up forms which uses the templates as parameters should work. Something to think about… 

How do you build something piece by piece?

I love how everything has a fancy name now. We’ve been doing StartInTheMiddle / MinimumViableProduct / Prototyping / GetSomethingOut / StepwiseRefinement for years: 

Customer: I must have anything I want from the database without asking you. 

Me, 1 hour later: No problem, here’s your screen. 

Customer: This only does does Customers. I want to pick “any” table. 

Me, 1 hour later: No problem, now you can pick your table. 

Customer: This dumps every column. I want to pick my own. 

Me, 1 hour later: No problem. Now you can pick your columns. 

Customer: This doesn’t sort. I want it to sort. 

Me, 1 hour later: No problem. Now you can sort. 

Customer: But I want multiple sorts, some ascending, some descending. 

Me, 1 hour later: No problem. Sort any way you want. 

Customer: It dumps the whole table. I want to filter. 

Me, 1 hour later: No problem. Now you can filter. 

Customer: It only give me local columns. I want columns from other tables, too. 

Me, 5 mins later: Give me an example. 

Customer: Here. Give me these linked columns and accumulators, too. 

Me, 2 days later: OK. I figured out how to give you all this data too. 

Customer: OK. This will work. Why didn’t you do all this in the first place? 

Stepwise Refinement Method: Time to beta: 1 hour. Time to production: 3 days. 

Waterfall Method: Time to beta: not applicable. Time to production: who knows? 

Programming FAQ

What editor do you use? 

Textpad. 

How can I learn to program? 

Find a customer with unreasonable deadlines. Hit them. Repeat. It won’t be pretty, but you’ll be the kind of programmer I’d go into battle with: great at the things that really matter and mediocre at the things that don’t. 

Why do you advise plunging right into a programming project instead of carefully planning it first? 

It’s incredibly difficult for anyone to define what they want when they start with nothing. It’s human nature (incredibly easy) to criticize what you have and how to make it better. Plunging right in and producing anything raises you from LevelIncrediblyDifficlut to LevelHumanNature. 

Why do you keep going on about PICK? 

I have a very small back pocket that holds everything you need to program in PICK. Whatever you can do in technology , I can probably do in PICK, often quicker and easier. 

Isn’t object-oriented programming naturally suited to some problems? 

Sure, but that doesn’t necessarily mean you have to use formal object-oriented technology. You can mimic the concepts with almost any technology. 


Is becoming a lazy programmer evolving?

Show me any tool and I’ll show you a horrible use of that tool. That doesn’t make the tool horrible. 

ELSE statements don’t kill. Drunk programmers kill. 

This reminds me of something I once ran into: 


Junior Programmer:

if (m==1){Month="January")} 

if (m==2){Month="February")} 

if (m==3){Month="March")} 

if (m==4){Month="April")} 

if (m==5){Month="May")} 

if (m==6){Month="June")} 

if (m==7){Month="July")} 

if (m==8){Month="August")} 

if (m==9){Month="September")} 

if (m==10){Month="October")} 

if (m==11){Month="November")} 

if (m==12){Month="December")} 


Senior Programmer:

 switch(m) 

case 1:

Month = "January" 

break;

case 2: 

Month = "February" 

break; 

case 3: 

Month = "March" 

break;

case 4: 

Month = "April" 

break;

case 5: 

Month = "May" 

break;

case 6: 

Month = "June" 

break;

case 7: 

Month = "July" 

break;

case 8: 

Month = "August" 

break;

case 9: 

Month = "September" 

break;

case 10: 

Month = "October" 

break;

case 11: 

Month = "November" 

break;

case 12: 

Month = "December" 

break;

default: 

Month = "unknown" 


Lazy Programmer:

 MonthNames == ["","January","February","March",...] 

 Month = MonthNames[m] 


Are these things really that hard to do?

“I have not seen these things be successful, therefore they “can’t” be successful”. 

This kind of thinking scares me, not so much because it’s so myopic, but because it becomes a self-fulfilling prophecy: “I have never seen success” becomes “Success is not possible” which becomes true because we stop trying.

Mere mortals throw up their hands in futility, blaming the user, the state of the art, or the alignment of the planets, without ever understanding the fundamental principal that great systems accommodate great needs and the greatest need of all is constant change. 

“the company recategorizes its product line based on utility and lifestyle rather than brand and designer”

This is incredibly common and can easily be accommodated with proper database design, decoupling products from their associated attributes. 

“the parent company divests itself of you and withdraws the connection to its parts and inventory database” 

So now you have to treat them like any other vendor? You do have some of those, don’t you? 

“a manufacturer starts using more than one UPC per product because they changed the packaging” 

A simple database design consideration. “One to one” is just a special case of “one to many”. 

“the law now requires that national holidays must be counted against vacation time if the employee takes a vacation day immediately before/after that holiday” 

Rule driven logic. What’s the big deal? (Your logic was rule-driven from the outset, not hard-coded, right?) 

“a loan company files to become a bank and store deposits that earn interest” 

Additional logic to existing data. We do this all the time. 

“CSV files exchanged with a partner were always denormalized, but then one company starts using normalized records with mixed column mappings” 

Any decent batch file processor should be able to handle anything thrown at it. Companies that do a lot of this build uncertainty into the design of their systems.

“another partner decides to ditch file transfer as a way to submit data, and creates a web service that you’re supposed to invoke commands on”

Sounds like you’ll need an extra piece of software to create a feed. Not exactly like no one’s ever done this before. 

“the shipping carrier reveals that their tracking numbers are all recycled at the end of each year” 

Not a problem if they were never used as the primary key to a table. 

“new rules require every credit card number to be encrypted, but you still have to be able to quickly search for matches in a database of millions” 

Ahh, but the last 4 digits do not have to be encrypted. Start your search with them and resolve synonyms. Pretty standard stuff. 

“a partner switches to mixed-case alphanumeric PO numbers” 

As an identifier, a PO number is always a string even if it looks like it’s numeric. (When was the last time you added 2 PO numbers together?) 

OP’s roadblocks are experienced developers’ speed bumps. Just because he hasn’t done it doesn’t really mean that “Nobody knows what they’re doing”. 


Annoyances vs. Requirements

“One of the annoyances that we have to deal when building enterprise applications is the requirement that no data shall be lost.” 

Since when is a business requirement an “annoyance”? We keep data for lots of good reasons. Just a few off the top of my head:


- IRS requirements 

- SEC requirements 

- SOX requirements 

- data warehousing 

- data auditing 

- delayed undo 

- business intelligence 

- trend reporting & analysis 

- research & development 

- cooperative databases 

- industry databases & statistics 


“The usual response to that is to introduce a WasDeleted or an IsActive column in the database and implement deletes as an update that would set that flag.” 

Wrong. The usual response is archiving to disk using separate tables. This solves all of the requirements above while streamlining active database tables. It’s not unusual for 98% of all the enterprise data on disk to be in the archived state. 

“This sort of cleanup now has to moved up into the application layer.” 

So what? 

One of the biggest mistakes I consistently see is trying to use the facilities of a database management system to replace application logic. Indexes, triggers, and stored procedures are all critical tools in the developer’s arsenal, but they do not replace application analysis, design, and programming. Like security and scaling, archiving is a “architectural consideration”, not a bolt on. Including proper data archiving in the application’s design renders the hard vs. soft delete debate pointless.

Technical Debt

Typical way that competent developers end up with technical debt: 

1. Customer/user/consumer has a vague idea of what they need but doesn’t know how to express it. 

2. Developer works with customer to learn their business and understand their requirements. 

3. Developer throws together a prototype to confirm that he understands the problem.

4. Customer sees that developer is on the right track. If these 9 enhancements are done, then we’ll really have something. 

5. Developer quickly adds 9 enhancements to prototype. 

6. Customer loves it! Move it to production so we can play with it for a while. 

7. While customer plays with it, developer maps out a plan to architect, refactor, and scale the prototype to be “production worthy”. 

8. Developer is pulled away to 5 other urgent projects. 

9. Customer continues to use prototype as production software. 

10. Two years later: “Who wrote this crap?” 

What makes code crappy?

When it comes to maintaining code, I believe there are 2 kinds of crap: subjective (I don’t like it) and objective (it’s crap because of these 14 specific reasons). 

You’re probably right about people who inherit my code. I know, when they’ve whined about it, I confronted them. “Please show me exactly what’s wrong with it. What are your specific complaints about violations?” I rarely got an objective answer. It was usually something about formatting, indenting, variable names too long, variable names too short, I’m used to it the way we did it (wrongly) at XYZ Co., something like that. 

True crap can be objectively identified by a violation such as: 


- variables named so that no one except King Tut could possibly figure out what they are 

- the same variables used for different purpose “at the same time”, usually in nested recursions 

- variables named with 1 or 2 characters 

- unassigned variables 

- variables initiated when they shouldn’t be 

- division by zero 

- single entry, multiple exit (heavily maintained so that now outlying cases skip critical logic) 

- the same code in multiple places (only some of it maintained so that outlying cases skip critical logic) 

- endless recursions (for outlying cases only, naturally) 

- comments that don’t agree with the code 

- data base tables with no definitions either in the schema or any code (my new favorite) 


I could go on and on, but you kinda get the picture. I wonder how many readers here have posted crap like this on their “wall of shame” at one time or another. It’s funny the first 2^n times. Not so much fun anymore. 

Is software engineering dead?

“Software Engineering is Dead” is obviously an overly sensational title, but let’s look for the deeper truths. 

First a little background. I have built a career developing business applications as a contractor, often in very large organizations. I am almost always very successful and I’m often regarded as a hero doing what most people here would call “just doing my job”. 

Why is it so easy to be a hero in the enterprise with software that would just seem ordinary in other places? Is it because enterprise programmers aren’t as good as us? Is it because their managers are all phbs? Or because they don’t know how to run projects? 

I’d say no to all of the above. Enterprises are filled with lots of excellent people doing great work. 

I think that the real problem is that the Systems Development Life Cycle (SDLC) that so many depend on so much “never really did work”. Why? 

Every phase depends upon Phase I, Analysis to be rigorously done. This rarely happens for 2 reasons: users often don’t know what they want and most systems analysts don’t know how to extract it even if they did. 

So almost everything done after Phase I is built upon a foundation of sand. It’s either wrong or sinking fast. 

And what do most people do? Everything except fixing the problem: more resources, more project management, freezing specs (which aren’t right in the first place), more rigorous deadlines, etc. 

But rarely does anyone attack the core problem with the Systems Development Life Cycle: defining the expected result. 

So what should we really do? Develop something, anything, quickly, cheaply, and get it out to the right users. They will instantly give you feedback. What’s right, what’s wrong, what’s stupid, all the cool stuff that no one thought of. 

No one can just sit down and write a Functional Specification for a large business application. And even if they could, you don’t want them spending time on it. Better to get the right people together and find out what they need. Usually, no one of them knows what the result should be, but all together, any decent developer should be able to extract enough data to write version 1.0 of “something”. 

It’s a lot easier to judge something that exists than define something that doesn’t. 

The larger the organization, the more difficult it is to change their ways. 

Software engineering isn’t dead. It’s just that the process of depending upon blueprints before you get started never worked in the first place.