Nobody told me I had to be a teacher

A Tech Lead has to be a teacher? Why didn’t someone tell me?

We have this C# method. It used to be good. Small. 25 lines or less. All at one abstraction level. See Bob Martin.

One of the kids, from offshore as it happens, had a bright idea. Next morning I wake up to find that the method is now a 100 lines.

I want to tell the kids. The method is too large. No method should be more than 25 lines. And they will chop it down pronto. They are good kids. But. There is no telling how they will chop it down. If they know how to tell a story in simple, clear steps, I have not seen evidence of it yet. They can’t seem to find the shortest, most direct route, between A and B.

Ask them how to go from D.C. to Baltimore.

They will come up with this. I-495 from National Airport to I-270 and Frederick. Then take I-70 to Breezewood. Break East on the PA turnpike to Harrisburg. Finally, come down I-83 to Baltimore.

That was fun. We got to write a lot of code. Oh what a lovely route it was.

They won’t stop, look around, and find 295, the Baltimore Washington Parkway, a straight shot between the hearts of D.C and Baltimore.

So I have to teach them how to chop the method down. But there is a problem. I know how to do the work. I don’t know how to teach it to another person.

I can say, make sure all of the code is at a single level of abstraction. They have no idea what I am saying. I don’t blame them. What does the word ‘abstraction’ even mean? I don’t know how to describe it man, I just know it when I see it. You know the button that starts your car. That’s an abstraction. You know what I mean? You don’t? Well, bloody hell.

So now on to Plan C. I redo the method myself. You know, I give them advice, and an example. Guess what happens. Nothing. Two days later the silly drama repeats itself.

It turns out, they could not care less about Clean Code. They know the programming language. They know some libraries. They are decent at problem solving. They get a kick out of flipping switches and seeing results. They are having fun. They feel no inclination to examine what they are doing. Stop, step back, dig deep, see under the surface, unlearn old habits, cultivate new habits. Further, after a couple of Sprints, they also learn that I will clean up the code myself.

It took me a long time to understand how to write Clean Code. It took me much practice to do it instinctively. Do you know how much I rewrite? How am I going to get the kids to adopt a regimen of study and practice? How am I going to get them to show interest and sustain it? How am I going to get them to care?

I am only a working engineer. You are asking me to not only teach, but also to motivate.

All of this, I have to do while a project is going on; under the gun, to deliver something.

It is not going to happen.

You are not going to get Clean Code.

Unless. You hire the right people.

Developers must know the business domain – I

Knowledge of the business domain is essential to developers.  They must know the business as well as the business folks know it.

We have all worked in environments where the business analyst’s word is gospel.  The analyst specifies a solution, and the developer translates it verbatim into code.

This approach to software development is less then optimal.

Blind football

Imagine sending a running back onto the field blindfolded.  We tell him, never mind that you cannot see a thing.  The analyst will relay  instructions to your ear.  Follow them to the letter and Bob’s your uncle.

  • Run 6 yards on a 37 degree angle to the left.  Your left, not mine.
  • Now tack right, 82 degrees, and run 15 yards at a speed of 26 miles per hour.
  • Wait, 300 pound linebacker at 7 ‘o’ clock.  Wheel, dummy, wheel.
  • Uh oh, too late.  No, wait.  The linebacker got tripped by his own cornerback!

See, the defense has blindfolds on too.  In fact, all 22 players on the field are blind as bats.  They are unseeing puppets, lumbering about, whose strings the business analyst is pulling.  Don’t you think there will be stumbles?  You bet there will be.  The business analysts have to be superhuman to get everything right all the time.  Your team must loose the blindfolds.

Pre-empt the bug

Business folks and analysts are as fallible as the next person.  There will be holes in the information they provide.  These gaps can cause  errors.  Developers must recognize and fill those gaps so that they can avoid those errors.  The alternative is to let the error happen, hope that someone catches it, then fix the error.   How can this ever be better than avoiding the error in the first place?  

Process is very often, much ado about little

The first principle in the Agile Manifesto is “Individuals and Interactions, over processes and tools”. A recent development task illustrated that point starkly – skill trumps process.

Time’s a wastin ….

I was working through a weekend, exhaustively specifying the UI (mockups, WORD docs, UML State diagrams) for a recent user story, when it occurred to me that we were wasting our time.

Here is more or less the user story I was working on.

As a documentation processor, I must be able to review all of the documents in a mailbag. Upon review, I must be able to accept, or reject each of these documents.

In the time that it was taking to describe the UI to its last gory detail,  I could create a working prototype of the UI, which would be close to 80% of what the user needs.  The business folks could take the prototype for a spin, and give me feedback, which could quickly iron out the remaining 20% of the work.

See, we are building this for processors in an insurance company.   They are not looking for sophisticated, space age UI.  They just need something that is easy to understand, learn, and allows them to do the work efficiently.

Between the business analyst and me, we could have the UI squared away in a couple of weeks – a single sprint.  Add a tester if you must.

I will test every damn line of code I write anyway, before this leaves my hands.   The tester is only a second line of defense.   Even without that tester, I can get this very close to done.

So why am I specifying the UI when I can just build the thing myself?  I am having to do this because, collectively, the primary resources that are assigned to this task cannot or will not, produce an effective UI on their own.  That amazes me.  I am shaking my head as I write this.   If you have several years of experience with this problem domain, with these business analysts, with these end users, and with the same UI technology, you should be able to take the user story, fill in all the missing details, and end up at the UI.

Again, here is the user story, for reference.

As a documentation processor, I must be able to review all of the documents in a mailbag. Upon review, I must be able to accept, or reject each of these documents.

Let’s think through this.

Analysis

  • Users have to review all the documents in the mail bag.
    • This means you have to list the documents to the user
  • So how do you present a list of documents.
    • A table, where each column is some attribute of the document, and each row is a document.
  • How do you make it easy for a user to study a large list of data that is in a table?
    • Allow filtering and sorting by various attributes.
    • Break up the list into several pages, and allow the user to page
      • Or simply allow the user to scroll up and down the large list.
  • How do you help the user make changes to large amounts of data safely, and correctly?
    • You must ask the user to confirm a large change.  Give her a chance to back out.
    • You must provide the user a way to undo a change.  Mistakes will happen.
  • What attributes (columns) of the documents must be included in the list
    • Leave out the attributes of the documents that are implementation-centric, which users have no need to know.
    • Pick the attributes that are business information.  Make a guess on which of these the user might be interested in.   Changing this list after review should not be hard.

Can’t the developer do this?

Analysis

If you have been developing UI for any time at all, you should be able to do the analysis I just did, and arrive at a similar, if not the same place.

Business Info

You have been working in this domain for several years.  That means you must already have all the business information you need.

You must know the business-centric attributes that characterize the mailbag and documents.   These become the columns of your listing, and suggest what the user can sort and filter on.

Language and jargon that end-users will recognize must also be familiar to you by now.  This is where static labels, feedback messages and such will come from.

Implementation

You have been working with your UI framework for several years.  So you should know how to implement the various UI features mentioned above – a table of data, sorting, filtering, paging, scrolling.

But none of this happened

But none of this happened, and a UI designer had to be brought in to spell everything out.   Why?

The Developer

Though they were well-versed with the UI framework, the developers have little knowledge of, or interest in, what makes an effective UI.

They are happy to be told what to build.  They want to be told what to build.  When left to their own initiative earlier, they produced a UI that so defied common sense and business reality, that the end-users’ job turned into a labor-intensive, error-prone, hell.

The Tester

If the testers know the lingua franca of the business (English, in this case), if the testers know the business, and if they know the end-users, the testers can judge if the UI satisfies the business need, simply by relying on the 2 sentence user story.

Unfortunately, testers’ familiarity with the business is uneven.  They are simply kids that compare a spec to delivered software.  If the spec is incomplete, or incorrect, these testers are thrown off course.

Further, more often than not, the testing leadership subscribes to the view that testers must only work off an exhaustively detailed spec.  Applying their own knowledge of the business, their own analytical and communication skills, is considered risky. The focus on learning the business themselves is weak.

Manager

Well, managers have all the power, which makes them responsible for everything, doesn’t it?

Who are they hiring?

The UI developer does not exhibit knowledge of effective UI design.    So how did we end up hiring him?

Say the manager that is evaluating the developer does not know anything about UI design himself.   So the manager cannot determine the developer’s competence in the matter.  That is reasonable and common.   A manager is constantly confronted with problems in which he does not have direct expertise.   Yet, she must hire people that will be responsible for solving that problem.    In that situation, a manager has to be able to recognize competence (and conversely, incompetence) as a characteristic separate from concretely observable skill.   Competence has an aura, a body language, a speech pattern, a look in the eye, as does incompetence. You have to be able to smell the bullshit before you see it.

When managers neither have concrete expertise, nor do they have a nose for fakery, we end up with these half-baked developers that require to be spoon fed.

Bad drivers

Many resources are able to learn and do more if we create the right environment.  This is usually some combination of large grained carrot and stick, coupled with the pushing of buttons that we can only learn by getting to know the resource personally.

Effective UI design for the corporate world, is a skill that can be learned by just about anyone in a few weeks, or over the course of a few UI development tasks.  If a developer has worked on UI development for going on three years, and still does not have a coherent, useful view of the matter, the leadership has been asleep at the wheel.

The same argument applies to the testers.   The management enabled them to be unthinking, ‘garbage in garbage out’ type grunts.

Skill trumps process

What a business analyst and a skilled engineer can take care, is now distributed over a whole platoon – The business analyst, the UI designer, the developer, the tester, tech and test leads to oversee the grunts, managers to oversee all of this.

Where the work could simply be a conversation between two people, now is a multi-step workflow involving many more people than that.  Two people getting a task done is just work.    Eight people, each with their own inputs, and deliverables, working on narrow parts of the whole, and that with their vision constrained by blinders, is a process.

What does the process buy us?   Nothing that I can see.  I see overhead. An 8 to 10 person team requires more management and book-keeping than a 2 person team. I see a machine with more moving parts, which exponentially increases the complexity, the amount of co-ordination required, and the number of ways the process can fail.

One or two committed, skilled engineers can replace the whole process. Why not learn to identify, hire and hold on to such resources? Why the fixation on process? Do you want get work done?  Or do you want to run a process?

Software Engineers, Clerks, Baby-sitters

What kind of a software engineer am I, I often wonder.

Consider a Java developer, Tom Ws, who has worked on SOAP based web services for over a year, yet does not know how XML schema and WSDL are related.

Tom gave the front-end guy, Dick Ui, an updated WSDL. Dick then tells Tom, ok, now I need the XSD. Tom Ws thrashed about for a day, giving Dick Ui this XSD file and that, which Dick kept rejecting. Finally, Tom goes to the purported architect, Harry Bs, who, wonder of wonders, asked Dick Ui the right question. The WSDL contains all the XSDs you need, embedded within it. What on earth are you talking about? After this, the situation resolved itself fairly rapidly.  It turned out that Dick Ui was looking for the schema of JMS payloads, a related but different unit.

Engineers

There are resources, that know your domain, technologies, tools coming in.  These are few and far between. You cannot always count on finding these folks.

However, there is viable alternative.  There are resources that will not know your problem space, nor the technologies and tools that you use, but upon arrival, they are perfectly able to dig into the existing system, discover what they have to learn, and learn it themselves.

They will not have answers right away, but they know the correct questions to ask, and can find the answers with minimal hand-holding.

Clerks

They begin work at pretty much the same gate as the engineer.  There is much they do not know about the business domain, and the technical solutions of your choice.  That is where the similarity ends.

They learn nothing that you do not teach them explicitly.   They wait to be told what to learn.  Then they wait to be taught what they have to learn.    They cannot fill in any of the gaps themselves.

When they run into a roadblock, they will send out an email and are happy to wait, and wait, and wait.  You see, they believe “answers” are someone else’s responsibility.

Baby-sitters

Someone must spoon-feed the clerks.   Enter, the baby-sitter.  You know those people that say to you pityingly, “Do you still code?”.   That’s a baby-sitter.

The baby-sitter thinks that programmers are simply draftsman, translating a perfectly conceived blueprint into Java, C#, or what have you.  That writing computer code is an act of communication, which requires thought and practice to master, a baby-sitter considers a fanciful concern.   The baby-sitter believes that the coder will never have to make a consequential choice when he writes code, and actively encourages the coder to dumb himself down.

If you got rid of the clerks, you would not need baby-sitters.

Imagine

Imagine an engineering outfit that has only engineers. Imagine a development team that religiously avoids both clerks and baby-sitters.

This seems like a reasonable goal to me, especially, if you factor in the trope that a good developer is usually worth 4 or 5 mediocre developers (a case that I must learn to make one of these days). There will be human resource challenges; how to hire and keep high-skilled, and hence high-valued resources, but you have man-management challenges with low-skilled workers too.

As for me

What kind of a developer am I?

I suppose I have been around long enough to be some kind of an Engineer.

On some days, though, I am happy to be a baby-sitter.  That is all the energy I can muster. Further, some poor soul is happy that I am making his job easier, and that is not a small thing.

On other days, I dream about a rigorous development outfit that is entirely, of and by, engineers.  I would very probably bring up the caboose in a place like that, but that may not be such a bad thing.

Early error detection is paramount

Is early error detection, while developing software, really all that important?

This question has probably been asked and answered a thousand times over in the last 50 years.  Let me try to rehash the argument in my own words.

Catch the error while the cement is wet

Construction, of the brick and mortar variety, sometimes provides an apt analogy for software development, so I am going to give that a whirl.

See if you can correlate the story I lay out below, to the various stages in a software development task – DEV, QA, Bug Fixing, and the Aftermath.

Say you decide to build a house. You create some kind of design, and completely construct your house.

After the construction is all finished, and only after this, you call in an inspector to see if the construction is up to code. The inspector finds that your electrical wiring is the wrong gauge.  You must change it.

The wiring is inside the walls.  You have to tear into the walls to get to the wiring.

You have already spent a lot of money and time on the construction.  You want to move in already.  The extra expense is a burden on the pocket book, and the mind.  You are not at your patient, nor enthusiastic best.

The builder had other projects scheduled.  He wants to be done with your house yesterday. He can no longer giving his best attention to your problems.

Some of the folks that worked on this house are needed on the county commissioner’s lake side cottage. The builder brings in some temporary help to make the fixes. These are snot-nosed college kids, who don’t know many of the small, but consequential technical decisions that went into your house’s construction.  They are going to trip over these and make mistakes. Worse, these kids know they will never see you and your house after this summer.

After the wiring is changed, you notice that a couple of windows do not close well. The lights in the stairwell flicker randomly, but noticeably.  The re-painting of the walls in your guest room is not the right shade.  By this time you have no other place to live, so you suck it up, and move in.

After you move in you notice that your water heater does not work well with the new wiring.  You have to replace the water heater.   More aggravation; more time wasted; more expense; send in the plumber.

There is worse.  While monkeying with the walls and the wiring, a construction worker accidentally rammed a 100 pound sander into a load bearing beam.  It now has a crack it in.  No one notices.

Let’s see how this correlates to software development.

DEV

Say you decide to build a house. You create some kind of design, and completely construct your house.

Listen pilgrim, I just write code. I don’t test.

QA

After the construction is all finished, and only after this, you call in an inspector to see if the construction is up to code. The inspector finds that your electrical wiring is the wrong gauge. You must change it.

This happens all the time in enterprise software development. Developers do not test their code effectively. Infrastructure, which enables developers to adequately test the code they write, often does not exist. Everyone, including management, is happy to leave serious testing till after all of the code is turned in.

The bug fixing

The wiring is inside the walls.  You have to tear into the walls to get to the wiring.

The bug is buried somewhere deep in a few thousand lines of code that you blithely turned in. You go digging, make a change some place, with little knowledge of everything else that might now be affected by your change. It is hard to know, there is too much code, code that you don’t even remember exists. The bug fix is a risk.

You have already spent a lot of money and time on the construction.  You want to move in already.  The extra expense is a burden on the pocket book, and the mind.  You are not at your patient nor enthusiastic best.

The builder had other projects scheduled.  He wants to be done with your house yesterday. He is no longer giving his best attention to your problems.

I’ve seen this in just about every large project I have been part of. Developers use all of a sprint to write code and turn it in. Testing of this code happens in the next sprint, when both the stakeholders and the developers are also assigned to the development tasks scheduled for this second sprint. Nobody is able to bring their best selves to the bug fixing.

Some of the folks that worked on this house are needed on the county commissioner’s lake side cottage. The builder brings in some temporary help to make the fixes. These are snot-nosed college kids, who don’t know many of the small, but consequential technical decisions that went into your house’s construction.  This is going to trip them up, and they will make mistakes.   Worse, these kids know they will never see you nor your house after this summer.

You designed and wrote the original code. However bugs are assigned to someone else, who knows little of the business requirements, the design decisions that went into the solution, and the contours of the code base you created.

Sometimes this someone else is a consultant. And we know consultants can be a mixed blessing, don’t we?

The new and not so improved aftermath

After the wiring is changed, you notice that a couple of windows do not close well. The lights in the stairwell flicker randomly, but noticeably.  The re-painting of the walls in your guest room is not the right shade.  By this time you have no other place to live, so you suck it up, and move in.

A bug fix can fundamentally improve the solution you constructed. Or it may just be a jerry-rigged whatchamacallit that Rube Goldberg would look down his nose at. Often it is the latter, which gets you past today’s problem, and sows the seeds for several others.

But you have no choice. The show must go on.

After you move in you notice that your water heater does not work well with the new wiring.  You have to replace the water heater.   More aggravation; more time wasted; more expense; send in the plumber.

There is worse.  While monkeying with the walls and the wiring, a construction worker accidentally rammed a 100 pound sander into a load bearing beam.  It now has a crack it in.  No one notices.

Like I mentioned earlier, you often have no idea what damage you did while making your bug fix.

Lesson Learned

You want to catch the wiring issue in DEV:

  • Before a whole bunch of stuff was built around it
  • Before you build a whole bunch of stuff that depends on the error
  • While the construction crew was focused exclusively on this task
  • When the folks who made the error are available to rectify the error
  • When you have the least risk if you make another mistake

Knowing a tool vs knowing software development

Give an enterprise developer a top notch table saw, and a 500 dollar power drill.

Give that developer all the training he wants on those tools.

Ask the developer to build a chair.

His chair will come out with 4 legs of different lengths, cracks in the seat, and a couple of nails sticking out.

The developer knows how to use his fancy tools, but he does not know how to build a chair.

That is the difference between knowing how to use a tool, and knowing how to do software development.

They are two different bodies of knowledge, two different sets of skills.

By the way, that chair has business value.  If you must sit, and that chair is all you have, you will sit on that chair, carefully, and with a few choice curses.  I am willing to bet that this is how business folks view most enterprise software that they are saddled with.

Bloody-minded software development

I’ve been pre-occupied lately, with the familiar notion that ‘action‘ has its moment.  How much planning did the chicken do, before crossing the road?

I have seen two kinds of software development outfits.

One was all chaotic action, with apparently little method, yet who always managed to deliver something. Some thing went into production.   Some thing of some value was up and running.  The plan, if one can be said to exist, was often brutal but effective, like clearing a minefield by having your platoon walk across it.  Quality was an alien concept, little more than a pretty thought.

The other development shop is all talk, with little to show for it.  Good people, talented, even competent individuals, who collectively can’t seem to program their way out of a paper bag.  They have worked two, three years on something, nothing of which is in production.  The waste is heart-breaking. Some thing, some essential bloody-mindedness, is missing.

If I were a business person, I would have to pick the former team every time.

Delivery is an essential, like the food you put in front of a starving man. Quality provides long term value, with long term benefits, and requires constant application – it is putting healthy food in front of a starving man, and continuing to feed him healthy food, even after he stops starving.

 

 

Loose the debugger

Loose the debugger

My ideal development team would not use step-through debuggers.  If I am responsible for mentoring newbie programmers, my first rule would be – no step-through debuggers.  My ideal IDE would include all the editing, analysis, navigation, and refactoring features, that modern incarnations like Eclipse and IntelliJ have, but without the step-through debugger.

Does this make any sense at all?

What is a debugger used for?  It is used to understand what a piece of code is doing.  The code might be doing something wrong, aka a bug.   The debugger can help us understand how a bug came to be.  If there were no debugger, what can you do?

Well, read the code.

 

Less Code

If reading code was the only way to understand the code, wouldn’t you write less code?  You will.  This will act as a disincentive to proliferation by copy/paste.    This will be an incentive to learn to ‘not repeat yourself‘ (the DRY principle).

 

Intelligible Code

If reading code was the only way to understand the code, wouldn’t you write code that is easy to understand?   You will learn the difference between the code, and the intent of the code.  You look at code, and ask yourself, WTF, why was this code written?  That.

Is there any need for code to be a puzzle?  Here is an example.

protected <I, O> O mapIO(Class<O> clo, I in) {
   try {
       Class<?> cli = in.getClass();
       O out = clo.newInstance();

       for (Method mo : clo.getMethods()) {
           if ((mo.getName().startsWith("set")) && 
               (mo.getParameterTypes().length == 1)) {
               Class<?> pr = mo.getParameterTypes()[0];
               Method mi = null;
               Object ob = null;
               if ((BaseList.class.isAssignableFrom(pr)) || 
                   (Collection.class.isAssignableFrom(pr))) {
                   mi = null;
               } else {
                    try {
                        mi = cli.getMethod("get" + mo.getName().substring(3));
                    } catch (NoSuchMethodException e) {
                          try {
                              mi = cli.getMethod("is" + mo.getName().substring(3));
                          } catch (NoSuchMethodException e2) {
                    }
               }
               if (mi != null && pr.isAssignableFrom(mi.etReturnType())) {
                   ob = mi.invoke(in);  
               } else {
                   try {
                       ob = pr.getConstructor().newInstance();
                   } catch (NoSuchMethodException e)  {
                       ob = null;
                   }
               }
               mo.invoke(out, ob); 
           }
       }
       return out;
   }
   catch (Exception e) {
       ......
   }
}

Any idea what the above code does?   Right.  I looked at it and my eyes started to swim.   It is in fact, a decent method.  It is short, and once you decipher it, you see that it does one simple thing.  The rub, of course, is having to decipher it.  I had to spend some time digging into it, doing a little archaeology as it were, to discover the intent of the code.  So what does this code do anyway?

Given an input object, and the class of the output, instantiate, and 
initialize an output object, in the following manner.  

Scalar properties, which exist in the input object, are copied over. 

All other properties - properties that do not exist in the input object, 
and vector properties (collections), are initialized with the 
default no-arg constructor.  

That's it.  

This is the 'intent' of the code.   This is what the code is supposed to 
accomplish.  This is why the code exists.

Now, why can’t the code just say what it means?  Something like this.

protected <I, O> O prepareOutput(Class<O> outputClass, I input) {
   try {
       List<Field> propertiesToBeCopied = 
                     getMatchingScalarProperties(outputClass, input);

       List<Field> propertiesToBeInitialized = 
                     getRestOfTheProperties(outputClass, propertiesToBeCopied);

       O output = outputClass.newInstance();
       copyProperties(output, input, propertiesToBeCopied);
       initializeProperties(output, propertiesToBeInitialized);

       return output;
   }
   catch (Exception e) {
       ......
   }
}

This alternative code is definitely less efficient than the original version.  On the other hand, what this code is about, is fairly obvious.  Even if it turns out that I must optimize this code, I will have more confidence in that attempt, because I start with a better view of what the code is supposed to accomplish.

Wait, I see how we can make this more efficient, without sacrificing the clarity we are heading towards.

protected <I, O> O prepareOutput(Class<O> outputClass, I input) {
   try {

       O output = outputClass.newInstance();
       for (Field field : clo.getDeclaredFields()) {
           if (isMatchingScalarProperty(output, input, field) {
               copyProperty(output, input, field);
           else {
               initializeProperty(output, field);
           }
       }

       return out;
   } catch (Exception e) { 
      ...... 
   }

}

As a friend of mine says, whaddyathink?  Notice, this version looks a lot like the English description of the intent of the code.  I just translated English to Java.   Give me code like this, and I don’t need a step-through debugger.

This is also a good example of the oldest truth in design (or writing, for that matter) – you almost never get it right the first time.

Also, see the point Martin Fowler makes about about code that requires comments.  It is at the end of the ‘Bad Smells in Code‘ chapter, of his refactoring book.

 

What you see is what you get

Bob Martin, in his book, “Clean Code: A handbook of Agile Software Craftsmanship“, quotes Ward Cunningham’s notion of clean code – “You know you are working on clean code when each routine you read turns out to be pretty much what you expected“.

You loose the step-through debugger, you get this.

Haven’t you had to deal with a method that had some simple name like getDriversLicense, but went on to do everything from the groceries to changing your baby’s diaper, and in some obscure corner, almost as an after thought, it retrieved your driver’s license.  If the method, getDriversLicense, did just that and nothing else, you could skip reading the content of that method.

The more you are forced to read code, the more you will write methods that do one small thing, just the thing that the method’s signature suggests.

 

Developer tested

Of course that cleanly written, getDriversLicense method, could have bugs.   How do you increase your confidence in the getDriversLicense method?   As you read the code, you read a call to getDriversLicense, and say, okay, great, I know that works, and move on.  You don’t want to have to also read that method’s definition.

You know the answer.  How do you produce code that folks can implicitly trust?  You test the daylights out of the code that you deliver.   Automated developer tests.

Loose the debugger, and you will learn to hate the lack of developer testing.

 

Log your way out of trouble

Regardless of how clearly your code is written, there will be times when you will want hard evidence of what the code is doing to the data.   In the absence of a step-through debugger, you will necessarily have to rely on logging. You can understand what your code is doing by logging inputs, outputs, and execution paths, which trace the code’s work.

Any enterprise system worth its salt must have good tactical logging anyway.  Clear, and configurable logs, is useful for system maintenance, and business monitoring.

Loose the debugger, and you will be forced to nail down your application’s logging.

 

And so,

Do any of these alternatives to step-through debugging sound like a bad thing?  No.  Taken at face value, each of these alternatives, and in fact all of them together, add a lot of value, which the step-through debugger does not.

Think about it another way.

Why do you need the step-through debugger.  9 times out of 10, you need it to negotiate bad code.   If you are starting from scratch, if you do not have to deal with legacy code, stay away from the debugger.  This will force you to learn to write cleaner code.

Reading code makes you feel the pain caused by poor code.  Using a step-through debugger helps you turn a blind eye to poor code.  At its worst, the step-through debugger enables poor code.

 

A benchmark?

Say I am building a new software team, my own outfit even.   I almost think that the missing debugger can separate folks that I want to rely on, from folks that I am sort of forced to rely on.  At the minimum, I want developers that can learn to be productive without the step-through debugger.  If you cannot live without that crutch,  hmm, well, ….. I don’t know.

User experience for the techies

What do I think of when considering ‘user experience‘ for the technical folk?   What makes it easier to do their jobs?  What helps them do their jobs better?

Techies include the following sorts of resources.

  • Programmers
  • Testers
  • Dev Ops
  • Program Operators

As always, common factors that I listed in the post, User experience in an enterprise system, apply to these resources as well.

Programmers can see everything

Interestingly, it appears that programmers occupy a special place in the enterprise.   Everything, systems and data, that any corner of the enterprise sees and uses, must be accessible to some programmer or the other.  Who builds these systems?  Programmers.  Who do you call when anything goes wrong?  Programmers.   Nothing can be hidden from the programmers.

This means that the the user experience considerations that apply for everybody else in the enterprise, which I have written about in other posts, apply to programmers as well.

One thought occurs to me.   Doesn’t this kind of all-pervasive access raise privacy issues?  Not to mention security concerns?  I wonder how enterprises deal with this.

 

A Domain Specific Language (DSL)

Often, for some reason or the other, a programmer is asked to perform a business task.  The enterprise system typically supplies business users a graphical interface for this work.  Programmers can use that interface too.  However, programmers have technical skills that typical business users may not have. Further, programmers have responsibilities other than performing business tasks, which means they are looking to save as much time as possible.

Hence, if it is possible to provide programmers an alternate interface, which is more powerful, and more performant, even if more technically complex, it would be a good thing.

In some of my previous work, programmers did considerable customer support work. Often they would have to perform some activity that meant wading through pages and pages of UI, in order to make one small change, or press one button.  I heard them lamenting the lack of a more ‘expert’ kind of interface. After all, they arguably had more technical expertise than the rank and file business users.  We could have used a scripting solution. A couple of lines of a well designed DSL (domain specific language), would have put them all in a good mood, not to mention saved a lot of time, and energy.

Say that you have to change the type of roof, on the 3rd barn of the farm that is insured by farm policy, FU-237EKS. After the change, the policy must be assigned to an underwriter for review.   In the UI, the change happens on the 8th screen of the farm policy. The assignment to the underwriter is a further 3 screens down.   Rather than schelp through all that UI, some folks I knew would have liked to execute something like this script.

FU-237EKS.barns[3].roof = shingle
underwriters['nate silver'].reviews += fp237eks

However, keep in mind that it ought to be possible to design the graphical user interface so that it provides the same kind of power, and efficiency. The recent, industry-wide emphasis on usability is all about this kind of improvement.  The point here is that alternatives to GUIs (graphical user interfaces) exist, which might more naturally fit programmers’ sensibilities.

I also wonder if there might be certain kinds of business functions that are hard to represent in a GUI.  Some complex, but one-off, workflow, which has to be created on the fly, for instance.  This is a question to explore.

 

Some items related to support

  • You must be able to change the logging level that is in effect without stopping the application.
  • You must be able to add muscle to the system, without stopping anything.  Bring more servers on line, add more threads to a running server, and so on.

 

Software Configuration Management

Essentially, all of configuration management must be automated.

Check out, and check in of code; build, test, assembly, and release of an application, must be completely scriptable.  You should be able to do all of this at a click of a single button, or the issue of a single command at the command line.

In some of my previous work, even though the code base was all in one source control system, we used to have to explicitly issue about 60 check out commands. We never automated the check out. So to
create a new workspace, we would do a lot of manual work – 60 clicks of the mouse, 60 commands at the command line.

Releasing a new version of the application was a multi-step, manual process, which would require some Dev Ops person to be up at ungodly hours.

Some releases, especially emergency patches, were horrendously complex. Some poor schnook, sitting in India, used to have to painstakingly undo changes to several parts of the code base, make the release, and then restore all those changes.

Needless to say, this was error-prone. Disasters, big and small, begging to happen.  This should never be the case.

Software configuration management (sometimes referred to as build management, release management), must never be a burden to the developer.   Folks that specialize in this work (Dev Ops), must hide the complexity by automating it all away.   If you are using tools that do not lend themselves to this kind of automation, well, you are using the tools that developers cannot love.   This is infrastructure, which is meant to remove some of the drudgery from a developer’s working life.   So let us have useful, and reliable, infrastructure.

 

Testing

One of the most critical lessons of the Agile philosophy is the recognition that developers must also test.   The Agile world asks, how does a developer know he is done with a task?  The Agile world answers, he proves it with tests.  When all of his tests run successfully, the developer is done with his work.

Each developer must be able to test her work independently of other programmers.    This means that each developer must have separate sandboxes for code, and data.

Developers have their own sandboxes for code by virtue of using a 
source control system.  However, in my previous work, I often 
encountered resistance to setting up independent sandboxes for 
the data.  I never really understood this.  Why couldn't each 
developer have their own copy of the system database for instance?
Isn't this sort of thing quite inexpensive these days?

We must automate the generation, and load, of test data.

In one of my previous jobs, many tests required testers to create an
insurance policy.  These were manually entered, a laborious process,
which took significant time.   

As you can imagine, testing was not as rigorous as it could have been,
because it was just too hard to setup the data required for the test.

The system’s user interfaces must support automation.   This is necessary not only for functional testing, but more importantly, for load testing.   You have to be able to simulate many users banging on the UI.   For this to be done with any kind of rigor, you have to be able to drive the UI with scripts.  Keep that in mind when you construct the UI.

Tests must run continuously.  If you have ‘continuos integration‘ going, you have this in place.   Continuous integration is a feature of software configuration management.   Every time a change is checked into the source control system, you must automatically kick off a build of the whole system, which, by definition, includes tests.   This allows you to find errors sooner rather than later.   Continuous integration is possible only if all of your software configuration management is automated.

Finally, a replica of the production environment must be available to the developers.   Often, you run into errors that only seem to happen in production.   Give developers an environment that is identical to production, where they can test, and debug problems, without messing with the production environment itself.  Without this, you are asking developers to be brilliant, which seems like a high risk strategy.

 

Techies other than developers

So how about testers, dev ops personnel, and program operators?   These folks perform functions that have been covered above, and in earlier posts.

The section on testing applies to folks that are exclusively black box testers.   The section on configuration management applies to dev ops.   Earlier posts on graceful processes applies to program operators.

 

User experience for business employees

Business employees

Who am I referring to exactly?   After all even the IT developer who builds and maintains the enterprise system is an employee of the business.  In fact, I mean folks that are not IT employees.   I am referring to people whose primary knowledge is the business of the enterprise, and not computer related skills.

For instance, she is a certified underwriter of farm policies.  She is not expected to know SQL.  She is not expected to be able to setup CRON jobs, or put together a Lucene query, or even an advanced Google query.  She does not tune the Oracle database where her policies reside.

What does it mean for such employees to have good user experience?

 

User experience

Common characteristics

At the outset, the common characteristics, as described in these posts, apply to business folks too.

Besides these, there is a perspective that applies to business folks specifically, I believe.

No training

Business resources must really only need training, experience, and expertise in the business, and not in whatever enterprise-wide computer system that is in place.

For instance, an underwriter should be able to come into a new insurance company, and knowing no more than how to use a keyboard, mouse, and perhaps a touch screen interface, and without formal training, should be able to very quickly learn and be productive using the existing enterprise system.

Anything the business resource has to learn, she must be able to learn painlessly, by just using the system.

The interfaces that the business user encounters must be a clear, natural, and seamless representation of her knowledge of the business.   The system should guide the user down paths that are instantly familiar, and obviously correct.

The enterprise system must leave little room for mistakes.   Even when the mistakes happen, they must be caught early, and there must be little or no cost.  This is essential to facilitate experimentation, and self-learning.

Transparent

You know that the user experience is good when the enterprise system recedes into the background.

The computer system must not register in the user’s mind as an obstacle, as a challenge, or as anything at all that is above and beyond her knowledge of the business.

Granted, regardless of how convoluted a system is, once a user learns it, the system will recede into the background.  That is almost unfortunate, because that is how a lot of clunky systems come to be.

However, say you have to make a change to the system.  Or say you want to replace the system.   How much resistance do you encounter?  If the business complains about having to learn a whole new system all over again, your user experience is suspect.

To put it another way, your system’s interfaces must not add any cognitive burden, beyond that which the business expertise itself requires.

How to get there

The fundamental business

Good solution design begins with effective business analysis.  Before diving into solutions, business analysis must first describe the essential business problem.  Volere, a Requirements and Business Analysis consultancy has a good definition of such analysis, which it calls ‘systemic thinking’.  To paraphrase Volere, you want an understanding of the essence of the business, without being prejudiced by any solutions, whether digital, or the old-fashioned kinds.

In a lot of my past work, the product of business analysis included 
someone's notion of a solution too, typically a user interface 
designed by folks with knowledge of the business, and good intentions, 
but not much else.  

Folks with the expertise (in user experience design) to translate the 
essential business rules, processes, and outcomes, into a transparent 
computer solution, never got a chance to understand the business at all.  
Result, more often than not, avoidable errors, unnecessary iterations, 
and ultimately, an interface, that was not useless, but that was less 
optimal than it had to be.

These were common refrains - "They will get used to it", "This is a 
documentation issue", "This is a training issue", etc.  All telltale signs 
of user experience that has room for improvement.

Human interaction design and construction

There are folks with the expertise to take the description of the essence of the business that systemic business analysis produces, and design a system with the characteristics described above.

Much of this expertise has been codified, as guidelines, patterns, and frameworks, which a competent generalist can learn as necessary.

Here is a list of resources that must serve as our guides.

Further, design is an iterative process, which will include the following sort of cycle.

  • The human interaction designer comes up with a design.
  • The design is implemented as some kind of prototype.
  • Users use and evaluate the prototype.
  • Tweak, enhance, start over, until everyone arrives at a satisfactory destination.

As this suggests, besides the design expertise, you have to be able to repeatedly construct, deploy, review, and change these solutions quickly.

Construction skills include the following.

  • Create plain wireframes with a tool like Balsamic.
  • Create colors and images laden, HTML, and CSS mockups with tools like Dreamweaver, and Photoshop, etc.
  • Create live prototypes with RAD frameworks like Ruby on Rails, or Django (Python), or Grails, or Play with Scala etc.  In particular, my personal interest is in the Java eco-system (Grails, Play), and a pure Javascript solution (for instance, Bootstrap.js, and BackBone.js at the client, and node.js in the backend).

You have to have the infrastructure and the skills for continuous integration, and continuous release.

Part of the review capabilities must include the ability to run usability tests.

Finally, there will be times when interfaces will have to change deep into the construction of the system.  Your engineering must be such that the interface can change quickly, without adversely affecting the backend.  You never want to say to the client – “It is too late to make that UI change.  You should told us this earlier,”.