Search This Blog

Tech Book Face Off: Effective C++ Vs. More Effective C++

I spend most of my work time programming in C++. I learned the language nearly twenty years ago. I've even read a couple of books about it - a beginner text from way back and Bjarne Stroustrap's classic text on C++ (recommended, by the way, but it's a pretty dense read). But I've never read a book on how to write effectively in C++ using the accepted idioms and methods in common use. I picked up this pair of books to finally change that, and I really shouldn't have waited this long to do it.

Oddly enough, Effective C++ and More Effective C++ were the oldest and newest books on the list of C++ books I'd like to read, and More Effective C++ is the older one. That's because Effective C++ is on its third edition, while More Effective C++ is still on its original version. We'll see how that affects the comparison of the two books.

The books are both organized as a set of "ways to improve your programs and designs," 55 ways in Effective C++ and 35 ways in More Effective C++. That's 90 ways in total, which is more ways than I can possibly cover adequately in this review. I'll do my best to provide some interesting detail while keeping things focused.

Effective C++ front coverVS.More Effective C++ front cover

Effective C++, Third Edition

Scott Meyers does an impeccable job of describing the ins and outs of building better C++ programs in a clear and engaging way. I ate up every one of the 55 items he covers in Effective C++ as if it was C++ programming manna. The book is packed full of valuable information that every C++ programmer should know. Meyers goes into minute detail on many of the tricky and subtle design decisions and implementation methods that programmers will run into. Being aware of, or better yet, being well-versed in these idioms and practices will help you come up with much better solutions to nearly every kind of programming problem.

Such valuable information does come at a cost, though. The learning curve is quite steep. Things start off fairly easy with some basic C++ best practices and guidelines for constructors, destructors, and assignment operators. Then the difficulty starts ramping up with resource management and implementations.

By the time Meyers is discussing inheritance and object-oriented design practices, the details of the design considerations are getting pretty hairy. Then the chapter on template programming takes another big step up in difficulty. Luckily, as the difficulty goes up, the likelihood that you're ever going to use the concept goes down because the concepts get further away from the common solutions to everyday problems. Of course, that means you'll have to look it up when you need it, because you're probably not going to remember the details.

One thing that struck me as I got deeper into this book is how ugly C++ really is. It is a truly flexible language that allows you to have control of almost every aspect of the code that makes up your programs, but that means that if you want it to perform correctly, you have to maintain control of every aspect of the code that makes up your program. You have to constantly think about a staggering number of details and diligently write code for the specific conditions that apply to each parameter, variable, function, and class.

For example, Item 31 of the book goes into detail on the pimpl idiom, which means "pointer to implementation," and how it improves compilation by reducing dependencies. This idiom is referred to in numerous other places in the book, so it leaves the impression that it's an important practice, especially when creating large systems with long compile times. What the idiom does is manually emulate something most other popular languages, Java and C# included, do by default, and that is to handle all objects as references.

The pimpl idiom is implemented by creating a class with the full interface that is required, and then include one pointer (preferably a smart pointer) to the implementation class as a data member. The implementation class contains the actual data members that are needed for the class, and a complete duplication of the interface. The interface class methods then simply exist to call the corresponding implementation class methods through the smart pointer. I am not kidding.

If you don't use this idiom in C++, you'll have a mess of dependencies that generally results in having to compile the world every time you make a change anywhere. That is generally okay for small systems, but it's a big problem for large systems. To do the right thing and correctly decouple interfaces and implementations, you have to write a crap-load of extra boilerplate code. Like I said, this is ugly, but that's C++ for you.

Templates are another example of C++ complexity, except they take it to a whole new level. Templates exist partially to emulate the relaxed type system of dynamic languages, but the code is compiled instead of interpreted. With templates, you don't have to rewrite the same logic over and over again for different data types, but the amount of complexity involved in coding this way is astounding. The issues that you must keep in mind are fascinating, but in the end you have to ask yourself, what problem am I really trying to solve here? Taken to the extreme, all of the template programming items would result in a massive code base that implements features of dynamic languages in a hideous way. It reminds me of Greenspun's tenth rule:
Any sufficiently complicated C or Fortran program contains an ad hoc, informally-specified, bug-ridden, slow implementation of half of Common Lisp.
If you need the features of a dynamic language, why not use a dynamic language? You can call tightly written C/C++ programs for those parts of the program that need to be really fast.

Taken as a whole, this book has some definite issues with YAGNI. If you do most if this stuff, most of the time, you're probably not being very efficient. These practices should be used when they're needed, not before. Otherwise, how could you ever make any real progress? At the same time, you need to be more than aware of these idioms to use them when needed; you need to be well-practiced in them.

Regardless of the YAGNI issues, this book is a gold mine of good C++ practices that will help you write correct, robust programs, and Meyers does an excellent job covering all of the intricate details in a clear, logical way. I highly recommend reading it; just don't try using all of the advice all of the time or you'll never make progress with your programs again.

More Effective C++

More Effective C++ has a very similar style and structure to that of Effective C++, as they are written by the same author. What surprised me about this book was the amount of overlap that it had with Effective C++. About half of the 35 items were redundant with material in the other book. It seems that during the two revisions of the first book, much of the best material of the second book was included in it, making about half of the second book irrelevant.

Of the remaining items, about half of them were outdated, covering topics that have been superseded by new language features, additions to the standard library, or better programming practices. The book was written at a time when C++ was changing significantly, and most compiler vendors were not yet supporting all of the features of the language, so Meyers covered a fair number of workarounds that are no longer necessary. Interestingly, I first learned C++ a couple years after this book was published. At the time, I was an ignorant high school student. I had no idea how much C++ was in flux at the time, and I missed out on all the fun of worrying about compiler incompatibilities and unimplemented features.

There were a few gems to be found, like this one when Meyers was talking about the 80/20 rule of performance optimization:
The way most people locate bottlenecks is to guess. Using experience, intuition, tarot cards and Ouiji boards, rumors or worse, developer after developer solemnly proclaims that a program's efficiency problems can be traced to network delays, improperly tuned memory allocators, compilers that don't optimize aggressively enough, or some bonehead manager's refusal to permit assembly language for crucial inner loops. Such assessments are generally delivered with a condescending sneer, and usually both the sneerers and their prognostications are flat-out wrong.
I couldn't agree more. A lot of programmers tend to substitute urban legends and vague incantations for precise measurement when doing optimizations, and they would be much more effective at targeting code that needs improvement if they would just pull out the stop watch and profiler to benchmark the program.

The set of items on code efficiency were generally a good review of optimizing algorithms in different contexts. Meyers didn't shy away from giving contradicting advice because the best optimization depends on the behavior of the inputs and the expectation of the outputs for any given piece of code. The same optimization does not apply everywhere, so what is exactly the right approach in one case may by exactly the wrong approach in another. Good programmers understand when to use different approaches and know a wide variety of them.

One topic that I could not agree with was Item 32: Program in the future tense. Most of the explanation for this item flies in the face of YAGNI. Here's a representative quote:
To program in the future tense is to accept that things will change and to be prepared for it. It is to recognize that new functions will be added to libraries, that new overloadings will occur, and to watch for the potentially ambiguous function calls that might result. It is to acknowledge that new classes will be added to hierarchies, that present-day derived classes may be tomorrow's base classes, and to prepare for that possibility. It is to accept that new applications will be written, that functions will be called in new contexts, and to write those functions so they continue to perform correctly.
If you spend the time that you would need to predict all of those things about the functions and classes that you write, you are wasting a ridiculous amount of time designing and implementing stuff that may never be used. Software is flexible and malleable. That's why it's called software. Sure it would be nice to design for every contingency, but at what cost? If your design is clear and your code is clean, you should be able to change it and add to it the things that are necessary when they become necessary.

If you are trying to save programmers from themselves by making your code future-proof, you are on a fool's errand. For one, this is an insurmountable task, and for two, programmers are very adept at shooting themselves in the foot and passing on the blame. Your attempts to make the design work for their future needs will likely be futile. They need to stumble and learn; that can't be prevented.

I think there's some amount of hindsight bias underlying this advice. Every programmer has been in situations where they're trying to add features or optimize code, and they get buried in unwanted complexity. The natural response is to think that if only the original programmer had designed the system some other way, making this change would be so easy, but now I have to make all of these other changes, tear up this code, and rewrite this algorithm; and holy cow, this is so much work!

Think about that. The basic thought process is, if only the original programmer could have predicted what you need to do now, you wouldn't have to do all of this work. Your job would be easy because it would have been prepared in advance. I would posit that designing and implementing software for every possible future feature and performance requirement is infinitely more work. That's what it would take to never have to rewrite sections of a program or dismantle and reassemble an architecture to add new features. Let's face it, unforeseen requirements are going to happen, and a simple, clean code base is much easier to adapt in those situations than the monstrous edifice of code that would result from overzealous contingency planning.

This assessment may not be completely fair to Meyers because he probably doesn't mean for his advice to be taken to such an extreme, but I can easily see people interpreting it that way. The broad application of all of the items in these books would certainly lead in that direction, and there are plenty of programmers that would naively go down that path. Later in the topic, Meyers dialed things back a bit to something I could definitely agree with:
Design your code so that when changes are necessary, the impact is localized. Encapsulate as much as you can; make implementation details private.
That is sound advice, and much more focused and realistic than advocating the design of future-proof software. Really, most of the advice in More Effective C++ is sound and logical, if kept in context and used when necessary. The main problem with this book today is that it's mostly outdated and redundant with Effective C++, so it isn't terribly useful anymore.

The Bottom Line

From my disagreement with Meyers' advice on programming in the future tense, you may think that Effective C++ and More Effective C++ were overflowing with unnecessary complexity, but that is definitely not the case. I very much enjoyed reading them, and the advice on proper C++ coding style and the correct use of idioms was almost all excellent, well presented, and worthwhile. The trick is to know when and in which contexts it is most appropriate to use each piece of advice, and that knowledge will only come with time, experience, and experimentation.

Meyers does a remarkable job of exposing and examining C++, with all of its faults, traps, and complexity. He shows the way to tame the beast, and every C++ programmer should know the idioms and practices that he covers in Effective C++. Since More Effective C++ hasn't been updated and covers a lot of the same ground as Effective C++, it's probably not worth a read. But definitely give Effective C++ a look. It will open your eyes to a much bigger C++ world, and it will dramatically improve your understanding of good C++ programming.

The Essence of Programming

Why do I love programming so much? I mean, I get an unreasonable amount of satisfaction out of getting a program working well and making sure it's clearly written and well organized. I've always been attracted to programming, and the more I learn about it, the more I want to learn and the more I want to improve.

I'll happily sit in front of a computer for hours trying to describe the best algorithm for solving some tedious problem in an esoteric syntax that barely resembles human language, and it only resembles normal language because it uses a smattering of English words. Why is that? What is it about programming that makes it so enjoyable, and dare I say, fun? Here are the best reasons I can think of, and they make up what I consider to be the essence of programming.

Creative Problem Solving

Every programming problem is a new challenge to wrap your head around and solve. Even if it's something you've done before, there will be parts of it that create new issues for you to deal with. You'll be implementing something in a new context, or you'll have to scale it up for massive throughput or millions of users or incredibly low power. Those issues require creativity to overcome.

Any programming you do is inherently new, at least to you, because otherwise you would be using software that you already built. In many cases the problem you're trying to solve is new to a lot more people than you. Otherwise, someone would have already solved it, and you would be using their software instead of writing your own. As you're solving these new problems, you're also learning. You're learning about the problem domain. You're learning about the requirements and constraints. You're learning how best to solve the problem at hand.

This whole process involves so much creativity. Design rules and coding guidelines are all well and good, but they will never be enough to address every situation or produce solutions for any of the more interesting problems. Programming is first and foremost a creative process, and the more knowledge you have, the more associations you can make to come up with novel solutions to these hard problems.

Expression of Ideas

It's not enough for a solution to be creative if it's incomprehensible. It took me a while to understand this, but good programming is as much about good writing as it is about creative problem solving. I used to think that if the code was well formatted and did what it was supposed to, that was enough, but programming is so much deeper than that.

There is an elegance to good code that goes beyond merely telling the computer how to do something. If that was all there was to it, we would still be writing in machine language. No, well-written code clearly expresses the ideas and intent of the solution so that it can be immediately understandable to other programmers, including your future self. When it's done well, it exists at a much higher level than a list of executable instructions.

Expressing ideas well in code is incredibly hard. It's as hard as it is to clearly express ideas in writing, and both take a lifetime to master. If you continue to work at it, it's possible to improve at this aspect of programming for your entire life.

Empathy for Others

If the software you're making will be used by other people, empathy is a necessary ingredient for a successful product. If you can put yourself in your customer's place and really feel the pain and frustration she has for the way things are, then you are much more well equipped to help make her life better.

Software interfaces can be terribly complex or refreshingly simple. They can be maddeningly inconsistent or pleasantly well-thought out. The better you are at imagining your target audience, the knowledge they already have before using your software, and the needs and desires they have to get stuff done, the better you will be able to design software that they will love.

Making something that people appreciate and depend on is incredibly satisfying. To do that, you need to know their motivations, and for that, you need empathy.

Analytical Thinking

Another fundamental part of programming is thinking about problems analytically. Going off of your creative instincts is not good enough. Creativity can generate the ideas you need to find your goal, but cold, hard analysis will be the compass that keeps you pointed in the right direction and the marker that lets you know when you get there.

Knowing what's important to pay attention to, being able to take good measurements, and interpreting results correctly are all critically important to developing performant software. Analytical thinking is all about developing good judgement and applying it when and where it matters most. It's a skill that can mean the difference between wasting weeks or months messing around with irrelevant optimizations and quickly ascertaining the bottlenecks in your software and eliminating them.

Elimination of Tedium

If there's anything that software does well, it's automating away tedious tasks. Think about the software that you need the most, the programs that you use every day. Imagine what you would have to do by hand to reproduce what they do for you, and you can appreciate the sheer amount of error-prone tedium that software has eliminated from your life.

Having an intense desire to remove other tedious tasks from your life gives you a great ability to imagine new software to do just that. You can even use programming to eliminate tedious programming tasks, and in fact, a lot of software is created by programmers for programmers to streamline programming as much as possible. And programming can go well beyond that, removing all kinds of tedium from your life when you have the motivation to create the software to do it.

Any of these things - creative problem solving, the expression of ideas, empathy, analytical thinking, and automation - apply to any number of human endeavors, but taken together, they are the essence of programming. They also encompass the reasons why I love programming. Where else could I engage in something so practical, rational, and creative all at the same time? I can't imagine anything else I'd rather be doing right now.

Technology and Everyday Life

How has technology really changed your life? That's a question that's generally overlooked. We take for granted that technology is advancing at an ever increasing rate, that we're inventing new and fascinating things so quickly now that we are overwhelming ourselves with technology. We ask questions like how are we going to cope if this continues, or what unforeseen consequences will we inflict on humanity with technology that runs out of control? We rarely take a step back and assess what is changing about our everyday lives with this new technology, and if that change is truly profound or merely incremental, so let's do that now.

You can look at the effects of any given technology across any number of dimensions. We'll look at only a few. First, a technology could make a real difference in your life personally, or it could make a major difference in the world, or some section of the world where it is used. Sometimes these effects overlap, sometimes they don't, and sometimes they are in major conflict.

For example, the widespread adoption of indoor plumbing from the late 1800s to the early 1900s not only allowed you to go to the bathroom in the comfort of your own home, but it also led to significant improvements in public health and sanitation. On the other hand, many small household appliances are a great personal convenience in the home, but they have a much weaker effect on the population as a whole. Then there are inventions like the printing press that had incredible effects on our civilization, but if you were a scholar that did transcription for a living, you were suddenly out of a job. Not everyone benefits from every technological advancement.

Another way to look at technological change is how drastically it affects your life. Does it change your life the way marriage does, or the way having children does? Marriage is more or less a change in degree, whereas having children is most certainly a change in kind. I'm not talking at all about the values or emotional issues of marriage or parenting here. This is purely an examination of how these things affect your life on a practical level.

With marriage, you were already spending plenty of time with your spouse before getting married and presumably enjoying it. You were sharing more and more of your things, your finances, and your life with your spouse before marriage, and by getting married you're committing to doing that for the rest of your life. Things don't change appreciably between the day before the wedding and the day after, but the bond between you and your spouse is stronger and will likely continue to get stronger over time.

Having a baby is an entirely different animal. The day after the baby arrives is completely and utterly different than the day before, and your life will never be the same again. You'll be doing all kinds of things that you've never done before, and you'll have to give up some things that you always used to do. Things that you used to do without a second thought are no longer easy, like leaving the house, going to the bathroom, or, you know, sleeping. You are now responsible for another person that is totally dependent on you for everything. That changes your life in rather significant ways.

Similarly, there are technologies that will change your life, and then there are technologies that will change your life. Some technologies are evolutionary, like marriage, while others are revolutionary, like having kids. Moving from black and white to color television would be an example of the former, while the creation of the internet would be an example of the latter.

So getting back to the question at hand, what are some current examples of technologies that have significantly changed our lives, say, in the last decade? That is actually a more difficult question to answer than it would at first appear. Most technology writing focuses on general changes to our society in response to technology in the aggregate, but the more interesting issue is what those changes are on a personal, individual level.

How has technology changed your everyday life? What do you do differently now than you used to because of new technology? That is a question everyone needs to answer for themselves, and an important one, because the answers may prompt you to reevaluate the technologies you're using and why they really matter to you. You can't possibly make use of every new technology out there. There's not enough time in the day to use a smart phone, a tablet, an ultrabook, a half dozen cloud storage services, facebook, Twitter, Evernote, Snapchat, Instagram, Pinterest, and who knows how many other social media and productivity apps that are out there, and still be an effective, productive, balanced human being.

Everyone is making choices from this smorgasbord of technology, so different technologies are going to affect different people to different degrees. In my case, I have both an iPod Touch and a Kindle. The iPod hasn't changed my daily life much at all. I plug it into my car to listen to my music library, but I could have just as easily used a flash drive for that. I occasionally use it to read for a bit if I'm waiting somewhere, but if I didn't have the iPod, I probably would have taken my Kindle. I've played a couple games on it, but that's hardly been life-changing.

On the other hand, the Kindle has completely changed the way I read, and I read a lot. I now have an incomprehensibly large library of books constantly at my fingertips. I can download technical books and read them on a device that's a fraction of the size, weight, and price of the dead-tree alternative. And that's comparing the Kindle to a single book, when an entire library is available. I can bookmark, highlight, and take notes directly on what I'm reading and save it all to the cloud so that it's available wherever and whenever I need to reference it. Even if I don't have the Kindle with me, I can access everything through Amazon's cloud reader. The Kindle has dramatically changed a significant part of my life.

Let's look at another major technology - smart phones. I don't even own one. I share an old clam-shell phone with my wife, and I use it for actual phone calls, mostly with my wife. (It lasts for more than a week on a charge, and it's the original battery!) The iPod touch covers the other functionality of a smart phone, but as I said, I don't use it much. I don't travel a lot, so I'm almost always near an internet connected computer, and I can work so much faster with a keyboard and mouse than a touch interface, so I have no real need for a smart phone. I've yet to find a killer app that would dramatically improve some aspect of my life if I had one. I can only see it being degraded by constant interruptions for my attention when it would be better spent on the people I'm with.

Expanding out from hand-held devices, the Nissan Leaf has radically changed my driving experience. Driving an electric car is so much more comfortable and fun than a gas-powered car, I can't see myself ever going back. The fuel is radically cheaper, and the convenience of not having to go to the gas station for a fill-up ever is a real game-changer. I can only imagine what things will be like when affordable EVs have a 300+ mile range and a widespread charging infrastructure, but the Leaf has already had a major positive impact on my daily life.

These are all recently available technologies that have had either a large or a small effect on my life. Other people's experiences will certainly be different. Obviously, smart phones have changed many people's lives in countless ways, and a lot of people can't imagine life without them anymore. Conversely, many people couldn't care less about the Kindle or the Leaf because they have different needs and priorities than I do.

We each have a set of priorities in our lives that we spend our time, money, and effort on. For some priorities we'd like to devote more of these things; for others we'd like to devote less. And of course, we'd like to make each of them more enjoyable. Here's one way to break down that list of priorities, in no particular order:
  • Basic needs like eating, sleeping, shelter, and clothing
  • Health and exercise
  • Transportation
  • Communication
  • Work
  • Leisure, including entertainment, recreation, and socializing
I wanted to also add energy consumption, but it's really separate from this list and underlies every one of these items. Energy drives advances in technology, and every time we've had significant advances in energy production, resulting in cheaper and more widely available forms of energy, we've made tremendous strides in technologies that affect all of the aspects of our lives on this list. If solar and wind power and battery storage technology advance enough to become the next cheaper form of energy, we can expect that to propel us forward yet again.

The internet is another technology that has and will continue to affect all aspects of our lives, some more noticeable than others. You could say that smart phones have a similar reach, but they're really a subset of the larger internet of all devices. The internet wasn't a single, distinct technology, but a vast platform that is continuously evolving and enables all kinds of other technologies to be developed on top of it. Different people can use different parts of that platform and derive benefits from it that are tailored to their own priorities.

If I look at the technologies that have changed my life the most, they affect areas that had the most potential for improvement. My basic needs, health, exercise, and communication are pretty well taken care of, and I don't see much need to improve them with new technology. Transportation is another story, though. I hate commuting, and the Leaf dramatically improved my daily commute. As for work and leisure, as far as I'm concerned, there's always room for improvement in both of these areas, and the Kindle proved to be one technology that made some major improvements there.

I used to buy into the whole technology overload hype, but more and more I'm realizing that the every increasing pace of technological advancement isn't that important at a personal level. What matters is which areas of your life you want to improve the most, and which technologies will have the biggest positive effect on those areas. Look for the technologies that are going to revolutionize your major problem areas, and skip the rest. The pace of technology will seem much less overwhelming, and you'll have more time to enjoy your life.

Tech Book Face Off: Rework Vs. The Silicon Valley Way

While reading blogs can be quite enjoyable and a great way to get bite-sized chunks of information when you have five minutes here or there, I still greatly prefer reading books. Books package up information in a nice, cohesive narrative in a way that blogs never could. The additional work that goes into organizing thoughts and culling superfluous stuff in a well-written book is worth the extra time that's put into writing it as well as reading it. Books have always been my primary resource when learning something new, and they have always served me well.

What does that have to do with today's Tech Book Face Off? Well, Rework is an edited collection of the founders of Basecamp's (formerly 37signals) best posts from their Signal v. Noise blog. Having these posts curated and presented in book form resulted in a very pleasant experience, but I'll get to that in a second. For something to compare to Rework, I selected The Silicon Valley Way as an opposing viewpoint on starting a business. Both books are very quick reads. You should be able to get through them in a few hours each.

Learn Ruby on Rails front coverVS.Crafting Rails 4 Applications front cover


The founders of Basecamp, Jason Fried and David Heinemeier Hansson, seem to be a lightning rod for strong emotions in the software industry. They have strong opinions, and they're not afraid to voice them loudly. Most people either love them or hate them. Let's just say I don't hate them.

Their book is much like their blog: a fast paced series of short, opinionated recommendations on how to run a good business. They don't spend much time on any one idea, and their critiques are sharp, focused, and clear. Some of their ideas are common sense, some are counter-intuitive, and some are intentionally confrontational.

You may balk at suggestions like "Underdo your competition" or "Planning is guessing," but they do have a point. And if you're willing to consider what they say, they will certainly get you thinking. I didn't agree with everything in the book, or their blog for that matter, but even the opinions I disagreed with taught me something. Their writing was so unabashedly direct that I could immediately see why I disagreed with them and how I thought differently.

I never felt pushed to take on their views. Jason and David built a successful business in a certain way, and they're presenting that method of building a business as-is. They don't spend time proving out their ideas with studies and references. You can take it or leave it, and they respect their readers enough to make up their own minds about what they're saying. I really appreciated that no-nonsense attitude.

Most of the time I found myself agreeing with them wholeheartedly. Their bit on "Go to sleep" was especially good. They strongly recommend getting good sleep over pulling all-nighters because the later is almost entirely counter-productive. In addition to making you stubborn, depressed, and irritable, it kills your creativity:
What distinguishes people who are ten times more effective than the norm is not that they work ten times as hard; it's that they use their creativity to come up with solutions that require one-tenth of the effort. Without sleep, you stop coming up with those one-tenth solutions.
It's easy to forget when you're working under a critical deadline, but sometimes the best thing you can do is take a break and get some sleep. If you allow your brain to rest, it will likely come up with one of those one-tenth solutions for you that will relieve most of the pressure you were trying to take head-on.

Most of the book was exactly like that - short, specific, relevant advice for being your best and building a successful business. Keep things simple, especially your products. Focus on your customers, help them do awesome things, and they'll love you for it. Stop wasting time doing things that don't matter. It was great stuff in an easily digestible package that's well worth reviewing every so often. And since it's such a quick read - only a few hours cover-to-cover - I'll probably look through it once a year. I highly recommend it for clearing your mind and reminding yourself of what's really important.

The Silicon Valley Way

The Silicon Valley Way was not nearly as interesting as Rework. It's organized into nine chapters on various topics about running a start-up company such as market research and strategy, competition, product definition, customers, and accepting reality. It starts with a discussion of Venture Capitalists' expectations and ends with a discussion on raising money, which is appropriate for a book about start-ups. One of the main concerns in start-ups ends up being how to get and keep getting VC funding.

Each chapter is a series of questions with a short discussion of how to go about answering it and a short example from a real company like Apple or Microsoft or a fake company that the author made up. This is where I pretty much lost interest. I couldn't get into the examples at all. The real examples were trivial and forgettable, like the issues with handwriting recognition not working well in the Apple Newton. This was given as a reason to test out product prototypes with real potential customers. It could have been any unsuccessful product from any company for all the impact it had on driving the point home.

The examples with fictitious companies were even worse. They all seemed contrived, as if the author was pontificating on something that should be obvious. If you just imagine there's this company that did things this particular way, and then this unfortunate thing happened or this great thing happened... There, you see? That proves my point. There was no meat to the argument, no main entree, just an unsatisfying salad of made up rationalizations. It was hardly convincing.

It's not as if I disagreed with most of the advice. It was mostly fine and prudent. I just couldn't bring myself to care about what the author was saying. I was ambivalent. Even for the points I disagreed with, I couldn't get too worked up about it. For example, in the chapter on competition there is a discussion on assessing labor costs of competing products:
Yet by observing your competitors at trade shows, reading their annual reports, visiting their facilities, and counting cars in their parking lots, you can obtain a surprisingly complete picture of how many people were needed to develop, market, and sell a particular product. If you are large enough to have a finance department, ask someone there to calculate your competitor's labor costs. Use this data to benchmark your competitiveness.
All I could think of was, what a waste of time and resources. That effort would be much better spent improving your own products rather than worrying about your competitor's products.

Later, in the chapter on products, the author suggests making a list of key product features and considering competing products to help fill out the list. Maybe, but paying too much attention to the competition will put you at risk of imitating them too closely. It's like when you're riding a bike near the edge of a road. You don't want to look off the edge of the shoulder, because you're going to veer in the direction you're looking. Look where you want to go, down the road, and go that way. Presumably you want to pass right by your competition, so don't watch them too closely or you'll end up in the ditch with them.

Overall, I didn't feel like I finished this book with any more knowledge or insight than when I started it. Really, Paul Graham's essays give much more depth and detail on the start-up world in a much more engaging way than Elton Sherwin does with The Silicon Valley Way. I would forgo this book and read Graham's writing instead.

Opposing Viewpoints

I have yet to address the opposing viewpoints of these two books directly. Both of them tend to agree that products should be kept simple and you should focus on your customers, but that's pretty much where the similarities end.  

Rework takes the stance that a business is best grown organically while staying profitable and developing a healthy, enriching company culture. Things like raising money, advertising, meetings, and worrying about the competition are seen as a waste of effort at best and counter-productive at worst. Especially for software companies, you don't need a lot of money or a lot of employees to get started. Building a high-quality product and selling it to a market that you can easily grow is a good way to take a lot of risk out of starting a company, and it can be done today on a lower budget than ever before.

The Silicon Valley Way takes the opposite approach, and assumes you want to take on a fast-moving industry with large, established companies. To compete, you'll want to get as much outside funding as you can, staff up your company, and concentrate on making a product that attracts a lot of users. Once you're more established, you can figure out how to monetize your product to start making revenue, and hopefully a profit. In this case, a significant amount of your time will be spent attracting investors and getting enough cash to fund your quickly growing company.

Both viewpoints are valid, in that using either method can result in a successful business. There are plenty of examples out there of profitable businesses that bootstrapped their way to success the Rework way and that rocketed their way to huge corporate status The Silicon Valley Way. There are also examples of companies that failed using either approach, sometimes spectacularly. I would imagine that slow, controlled growth would involve a lot less risk and a lot more sanity than fast start-up growth, but the payoff if your start-up succeeds is potentially much, much greater. It's a choice each set of founders has to make for themselves.

As for the books, Rework was clear, engaging, and direct. It was a great read, and it has something in it for everyone, even those people running start-ups. The Silicon Valley Way, on the other hand, was largely forgettable. It never grabbed my attention and lacked the forceful arguments of Rework. I'd pass on it and look for something better on how to run a start-up. If you're looking for a refreshing, no-nonsense guide on how to start and run a business without all of the cruft and waste of today's corporate bureaucracy, Rework is for you.

When RTFM Fails

I'm sure we all know what RTFM means, and it's generally good, if rude, advice. I follow it as best I can, especially with the work I'm currently doing as an embedded programmer. Programming embedded processors involves an awful lot of bit banging on multitudes of registers with esoteric names like UCA0STAT or TACCR2. You couldn't possible remember the meanings of them all for more than 30 seconds. Keeping the manual close at hand and referring to it frequently is essential.

Most of the microprocessors I've worked with have had fairly decent manuals. They're well organized and clear for the most part. It's not terribly engrossing reading, of course, but they get the job done. I recently had to do some development for an Altera FPGA, so I was designing hardware logic instead of embedded software programs, and the experience with the documentation was entirely different.

Altera has mountains of documentation on their products and development environment. Their flagship Quartus II software alone has a three-volume PDF manual that totals nearly 2,500 pages. They have dozens of other manuals covering their NIOS embedded processor, Qsys system builder, and the host of other products and software they provide for developing on FPGAs. That doesn't even account for the FPGA-specific documentation they have. On top of all of this documentation, they have oodles of online training courses because now that they have this massive edifice of documentation, no one wants to read it.

You would think with this amount of documentation, I would be able to find anything I needed to for completing my design. Maybe it wouldn't be easy or fast to find it, but the information should exist somewhere in all of that material. I'm not so sure that it does.

So what did I need to know for my design? It was a very simple design for a MAX II CPLD, one of Altera's smaller devices. The design ended up being a scant 65 lines of Verilog code, including blank lines and a couple comments. I've done plenty of hardware design before, so this should not have been difficult, but I needed to know three basic things that were specific to this Altera device to get my design working.
  1. I needed to know how to get a clock into the design because I needed to use a few 16-bit registers that require a clock.
  2. Additionally, those registers needed to be reset at power-on so that they would be in a known state.
  3. I needed to know how to connect all of the I/O signals to physical device pins.
I wanted to do all of these things only using a single Verilog file. It would have been a waste to create a top level schematic and a symbol for a single Verilog file, and I certainly didn't want to create a Qsys project for something this simple. This is where my problems with the documentation began.

I poured over the documentation trying to find information on any of these issues using a Verilog-only design flow. I went through half a dozen training courses looking for anything that might help. These three things - clock, reset, and I/O pins - are basic requirements that any design would need, and I couldn't find anything about them for a pure Verilog design flow.

Most examples used Verilog files lower down in the design hierarchy with schematics at the top. The few that used only Verilog showed how to make a comparator or a multiplier - pure combinational logic with no clock and no reset. And of course they didn't show how to connect the module signals to I/O pins. From all of the tutorials, examples, and documentation I went through, it looked like I was going to have to jump through development environment hoops to synthesize a 65-line Verilog design. I was disappointed.

I decided to turn to Google and see what I could dig up. I tried "verilog only design in quartus," and to my dismay, the first four hits were for Altera documentation that I had already looked through! What is the deal here? But the fifth link was the jackpot. A professor at Swathmore College, a college I've never heard of, put up a most helpful one-page tutorial on how to do a Verilog-only design in Quartus. The last part of the tutorial even had a clock!

The tutorial didn't have everything I needed, but it covered the biggest sticking point - how to connect the module pins to physical I/O pins. That got me on my way, and I was able to resolve the clock and reset issues through some experimentation. I ended up having to drive a global reset signal from a GPIO pin on an attached microprocessor because the MAX II device does not actually have an internally generated power-on-reset. That wasn't as clean as I would have liked, but it worked.

In the end I wasted a couple days floundering around in the Altera documentation and training materials trying to solve some basic design issues that should have been dead simple. Would it kill Altera to make a short training course with a Verilog-only design example, and include a clock and reset in it?! Or maybe they could write up a quick start guide for a non-trivial Verilog-only design.

The issues I struggled with are fundamental to any design, and Verilog continues to gain in popularity for hardware design because of its many advantages over schematic capture, including my personal favorite: the ability to use version control because it's all text files. Not all designs need the enormous complexity that comes with Altera's more involved design flows. Not everyone needs to know all of the minute details of timing analysis, clock insertion delays, synthesis constraints, and floor planning. I would venture to say that most designs don't need these things, at least at first, but designers would greatly benefit from a simple, straightforward tutorial that would get them up and running with a Verilog design flow quickly. Altera is dropping the ball here.

Don't make the same mistakes that Altera is making. If you're creating documentation for a product that requires a fair amount of configuration, design and implementation, think about the basic steps that first-time customers would need to take to get up and running with your product quickly. Try to forget everything you know about the details of your product and imagine what it would be like coming at it with no prior knowledge of how to set it up. Things that seem obvious to you will be confusing to new customers, even if they are otherwise experienced designers or developers.

You don't have to assume you know nothing about the domain, but pretend you've never been exposed to this particular product before. How do you make it do something useful in twenty minutes or less that you could build on later? Lots of products are doing this kind of quick-start stuff today. All of the tutorials and screencasts for Ruby on Rails come immediately to mind. If you can get your customers over that initial roadblock and help them create something useful right away, they will greatly appreciate the extra thought you've put into making their lives easier.