How to work an 8-hour day

One of the things I decided when I started working was that I was not going to be one of those guys who worked 12 hours a day for a company (if I ever become an entrepreneur, all bets are off since I’m working for myself). So far, I’ve been pretty successful, and I’ve noticed a few things that may help others. Some of these are more observations than practices.

1. Understand reality: Work Load

The first thing to realize is that the amount of work to do will always exceed the time available. This is why effective management is important. If you are being ineffectively managed, it may be difficult to force a change in some of the following areas.

Just because there is always more work to do, this is no reason to kill yourself trying to get it all done. Or even overexert yourself (except in rare instances). Don’t misunderstand: I’m not saying you have an excuse to slack. Giving all of your time and attention to your employer/projects/job is the baseline here. I am saying that just because you have a lot of work is not a valid reason to work 12 hour days.

Unless you enjoy it…in which case you’re reading the wrong article. If you’re a workaholic, sacrificing your health, family, and free time to get ahead, knock yourself out. You can stop reading now.

There are always special circumstances, though. If you operate in an environment that runs 24/7 services and Something Bad happens–well, then you need to fix it if takes you 24 hours. Hopefully, you’ll get corresponding time off in return. If it’s the last week before release of a project and a major bug comes up–get it done.

I’m talking about normal days, normal work.

If you are working 12 hour days and you don’t like it, then change. No excuses. Change the job or change jobs.

2. Don’t waste time

I knew someone who always complained about having so much work to do, working 60-70 hour weeks, always been pressured, etc. I know he did have quite a bit of pressure to do a number of things, but I eventually stopped feeling empathy for him because I constantly saw him talking to so many people (friends, not direct co-workers) during work.

If you’re so busy working long hours, why do you waste so much time? Why is it that the people who complain loudest about being overworked mostly create the situation themselves?

Don’t wander the halls looking for distractions–chances are you’ll find them.

There is a balance to strike here between enjoyable work environment, having friends, being part of a team, and actually getting things done. There is also something to be said for the difficulty of concentrating on challenging topics for a long time at a stretch. Breaks are definitely needed.

There are trade offs to everything. If you spend an hour or two every day reading blogs instead of working on your projects, you’ll pay for it in time later. If this is a trade off you’re willing to make, so be it, but make sure you understand your priorities and the consequences of your decisions.

I know someone else who used 100 words to say something when 4 would do. This made meetings long, tortuous affairs (unless strong ground-rules were created, endorsed, and enforced). Even simple questions were avoided because nobody wanted to sit there and endure a longer-than necessary answer about the history of the universe. Don’t waste people’s times, and don’t stand for people wasting yours.

Be wise, what can I say more?

3. Don’t micro-manage

The topic of micro-management is something that could take up other blog posts and books dedicated to the subject, but I just want to focus on aspects of it related to time.

This is an inverse of wasting time on trivialities. I once had another boss who spent unbelievable amounts of time responding to every trivial e-mail (and he insisted on being CC’d on every topic of course) and he also complained about working extremely long weeks. And he worked all weekend. He checked on the status of things constantly and was usually the first to spot potential problems. (There were other reasons for this, too: he was usually a main point-of-contact for customers and he had more domain knowledge of everything we were doing). He was very, very smart and usually not wrong, but he did spend a lot of time doing things that were arguably someone else’s job. We never felt invested in these aspects of work, though, because he just did them.

If you find yourself with your fingers in every aspect of your organization, you have a problem, and need to take some time out for consideration:

  • Why do you feel the need to be connected to everything going on? Is it because you have to feel in control, or do you not trust others to do a good job?
  • Do you not trust your employees? If not, why not? Do they really do a bad job?
  • If they do a bad job, why? Are they fundamentally lazy, unqualified, dumb? If so, why are they still working there? Why are you paying them and doing their job anyway?
  • Would better training help?
  • Maybe expectations aren’t clear. Instead of you picking up the slack, review the expectations you have for them and go over deficiencies. Make them responsible and give them ownership. Don’t undermine their jobs by taking it away. Check on them in the future to make sure things are improved, but don’t involve yourself day-to-day.
  • Is it necessary to involve yourself in every discussion or can you just ignore until it reaches a level you need to get into? Resist the urge to comment on things you weren’t asked about.

If nothing else, micro-management always breeds resentment.

 

4. Set boundaries

I have tried to make it clear to my bosses over the years that when I’m working on a task, I am not to be bothered on a whim. When I’m concentrating, don’t bug me. This is a somewhat loose rule for me, because it really depends on what I’m working on. However, it is more true than not.

The context switching that can happen with interruptions is dangerous for productivity. Eric Gunnerson wrote about “flow state” years ago. Flow state is a zone you get in where your brain is completely engaged–you’re firing on all cylinders, fully committed and involved–pick your metaphor. It’s hard to get into and easy to leave.

I have a nice pair of Bose QuietComfort 2 Noise Cancelling Headphones. These are essential for me now. The whole topic of listening to music while programming is a separate one, with some debate, but I find it usually beneficial. Sometimes I put them on to block sound without listening to music. This also minimizes casual interruptions. I rarely listen to music while trying to create a new solution for something–only when I’m coding something I understand.

Also make sure to enforce a work/life boundary. I have made it clear in my job that I am not be called unless it’s an emergency that needs to be fixed RIGHT NOW. I ignore IMs and e-mails (unless I’m in the mood to answer something, or it’s trivial, or I know it would make somebody happy to know the answer to). If there’s a critical problem, I’ll get a phone call.

I also communicate vacations and just how far out of reach of civilization I will be well ahead of time.

5. Limit Meetings

There is an abundance of resources out there for effective meeting management. I’m more in favor of limiting the occurrences of meetings in the first place. How well you can do this depends a lot on your organization and the projects you’re working on.

Pointless meetings are a waste of everyone’s time. They can be demoralizing, energy-sucking vortexes. Recovering from a bad meeting can take further attention away from actually getting things done.

In my case, we have mercifully few meetings–only when the entire team needs to give input, we need to brainstorm about a tricky problem, or general status updates (yearly or quarterly).

Much of what goes on in meetings can be substituted by effective individual planning, e-mail, issue tracking, or planning better in the first place.

6. Know your tasks

Spinning your wheels is death. Don’t be wasting your time unconsciously (If I’m going to waste time, I’d rather do it consciously with Desktop Tower Defense).

If you’re stuck on a task, get help, change gears, do something else. Make sure you have a process to detect when you and others are stuck so that you don’t waste time.

Always know what you’re supposed to be working on. In addition to have issue-tracking software, make sure priorities are communicated clearly and often. Once you finish something, you should know what the next task is, whether  you do it then or not. Whenever I have a problem of knowing my priorities, I ask my manager. It’s his responsibility to know and set them. I don’t have to worry about it.

There is usually a list of “nice-to-haves” that you can work on once high-priority stuff is done. Don’t let that list get lost, but track it the same way you do regular issues.

7. Effective Information Management

This means all sorts of data: e-mail, documents, data, scheduling, task lists. Simplify, automate, streamline. I won’t go into specific techniques–you can find them elsewhere.

Just a few simple points that I use:

  • Don’t read what you don’t need to
  • Don’t respond when you don’t need to
  • File away or delete ASAP

It’s easy to get buried in information these days–and consequently it’s easy to think it’s at all important. Don’t fall into that trap.

8. External Motivations

A little obvious, this one, but important to ponder. None of this will work if you don’t have strong outside motivations. You have to really enjoy being outside of work–and I don’t think the satisfaction of doing nothing is enough. You’ll get bored of that eventually. Sitting in front of a TV every night “unwinding” for three hours is not a motivational experience (quite the opposite, usually).

Hobbies, projects, sports, exercise, cooking, family, church, books, culture, service are all part of life and should be enjoyed.

I usually schedule my evenings to some degree–whether it’s working out,  moving ahead on personal programming projects, building my latest LEGO model, watching a movie with Leticia, or reading a book–I’ve got a long list of things I enjoy doing. If I don’t follow the schedule exactly, or can’t fit everything in, I don’t sweat it–as long as I’m enjoying myself, that’s what matters.

Work isn’t everything–in fact, it isn’t even the greatest part of anything. Be well-rounded.

* Exceptions

Unfortunately, not every job can be forced into a neat 8-hour work day. My wife, for example, works for a news wire service. She works 8-hour days most of the time, but quite often she ends up staying late to take care of things. Unfortunately, when your job depends so much on other people, it can be a bit hard to plan days, and it’s very possible that work comes up right when you leave, or there is too much work to fit in in a day. However, this is unsustainable in the long run. Either more efficient processes have to be introduced, the work load decreased, or more people hired.

A word or two about politeness as well: it’s difficult in some environments to enforce better behaviors without being considered rude, grouchy, or holier-than-thou. Sometimes firmness has to give way to politeness. The carrot usually works better than the stick anyway in the long term.

GetTextExtent vs. DrawText (with DT_CALCRECT)

Working on an MFC app that has just been converted to Unicode (finally!), I noticed that one button (which is created dynamically) is too small to fit the text in Korean (and Russian and a few other languages).

The code was calling something like:

CSize sz = m_btAdjustColors.GetDC()->GetTextExtent(sCaption);

It seems correct, but these script languages are throwing it for a loop–the measured size is much smaller than it should be. The GetTextExtent documentation doesn’t shed any explicit light on this subject, but may hint at it.

The solution? DrawText. There is a flag you can pass to tell it to calculate the rectangle needed instead of drawing.

CRect rect(0,0,0,0);
m_btAdjustColors.GetDC()->DrawText(sCaption, &rect, DT_CALCRECT);

It’s important to initialize the rectangle to zeroes because, as the docs say, it only modifies the right and bottom members of the rectangle.

How to catch a NetFlix thief

Via Geekologie comes the hilarious tale of a man (boy, really) caught stealing NetFlix DVDs from a mailbox. The comments are funny, too. Some seem like they’re obviously written by the neighbor.

One issue I didn’t really see addressed in the comments on the post is the overall issue of mail safety. People need to consider the seriousness of stealing mail. There’s a reason the fines for it are so severe. A reliable and trusted mail system is the foundation of a good portion of our society and its communications mechanisms.

Having lived overseas, and having had many family members live all over the world, I can personally testify to the need for a secure mail system. There are countries I would not mail a package to–it would just be a waste of money. The security of our system *HAS* to be enforced harshly or people will lose faith in it and it becomes a system of corruption and scamming. This kid got off lucky. If he were older or there were stronger evidence he were stealing more valuable items, or he were being less discriminating in what he stole, I think he could have gotten a far worse punishment.

10 Ways to Learn New Things in Development

Expanding upon one of the topics in my post about 5 Attributes of Highly Effective Developers, I’ve been thinking of various ways to kick-start learning opportunities in my career and hobbies.

1. Read books. There are tons of books about programming–probably most of them are useless, but there are many, many gems that can greatly influence your abilities.

I still find that it’s easier and faster to find information about many topics in familiar books than to find similarly valuable information online. Read all your books to get to this point.

Books are also valuable from theory, architecture, design point of view. There just aren’t that many places on the web to get high-quality, authoritative instruction in this.

Like this? Please check out my latest book, Writing High-Performance .NET Code.

2. Read Code. This is something I was late to. I didn’t start reading a lot of significant code until after I had a few years of professional programming experience. I would be a better programmer if I had started earlier. I try to read some source code every week (not related to work, not my own, etc.) from an open source project. Start with programs that you use and are interested in. I started with Paint.Net and it solidified a lot of .Net program design technique for me.

Reading other people’s code shows you different ways of doing things than you might have thought of on your own.

3. Write Code – Lots of it. Fundamentally, the best way to learn something is to do it. You can’t fully internalize something until you’ve written it. This starts with something as simple as copying the code examples from tutorials and books. That’s copying by hand, not cut&paste. There’s a difference. The idea is internalize and think, not blindly copy. Look up new API calls as you go. Tweak things.

Most importantly, develop your own projects–whether they’re simple games, participation in an open source project, or a simple plug-in to a program you use.

Try to use new technologies, new techniques, new designs–do things differently. Do things better in this project than in previous ones.

This is really the core point–if you want to be a better developer than develop.

4. Talk to other developers – about specific problems you have, as well as the latest tech news from [Apple|Microsoft|Google|Other]. This not only helps you feel part of a team or a community, but exposes you to a wide variety of different ideas.

Different types of projects require different designs, coding techniques, processes and thinking.

If you work in a small team (like I do) and you don’t have access to many other people, go find some at a local user group meeting. If nothing else, participate in online forums (you’ll have to look harder for an intelligent discussion).

5. Teach others. Similar to just reading code versus writing it, teaching other people can do wonders for forcing you to learn a topic in depth.

The very idea that you’re going to have to teach a topic to someone else should force you to learn something with a far better understanding than you might otherwise. You can face questions.

If you can’t explain a concept to a 6 year-old, you don’t fully understand it. – Albert Einstein

Teaching situations are myriad: one-on-one with your office-mate, water-cooler meetings, informal weekly gatherings, learning lunches, classrooms, seminars, and more.

How about setting up a once-a-week 30 minute informal discussion among like-minded developers? Each week, someone picks a topic they want to know more about and teaches it to the others, instigating a conversation. If you knew were going to teach the group about synchronization objects, don’t you think you’d want to understand the ins and outs of critical section implementation?

6. Listen to podcasts

If you’ve got time where your brain isn’t otherwise occupied, subscribe to podcasts. My current favorite programming-related one is .Net Rocks. They also do a video screen cast called dnrTV.

These will help you keep up on the latest and greatest technologies. You can’t learn everything and podcasts are a good way to get shallow, broad knowledge about a variety of topics, from which you can do your own deep investigations.

If there are other, high-quality developer podcasts, I’d love to hear about them.

7. Read blogs

There are more blogs than people to read them, but some are extremely well-done. I’m not even going to post links to any–there are plenty of other resources out there for that. This is one of the best ways to connect to people who actually develop the software you love and use.

8. Learn a new language

If all you’ve ever done is C(++,#)/Java there are a LOT of other ways to think about computer problems. Learning a new language will change the way you think. It’s not just a different syntax–it’s fundamentally rewiring the brain. Sure, all languages get compiled down to assembler in the end, but that doesn’t mean a high level abstraction isn’t valuable.

Functional, query, and aspect-oriented languages are starting to merge with C-based languages–are you ready?

9. Learn the anti-patterns

Aside from knowing what to do, learn what not to do. Read Dailywtf.com often and take the lessons to heart if you don’t already know.

It’s all well and good to understand proper OO design, coding style, and what you should be writing, but it’s easy to get into bad habits if you’re not careful. Learning to recognize bad ideas is vital when taking charge of a project.

Wikipedia has a thorough breakdown of many common anti-patterns,

10. Be Humble

Learning means:

  • Replacing faulty knowledge with better knowledge
  • Adding knowledge that you do not already have

There’s no way to learn until you admit you have some deficiencies. It all comes back to humility, doesn’t it? If you ever start thinking you know everything you need to, you’re in trouble. True learning is about hungrily seeking after knowledge and internalizing it. It takes lots effort. We all know this in theory, but we have to be constantly reminded.

Installed Vista SP1 – no problems

I installed Windows Vista Service Pack 1 this morning. It took about 45 minutes, two reboots, and afterward I had no problems. It never showed up in Windows Update for me so I used the standalone installer (linked to above), fully prepared to reinstall some drivers. But afterwards, no drivers seemed to have any problems–Device Manager didn’t show any issues. So all is well and good.

Technorati Tags:

How to file good bug reports (from Frank Kelly)

This is an issue I run into constantly at my job.

Frank Kelly wrote up a good summary of some items. They’re simple, easy to understand, easy to follow, even for non-programmers. 😉

In fact, I’m sending this link out to everyone in my group here at work.

Technorati Tags: ,,

Never make assumptions about performance

The importance of measuring performance changes is a topic that has been covered by others smarter and more experienced than me, but I have a recent simple tale.

I’ve simplified the code quite a bit in order to demonstrate the issue. Suppose I have a wrapper around an image (it has many more attributes):

   1: class Picture
   2: {
   3:     Image _image;
   4:     string _path;
   5: 
   6:     public Image Photo
   7:     {
   8:         get
   9:         {
  10:             if (_image==null && !string.IsNullOrEmpty(_path))
  11:             {
  12:                 _image = Bitmap.FromFile(_path);
  13:             }
  14:             return _image;
  15:         }
  16:     }
  17: 
  18: }

I had this and a view that loading about 2,700 of these into a customized ListView control at program startup. On a cold start (where none of the pictures were in the disk’s cache), it would take 27 seconds. Unacceptable.

What to do?

My first thought was to load the pictures asynchronously. I wrapped Bitmap.FromFile() into a function and called it asynchronously. When it was done, it fired an event that percolated up to the top.

Well, I spent about 30 minutes implementing that and ran it–horrible. The list showed up immediately, but it was unusable. The problem? Dumping 2,700 items into the ThreadPool queue is a problem. It doesn’t create 2,700 threads, but it causes enough problems to not be a viable option.

Asynchronicity is still the answer, though. But it’s at a different level. Instead of loading the individual images asynchronously, I skipped loading the images when creating the list control and instead launched a thread to load all the images and update them when done. The list loads in under a second, and the pictures show up little by little after that.

Measure, measure, measure. And pay attention.

Technorati Tags: ,,

6 Ways to Increase Your Confidence As You Code

One of the key requirements for being able to reliably update software is the confidence that the changes you are making are safe. The amount of confidence required increases with the complexity of the system.

In my day job I work on a real-time messaging system that can have very, very little downtime. As the service grows and sees more traffic, the amount of downtime shrinks. We start to worry now if upgrades take longer than 5 minutes. (It’s almost to the point where we’ll need redundant systems in order to do maintenance).

To upgrade this software, I have to have an awful lot of confidence in the code changes made. Sometimes that confidence varies.

What to do to gain confidence:

1. Consistent process

Having a set of rules to follow is a fundamental requirement of good software engineering. I’m not going to discuss what the process should be, but you should have one that works well.

Why is this important?

Programmers like order. We like well-defined problems where we can see the end from the beginning. We don’t like haziness, indeterminism, or too many choices.

A process nails down the unknowns–it tells you very specifically what the next thing to do is. A good process leaves no room for doubt.

A good development, testing, and deployment process is the first step to building confidence in what you’re doing.

For my messaging system example, here’s a short summary of what our upgrade process is. We didn’t just come up with it–it evolved as our business grew and the requirements grew with it.

  1. All unit and integration tests pass (we have about 2200 automated tests for this that can run in about 4 minutes)
  2. We’ve run it on staging server for a few weeks with no issues.
  3. All new features have been tested on the staging server
  4. Formal change document has been submitted and approved.
  5. Formal test results documented.
  6. Previous version backed up.
  7. Perform upgrade
  8. Monitor system (including custom automated monitoring tools)

At any point, I know where we are in the process and what needs to be done next. Sure, there may be details within these steps that require thought and creativity, but the process guides it all and makes us more confident that we’re not performing ad-hoc operations.

2. Unit Testing

There are other types of testing, but it all starts at the unit level, with simple tests that exercise your code line by line, function by function, feature by feature. I recently wrote a few thoughts about unit testing. Unit testing is where you can see the overall wellness of your code–you want that green bar!

Without unit testing, how do you know the code you’re writing is doing what it should? do you just run it and push it through its paces? This is highly inefficient for most types of code. You’ll run out of steam before you start getting close to edge cases.

The fact is that automated unit tests are a baseline for confidence in your code. You need to be able demonstrate time and again that your code performs well.

This all presupposes that you are writing good unit tests. If you’re not sure, start studying. I don’t buy the arguments about lulling developers into a false sense of security–sure, that can happen, but having good developers who understand this is a prerequisite.

If you’re not unit testing–what is your basis for confidence in your code?

3. Code Coverage

Code coverage goes hand-in-hand with unit testing as a good way to automatically discover what areas of your program are in need of more testing. I’ve found that one of the biggest barriers to unit testing a large C++ application we have is that we have no way of easily measuring test coverage. If we had time, we could definitely to the analysis ourselves, or we could spend a lot of money to get a C++ instrumentation profiler, but these are slow and very tedious to use in my experience.

In .Net, use the tools to your advantage.

The psychological benefits of seeing 75-, 90-, 95-, even 100-percent coverage are immense. You know that every line of the program has at least been touched.

Of course, most code coverage tools analyze line coverage, not path coverage. Combine  complexity analysis with code coverage to determine which functionality should probably have better testing. There are plenty of free and commercial tools that will give you cyclomatic complexity, among other metrics.

Use other analysis tools like FxCop to make sure your other ducks are in a row. It can find easy-to-overlook problems like not validating arguments of public methods, which can then lead to more unit tests and more coverage to achieve.

4. Automation

Take yourself out of the equation as much as possible. The point of a process is to be repeatable–it’s like automating yourself. Not only should unit testing be automated (thankfully, most testing frameworks handle this easily), but so should coverage and quality analyses.

What about deployment? Automate it. Documentation generation? CD master creation? Web upload? E-mail notification? Automate them all. Production builds should be invoked with a single command.

Working on boring, repeatable code? Automate it with code-gen.

The bottom line is: Don’t waste your brain cells on stuff that is highly repeatable, especially when it is prone to mistakes.

5. Code Review

Last week, a rather serious bug was discovered in some of our software (not released yet, thankfully, but close). The bug was mine, and I knew exactly what the problem was, but instead of designing a solution by myself, I brought a co-worker into the discussion just to bounce ideas off of. He had great suggestions, and made me think of things I might not necessarily have thought of on my own. We both went over the code and came to a solution that was simple and acceptable to both of us. The confidence level was much higher with this than it would have been otherwise.

This story is repeated daily by programmers throughout the world. Code review is a practice based on the simple notion that there is no one person smart enough to get it correct the first time.

Even if you’re working alone, which I often do, it pays huge dividends to regularly review your code with an eye for finding trouble. If you see any weakness at all, don’t ignore it–fix it. If you’re reviewing your own code, it’s a good idea to wait a bit after the time you wrote it. This gives your brain a chance to forget a little bit about it. Then, if you find you can’t understand it anymore, it’s either too complicated, or (if it fundamentally really is complicated) you need better comments.

Reviewing with other people has more benefit, however. Not everybody thinks the same way about problems. People have different experience, different expertise and focus, and you can’t take advantage of that if you don’t let them teach you. Even if the other people have less expertise than you, it is still beneficial (assuming they have some basic competency that they can bring to the discussion).

Once you let other people tear into your code (nicely, I hope), your confidence can be higher because you can add the confidence other people have in it (once your problems are corrected, of course!)

6. Repeatable Experiences

In the end, one of the best ways to increase your confidence in yourself, your code, and your practices is to have the evidence of repeated experiences behind you. You’re always learning, and that learning contributes to improvements in processes, testing, and your personal coding practices. Once you learn what works, especially during tricky upgrades, you can go into the next trial with increased confidence that you’re doing something right.

Have any other ideas on increasing confidence? Leave them in the comments!

Technorati Tags: ,,

Why I love LEGO

For Christmas, I got my wife a neat little townhouse. A LEGO townhouse. She loved it–until she got towards the end of the first model. There was a single piece missing. I went to LEGO’s web site and filled out a simple form. A few weeks later, I got the part and a really nice letter. Sure, it’s a form letter, but it’s still nice:

“Dear Mr. Watson,

Thank you for contacting us on 12/27/07 regarding the quality of LEGO(R) toys and products.

“We were sorry to learn of the difficulty you experienced with your LEGO set. We understand how upsetting and disappointing it can be when a product does not live up to its reputation. Please accept our apologies for the packaging error you encountered. Producing the highest quality LEGO products possible and establishing consumer trust in the LEGO brand name, are the most important goals of our Company. Certainly, whenever a packaging error does occur, we want to correct the situation as quickly as possible to restore your faith in our brand name and what it represents. Therefore, I have enclosed the item(s) you requested to complete your set.

“Please accept our apologies for the inconvenience you have experienced. If we can be of further assistance, please do not hesitate to contact Customer Service…”

And that’s why I love LEGO.

Technorati Tags: ,