Tag Archives: process

Airplane engines and teamwork

Charles Fishman has a wonderful article on a aircraft engine manufacture plant in Durham, NC. There are a lot of interesting lessons in here about teamwork, motivation, and work that make it a highly recommended read.

I’m supposed to be packing up the house and instead just read that.

Update:Jon supplied a link to a Joel Spolsky article counterpointing the above article. Now I’m going to be reading that instead of doing some chores.

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.

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: ,,

Thoughts on Process: Automation (and examples)

If a process, or part of a process, can be automated it should be. For example, in a project at work, part of our process is to make sure that every dialog present in the English resources of an MFC application is also present in all the other dialogs. We do this manually by loading each language into the app and triggering every dialog. This is tedious, time-consuming, and error-prone. Did I mention we have 12 languages?

A better way would be to have a utility that quickly parses a resource file and extracts the dialog names and compares that list to all the other languages. It could even by expanded to do a control-by-control comparison to make sure all of those were present.

At some point, of course, the dialogs have to be visually inspected for spacing issues in other languages, but for an automated check, it can find the most common errors pretty quickly.

I am a huge fan of automating processes like this. There’s no reason to waste brainpower on highly-repetitive tasks. Even if it takes me a whole day to write a tool, it’s usually worth it.

Examples of automated processes:

  • Build process – if you’re building and packaging your product manually, you’re doing it wrong. All modern environments include command-line, scriptable components. When we build our flagship product, I type “make” and ten minutes later there’s a setup.exe in a distribution folder for our team.
  • Unit testing – Unit testing suites are usually automated to some degree (you hit a button, all tests run), but it can be taken further by running them during builds or as part of a continuous integration server.
  • Documentation/Change-logs – whenever we produce a new build, we send out an e-mail to internal staff about the changes. These are usually culled from the check-in comments in subversion. It’s a manual process. It might be nice to automatically dump them to a file, which can then be edited instead of written from scratch.
  • Code checks – this can encompass almost anything, but having static analysis tools is invaluable. Like the utility that I mentioned earlier to compare resource files across all the languages we support, it can save tons of manual, “stupid” labor.
  • Loading source onto a new machine – How long does it take to get up and running on a new machine? Admittedly, you shouldn’t be switching machines all THAT often, but when you do how easy is it to grab the source and start debugging? Are all the required libraries and tools in source control and automatically configured by build scripts?
  • E-mail – If you’re like me, you get scores if not hundreds of e-mails a day. How are you organizing, sorting, responding, ignoring, deleting them? Setup filters to put them into different folders, highlight or tag them when certain keywords appear. Also, get Google Desktop Search or Windows Desktop Search. I like both of them, but I’m currently using Google’s version. I may switch back in a while.
  • Bug reporting – While not strictly about automation, I think it’s close enough. Reporting bugs and code changes in a text file is good for a while–if you’re the only one working, and you have a small number of them to deal with. Once you start involving more programmers, and perhaps a manager who wants to see some basic reports, the text file doesn’t cut it. Get a simple bug reporting tool. I use BugTracker.Net because it’s easy, simple and does exactly what we need with minimum fuss. How do I know what to work on? I open up a web page and it tells me. I’ve automated not only some manual labor, but also some needless thought processes.
  • Calendaring – Do you need to write a weekly report for your manager? Keep track of employee’s vacation schedules? Use Outlook’s (or whatever PIM you choose) task list and calendar for anything you need to remember about a specific date. Set reminders for when you need to think about them, and then forget about them.
  • Data production – if you’re in a production environment generating data that needs to be analyzed, create tools to do as much of it as possible. Of course, the tools need to be checked for correctness, but once you’re confident, do it and don’t look back.

There are many, many ways you can optimize, reduce, and automated the work you’re doing. Remember, the whole point is to get rid of the “dumb” work and let yourself concentrate on the important, creative things.

Technorati Tags: , , , , , , ,

Thoughts on Process: How much is enough

I’ve been thinking a lot about process lately, specifically how much process is enough, and how to automate things I do regularly. First of all, I think I’m lucky to work in a place that does not have a burdensome process in order to get anything done.

At its core, process is necessary because we as humans make mistakes quite easily. A process is a set of well-known, written guidelines to follow when doing a task.

I say written, though quite a few processes are mental, because if a process isn’t formalized, it’s more “This-is-how-we-do-things” than a real process. Process has to be repeatable by not only yourself, but by others.

I’m not the kind of person who really seeks after process formalization. I avoid paperwork like the plague, but even I admit that at some point you need to formalize at least something. The real question is how much process is enough. The answer is: exactly as much as you need and no more. The problem is, that amount is very difficult to find. I almost always err on the side of not adding overhead to anything until I see a clear need.

Process should not be added unless there is a clear and quantifiable benefit to the project. And I think the people who carry about the process should be the ones to judge if there is a benefit. Of course, there are exceptions, but I think for standard software projects, less is definitely more.

As an example, suppose I need bug tracking software. I find one that I like, and install it and we use it — it’s perfect for our situation. Along comes somebody else and insists that we switch to the corporate policy, even though my group does nothing like the rest of the company. It’s also a larger, more complicated program, and my group loses control of it. (If this sounds like a real situation, it almost is).

When confronted with this hypothetical, you should be asking yourselves, but what do I benefit? What does my team benefit? What does the product benefit? I do NOT ask what does the company benefit–why does that matter? If it doesn’t help our product and makes our jobs slightly more difficult, then the detriment is worse than any supposed benefit to the company as a whole. I’m sure you could argue this example both ways (for example, if support is an issue, maybe the company is right), but the point is to avoid processes and standards for the sake of themselves.

Here’s the key: Another word for process should be simplification. Having a process should simplify life, even if the actual steps are complicated. It’s the fact they’re written down, or we have automated tools, or that’s it formalized into a printed sheet of paper on a binder at our desk that simplifies it–it takes away our ability to inject mistakes. Does this make us mindless drones? For this process, yes!, but the point is that we shouldn’t be thinking about this anyway! Our minds should be hard at work creating something NEW. The process exists to make sure things go exactly as they need to, for the express purpose of freeing our minds to work on more interesting things.

A good process that I recently had to formalize was our final release build of our flagship product. After too many false starts, we realized that there were too many people, too many resources from various sources, and it was impossible to coordinate it all in someone’s mind. We needed a simple process to be signed off on. So a written checklist was created. We won’t use this for every build–just those that go to the customer. It’s simple, it works, it lets us worry about things worth worrying about.

I’ll talk about automation in another post…

Technorati Tags: , , ,

Managing Complexity – Part 2

Last time, I covered some generalities and anecdotes about minimizing complexity in my life. Today, I have a few more thoughts about complexity as it relates to software.

Software engineering has continually evolved since the inception of computer programming languages. One way of looking at that evolution is to see it in terms of improvements on complexity management. (This is a bit simplistic, since computers have simultaneously become much more complex.)

The first computers were simple by today’s standards, but the programming methodology was very complex: dials, levers, buttons, or physically connecting wires. Then machine language was developed binary code could be entered on a card, later memory, and interpreted.

These early languages required a perfect familiarity with the machine. If the machine changed, the code changed.

Over the years, the advances in languages have largely been a process of hiding the machine’s underlying complexity. ALGOL came around and hid the machine code and provided the foundation for FORTRAN and C. C built further by providing both structured programming tools and an abstraction of the machine’s language–one foot in each world.

Terminals began to have graphics capabilities and SmallTalk was developed to further hide the complexities of both growing code modules and user interface elements. Java hid the complexities of lower-level code like C and C++, and even took away the concept of a physical machine and substituted its own virtual machine, theoretically consistent across all physical platforms. C# has done much the same for Window–hiding the complexity of thousands of APIs in a hierarchical, intuitive framework of managed code.

Modern processors are beasts of infinite complexity and power compared to the early hulking iron giants, but the languages which we use hide nearly all of the complexity that our forebearers had to deal with on a daily basis.

Now it looks I’ve been really writing about abstraction. It’s extremely strongly related, but I don’t think it’s exactly the same thing. Abstraction is thinking at a higher level; minimizing complexity is thinking less.

Modern languages both abstract away lower level concerns and provide tools to minimize the complexity of things at the highest level.

There is increasingly a proliferation of visual tools, begun with GUI editors, but now including visual code designers.
Aspect-oriented programming and attributes are allowing complexity to be further minimized.

In the future, tools such as these, and increased use of COTS will become vital to accomplishing anything. Software complexity will only increase, but hopefully the trend of tools that minimize complexity will also continue.

Perhaps somebody (not me!) should investiage the theory of a total complexity quotient–a measure of the complexity of a system and the complexity of the tools to develop and manage that system. With this number we could measure if complexity overall is increasing or decreasing, and what/when is the crossover point.

Managing Complexity

Software engineers know that one of the keys to achieving development goals is effective complexity management. The single best way of managing complexity is to remove it from the system completely.

As a simple example, in an earlier version of my BRayTracer project (I really need to come up with a better name!), scene objects were edited by double-clicking on them in the tree view, which opened up a dialog window that displayed the properties of the scene object. The user could make changes and then click OK or Cancel.

This data flow introduced complexity by requiring:

  • An additional window to manage
  • Moving data between the main window and the dialog
  • Making a copy of the scene object
  • Allowing the user to cancel or undo previous actions

The functionality of being able to cancel changes necessitated most of that complexity.

While this example wasn’t overly complex, I still felt there was a better, simpler way. You can probably see a number of possible solutions:

  1. Implement a general undo system (more complexity)
  2. Don’t allow users to cancel changes–they’re committed! (possible, but wise?)
  3. Eliminate the dialog by having a child window on the main form (does not allow cancelling, but removes the additional dialog)
  4. Rethink how objects are edited from the ground up (expensive)

I went with option 3. Obviously, there’s a tradeoff here. I sacrificed some functionality for the sake of simplifying the interface and the code. In fact, in usability testing, many users wanted a way to cancel or undo changes. Someday, I’ll have to go back and add a way of doing it. This illustrates the principle that sometimes complexity is unavoidable for certain features (Undo support, for example, is nearly always very complex to implement effectively) and that often what is really going on is shifting the burden of complexity somewhere else.

Minimization of complexity is also tightly coupled to the principle of optimality (ah…but optimality of what?).


The tendency of developers (at least I assume it’s a tendency–I am, of course, generalizing from my own experience and those people I’ve observed) to minimize complexity is something that can carry over to our normal lives. I notice this myself in a number of ways, most of which probably aggravate Leticia to no end 🙂

  • When driving, I almost aways get in the “optimum” lane as soon as possible, that is, the lane from which I’ll have to make the fewest changes. Changing lanes adds to complexity. Having to worry about changing lanes when it becomes crucial adds too much complexity. While there are exceptions for painfully slow people, I change lanes only about 6 times on my 35 mile commute (4 roads and 4 highways).
  • When I cook, everything is optimized for minimal disruption. All ingredients and equipment are pregathered and then prepared in a way which minimizes work, time, and coordination.
  • When I watch movies at home, I try to optimize the experience by first queing up the movie, setting up the environment, volume, and then making popcorn. That way, once the popcorn is done we can begin watching immediately, while it’s hot. I almost can’t watch a movie without popcorn.