Journal Articles

CVu Journal Vol 28, #4 - September 2016 + Programming Topics + Process Topics
Browse in : All > Journals > CVu > 284 (10)
All > Topics > Programming (877)
All > Topics > Process (83)
Any of these categories - All of these categories

Note: when you create a new publication type, the articles module will automatically use the templates user-display-[publicationtype].xt and user-summary-[publicationtype].xt. If those templates do not exist when you try to preview or display a new article, you'll get this warning :-) Please place your own templates in themes/yourtheme/modules/articles . The templates will get the extension .xt there.

Title: Smarter, Not Harder

Author: Martin Moene

Date: 07 September 2016 16:15:20 +01:00 or Wed, 07 September 2016 16:15:20 +01:00

Summary: Pete Goodliffe tries to solve the right problems the right way.

Body: 

Battles are won by slaughter and manoeuvre. The greater the general, the more he contributes in manoeuvre, the less he demands in slaughter.
~ Winston Churchill

Life in the software factory can be hectic and fast-paced, with many unreasonable demands. “Make it super-elegant.” “Make it feature-rich.” “Make it bug-free.” “And make it now!” With the pressures of unrealistic deadlines and tricky coding tasks looming over your head, it can be easy to lose focus, and deliver the wrong thing, or fail to deliver at all.

There’s a trick, or is it an art, or is it simply a learned skill, to doing the right thing at the right time; to knowing how to solve the right problem; and to do as much (that is, as little) work as required to get to the right solution.

The wrong thing, the wrong way

Let me tell you a story. It’s true. A colleague, working on some UI code, needed to overlay pretty rounded arrows over his display. After he struggled to do it programmatically using the drawing primitives provided, I suggested he just overlay a graphic on the screen. That would be much easier to implement.

So off he went. He fired up Photoshop. And fiddled. And tweaked. And fiddled some more. In this, the Rolls-Royce of image composition applications, there is no quick-and-easy way to draw a rounded arrow that looks halfway decent. Presumably an experienced graphic artist could knock one up in two minutes. But after almost an hour of drawing, cutting, compositing, and rearranging, he still didn’t have a convincing rounded arrow.

He mentioned it to me in frustration as he went to make a cup of tea.

On his return, tea in hand, he found a shiny new rounded arrow image sitting on his desktop ready for use.

“How did you do that so quickly?” he asked.

“I just used the right tool,” I replied, dodging a flying mug of tea.

Photoshop should have been the right tool. It’s what most image design work is done in. But I knew that Open Office provides a handy configurable rounded arrow tool. I had drawn one in 10 seconds and sent him a screenshot. It wasn’t elegant. But it worked.

The moral?

There is a constant danger of focusing too closely on one tool, or on a singular approach to solve a problem. It’s tantalisingly easy to lose hours of effort exploring its blind alleys when there’s a simpler, more direct route to your goal.

So how can we do better?

Pick your battles

To be a productive programmer, you need to learn to work smarter rather than harder. One of the hallmarks of experienced programmers is not just their technical acumen, but how they solve problems and pick their battles.

Good programmers get things done quickly. Now, they don’t bodge things like a shoot-from-the-hip cowboy coder. They just work smart. This is not necessarily because they are more clever; they just know how to solve problems well. They have an armoury of experience to draw from that will guide them to use the correct approach. They can see lateral solutions – the application of an unusual technique that will get the job done with less hassle. They know how to chart a route around looming obstacles. They can make informed decisions about where best to invest effort.

Battle tactics

Here are some simple ideas to help you work smarter.

Reuse wisely

Don’t write a lump of code yourself when you can use an existing library, or can re-purpose code from elsewhere.

Even if you have to pay for a third-party library, it is often far more cost effective to take an off-the-shelf implementation than to write your own. And test your own. And then debug your own.

Use existing code, rather than writing your own from scratch. Employ your time on more important things.

Overcome ‘not invented here’ syndrome. Many people think that they can do a much better job themselves, or fashion a more appropriate version for their specific application. Is that really the case? Even if the other code isn’t designed exactly how you prefer, just use it. You don’t necessarily need to rewrite it if it’s working already. Make a facade around it if you must to integrate into your system.

Make it someone else’s problem

Don’t work out how to do a task yourself if someone already knows how to do it. You might like to bask in the glory of the accomplishment. You might like to learn something new. But if someone else can give you a leg up, or complete the job much faster than you, then it may be better to put the task in their work queue instead.

Only do what you have to

Consider sacrilege: Do you need to refactor? Do you need to unit test?

I’m a firm advocate of both practices, but sometimes they might not be appropriate or a worthwhile investment of your time. Yes, yes: refactoring and unit testing both bring great benefits and should never be tossed aside thoughtlessly. However, if you’re working on a small prototype, or exploring a possible functional design with some throwaway code, then you might be better off saving the theologically correct practices for later.

If you do (laudably) invest time in unit tests, consider exactly which tests to write. A stubborn ‘test every method’ approach is not sensible. (Often you’ll think you have better coverage than you expect). For example, you need not test every single getter and setter in your API. (It’s another issue whether you should have getters and setters in your APIs in the first place.) Focus your testing on usage, not methods, and pay particular attention to the places you would likely expect brittleness.

Pick your testing battles. 

Put it on a spike

If you’re presented with multiple design options and you’re not sure which solution to pick, don’t waste hours cogitating about which is best. A quick spike solution (a throw-away prototype) might generate more useful answers in minutes.

To make this work well, set a specific Pomodoro-like time window within which you will perform the spike. Stop when the time elapses. (And in true Pomodoro style, get yourself a nice hard-to-ignore windup timer to force you to stop.)

Use tools that will help you backtrack quickly (e.g., an effective version control system).

Prioritise

Prioritise your work list. Do the most important things first.

Concentrate effort on the most important things first. What is most urgent, or will produce the most value?

Be rigorous about this. Don’t get caught up on unimportant minutiae; it’s incredibly easy to do. Especially when one simple job turns out to depend on another simple job. Which depends on another simple job, which depends on.... After two hours you’ll surface from a rabbit hole and wonder why on earth you’re reconfiguring the mail server on your computer when what you wanted to do was modify a method on a container class. In computer folklore, this is referred to as yak shaving [1].

Beware of the many small tasks you do that aren’t that important; email, paperwork, phone calls – the administrivia. Instead of doing those little things throughout the day, interrupting and distracting you from your flow on important tasks, batch them together and do them at one (or a few) set times each day.

You may find it helps to write these tasks down on a small ‘to do’ list, and at a set time start processing them as quickly as possible. Ticking them off your list – the sense of accomplishment can be a motivating reward.

What’s really required?

When you are given a new task, check what’s really needed now. What does the customer actually need you to deliver?

Don’t implement the Rolls-Royce full bells-and-whistles version if it’s not necessary. Even if the work request asks for it, push back and verify what is genuinely required. To do this, you need to know the context your code lives in.

This isn’t just laziness. There is a danger in writing too much code too early. The Pareto principle [2] implies that 80% of required benefit could come from just 20% of the intended implementation. Do you really need to write the remainder of that code, or could your time be better employed elsewhere?

One thing at a time

Do one thing at a time. It’s hard to focus on more than one job at once (especially for men with our uni-tasking brains). If you try to work concurrently, you’ll do both jobs badly. Finish one job then move on to another. You’ll get both jobs completed in a shorter space of time.

Keep it small (and simple)

Keep your code and design as small and as simple as possible. Otherwise, you’ll just add a lot more code that will cost you time and effort to maintain in the future.

Remember KISS: Keep It Simple, Stupid.

You will need to change it; you can never foretell exactly what the future requirements are. Predicting the future is an incredibly inexact science. It is easier and smarter to make your code malleable to change now than it is to build in support for every possible future feature on day one.

A small, focused body of code is far easier to change than a large one.

Don’t defer and store up problems

Some things that are hard (like code integration) should not be avoided because they are hard. Many people do so; they defer these tasks to try to minimise the pain. It sounds like picking your battles, doesn’t it?

In reality, the smarter thing is to start sooner and face the pain when it is smaller. It’s easier to integrate small pieces of code early on, and then to frequently integrate the subsequent changes, than it is to work on three major features for a year and then try to stitch them together at the end.

The same goes for unit testing: write tests now, alongside your code (or before). It’ll be far harder, and less productive, to wait until the code is ‘working’ before you write the tests.

As the saying goes: If it hurts, do it more often.

Automate

Remember the classic advice: if you have to do it more than once, write a script to do it for you.

If you do something often, make the computer do it for you. Automate it with a script.

Automating a common, tedious task could save you many hours of effort. Consider also a single task that has a high degree of repetition. It might be faster to write a tool and run that once, than to do the repetitive job by hand yourself.

This automation has an added advantage: it helps others to work smarter, too. If you can run your build with one command, rather than a series of 15 complex commands and button presses, then your entire team can build more easily, and newcomers can get up to speed faster.

To aid this automation, experienced programmers will naturally pick automatable tools, even if they don’t intend to automate anything right now. Favour workflows that produce plain text, or simple structured (e.g., JSON or XML) intermediate files. Select tools that have a command-line interface as well as (or instead of) an inflexible GUI panel.

It can be hard to know whether it’s worth writing a script for a task. Obviously, if you are likely to perform a task multiple times then it’s worth considering. Unless the script is particularly hard to write, you are unlikely to waste time writing it.

Error prevention

Find errors sooner, so you don’t spend too long doing the wrong thing.

To achieve this:

Communicate

Learn to communicate better. Learn how to ask the right questions to understand unambiguously. A misunderstanding now might mean you’ll end up reworking your code later on. Or suffer delays waiting for more answers to outstanding questions.

Learn how to run productive meetings so your life is not sucked out by the demons who sit in the corners of meeting rooms.

Avoid burnout

Don’t burn yourself out working silly hours, leading people to expect unrealistic levels of work from you all the time. Make it clear if you are moving beyond the call of duty, so people learn not to expect it too often.

Healthy projects do not require reams of overtime.

Power tools

Always look out for new tools that will boost your workflow.

But don’t become a slave to finding new software. Often new software has sharp edges that could cut you. Favour tried-and-tested tools that many people have used. You can’t put a price on the collected knowledge of these tools available via Google.

Conclusion

Pick your battles. (Yeah, yeah.) Work smarter, not harder. (We’ve heard it all before.)

They are trite maxims. But they are true.

Of course, this doesn’t mean don’t work hard. Unless you want to get fired. But that’s not smart.

Questions

  1. How do you determine the right amount of testing to apply to your work? Do you rely on experience or guidelines? Look back over your last month’s work; was it really tested adequately?
  2. How good are you at prioritising your workload? How can you improve?
  3. How do you ensure you find issues as soon as possible? How many errors or re-workings have you had to perform that could have been avoided?
  4. Do you suffer from not invented here syndrome? Is everyone else’s code rubbish? Could you do better? Can you stomach incorporating other’s work in your own?
  5. If you work in a culture that values the number of hours worked over the quality of that work, how can work reconcile ‘working smart’ with not looking lazy?

References

[1] http://bit.ly/Y1J0f

[2] For many events, roughly 80% of the effects come from 20% of the causes. For more on this, see http://en.wikipedia.org/wiki/Pareto_principle

Notes: 

More fields may be available via dynamicdata ..