Search This Blog

I've read a number of books that talk about and encourage refactoring—the practice of modifying code to make it cleaner and clearer without changing its function—but I've never read a book about refactoring until now. I decided to flesh out my knowledge of various refactoring techniques with Martin Fowler's classic Refactoring: Improving the Design of Existing Code, and because refactoring is often used to convert existing code into various software design patterns, I paired it with Joshua Kerievsky's Refactoring to Patterns. I normally read two related books on a subject to cover the subject in more detail and from different perspectives, and in this case the two books turned out to be intimately related, with Refactoring to Patterns building on and referencing Refactoring extensively. Here is an in-depth review of these two books.

VS.

Refactoring

Martin Fowler decided to write this book because at the time many books were being written about the new agile design movement, refactoring was an integral part of programming in agile design methodology, and he felt that no one else was going to write about the details of refactoring. The result is this clear and thorough book describing 68 low-level refactorings and 4 higher-level refactorings.

Before getting into the nuts and bolts, he spent a few chapters introducing refactoring, discussing when and why you would refactor, and how to identify code that could benefit from refactoring with a list of "code smells" that reek of bad code. These introductory chapters were an excellent condensed treatment of most of the agile principles found in other agilebooks, and Fowler had some well-reasoned arguments for his recommendations.

His advice includes such things as minimizing published interfaces within a team because interfaces create friction to code changes; starting with the simplest design if there is a clear path to refactoring to other designs; analyzing programs before optimizing for performance because the wasted time is not where you think it is; and concentrating tests where the most risk of defects are because comprehensive testing has diminishing returns. He also has a lot to say about flexibility in design, and starts the discussion by cautioning against making designs too flexible too early:

Building flexibility in all these places makes
the overall system a lot more complex and expensive to maintain. The big
frustration, of course, is that all this flexibility is not needed.
Some of it is, but it’s impossible to predict which pieces those are. To
gain flexibility, you are forced to put in a lot more flexibility than
you actually need.

He proposes that refactoring provides a better path that becomes a productive habit, and sums up KISS and YAGNI in two brief sentences:

Refactoring can lead to simpler designs without
sacrificing flexibility. This makes the design process easier and less
stressful. Once you have a broad sense of things that refactor easily,
you don’t even think of the flexible solutions. You have the confidence
to refactor if the time comes. You build the simplest thing that can
possibly work. As for the flexible, complex design, most of the time you
aren’t going to need it.

Later he brings it all together by explaining how refactoring can actually make the design process more flexible, even if the code initially seems less flexible:

As refactoring becomes less expensive, design
mistakes become less costly. Because it is less expensive to fix design
mistakes, less design needs to be done up front. Upfront design is a predictive activity because the requirements will be incomplete. Because the code is not available, the correct way to design to simplify the code is not obvious.

While most of the introduction was well written and a good review, the introductory content could largely be found in other excellent books (such as The Pragmatic Programmer or Clean Code). The real meat of Refactoring is in the set of refactorings that are named, explained, and shown with examples. Each refactoring is given a descriptive name like Extract Method or Replace Magic Number with Symbolic Constant that are mostly self-explanatory and easily recognizable. This name is followed by a short description of when to use the refactoring and a diagram of what it looks like. Then there is a motivation section describing in more detail when you would want to use it and a mechanics section describing the recommended steps to perform the refactoring. Finally, an example is shown for the refactoring with code so you can see what it looks like in practice.

I found the examples to be the most valuable part of the book, and I would have been quite happy with just the name, short description, and example for nearly all of the refactorings. The mechanics sections were almost universally confusing because it's hard to describe code changes in words. The terminology and descriptions of moving code around end up becoming a muddled mess no matter how you organize the prose. As for the examples, I was thinking as I read through the refactorings that they could have been even further improved if they were set up as a set of check-ins to Git with code diffs for each step of the refactoring. Such a setup would be quite slick and very useful as a reference.

It quickly became apparent that most of the refactorings have dual refactorings that are complimentary. In some situations you want to refactor in one direction, and in other situations you'll want to refactor in the opposite direction. This leads to refactoring pairs like Extract Method and Inline Method, Hide Delegate and Remove Middleman, and Change Value to Reference and Change Reference to Value. Sometimes going through these pairs felt tedious since it seemed like repetition for completeness' sake.

By the end of the refactorings, I was wondering if most of them could be sufficiently summed up by one generic refactoring called Extract Behavior/Data and its dual Inline Behavior/Data—or maybe even the single Move Behavior/Data—with a few other oddball refactorings that don't quite fit that mold. Of course, that classification would be too generic to be especially useful for teaching, but it was an obvious way to think about what was being accomplished in most cases.

I can appreciate where Jeff Atwood was coming from when he described Refactoring as too prescriptive, although I don't think that criticism is entirely true to Fowler's intent. He meant for Refactoring to be a catalog of refactorings that you could peruse and select, with suggested implementations. The programmer is free to follow a different path while using the catalog as a guide or store of ideas.

I do wonder who would get a lot of value out of this book, though. I felt that most of the refactorings were trivial and obvious. Any programmer with a few years of experience should be able to come up with them on their own, and the handful of refactorings that were novel didn't require a 460 page book to present them. A programmer that needs to learn most of these refactorings is probably more of a novice and would be better served by gaining real programming experience and discovering refactorings on their own. They'll remember how to refactor much better from experimentation and exploration than from reading through a catalog.

Refactoring to Patterns

This book clearly builds on Refactoring with numerous references to the original refactorings and bridges the gap between basic refactorings and design patterns. The book's format is also very similar to Refactoring, with a few introductory chapters explaining what refactoring is, what design patterns are, and what code smells are. The rest of the book is the catalog of refactorings that lead from ad hoc designs to specific design patterns with the same series of description, diagram, motivation, mechanics, and example sections for each refactoring as Fowler's book.

Like Refactoring, the whole book is quite clear and readable, maybe even more so. Kerievsky is a good writer, and I enjoyed reading his many anecdotes, especially in the introductory chapters. He also had several snappy comments warning programmers not to use patterns too much:

The patterns-happy malady isn’t limited to
beginner programmers. Intermediate and advanced programmers fall prey to
it too, particularly after they read sophisticated patterns books or
articles.

And not to optimize to patterns prematurely:

If you want to be a good software designer,
don’t optimize code prematurely. Prematurely optimized code is harder to
refactor than code that hasn’t been optimized. In general, you’ll
discover more alternatives for improving your code before it has been
optimized than after.

He was also careful to explain what the reader should really be getting from the book:

The true value of this book lies not in the
actual steps to achieve a particular pattern but in understanding the
thought processes that lead to those steps. By learning to think in the
algebra of refactoring, you learn to solve design problems in
behavior-preserving steps, and you are not bound by the small subset of
actual problems that this book represents.

I totally agree with this sentiment. To learn anything well, it's best to understand the fundamental reasons why and how something works. Once you've mastered the fundamentals, then the higher level stuff that used to be confusing and hard now has a place in your brain to hook in to, and it becomes much easier. Once you have internalized the methods for refactoring to patterns and clearly understand how to do it, it becomes trivial to solve a much wider array of refactorings to any pattern you so desire. In fact, to better learn how to refactor efficiently it's probably best to not try to memorize these refactorings, but to work out the steps on your own to gain a much more solid understanding through practice and discovery. That kind of understanding is difficult to achieve purely through reading a book. It's a lot like a mechanical puzzle, like a Rubik's Cube, where the satisfaction and real learning takes place by figuring it out for yourself. It's almost impossible to learn and remember how to solve a Rubik's Cube by watching someone else do it, and refactoring has the same sort of feel to it.

Having the same format as Refactoring, this book suffers from the same shortcomings. The mechanics sections are again filled with complicated terminology and confusing descriptions, and it's much better to skim them or skip them. The examples are the most important part of the refactorings, but they would be much improved by checking the code into Git as a series of code changes that could be browsed and compared to more clearly see the evolution from less structured code to design pattern. Despite these issues Refactoring to Patterns was an interesting read. I wouldn't say it's a must read, but it's worth a look if you're curious and like reading about code transformations.

Refactoring is Something You Do

I tend to judge books based on how much I learn from them. The more sparks of insight I get and the more buzzing my brain does, the more engaged I am in the book. Unfortunately, with Refactoring and Refactoring to Patterns, I did not feel like I learned much. It was a good review and a nice overview of available options when cleaning code, but what I basically learned was that the Creation Method pattern I had worked out on my own a couple years ago is actually a thing (and has been for a while) and that refactoring is something you do, not something you read about. The best way to get good at refactoring is to write a lot of code, realize it's ugly and dirty, study some books on patterns and writing clean code, and then figure out the puzzle of refactoring for yourself by cleaning up your code and making it beautiful. Studying refactoring won't get you very far. Practicing refactoring will.

Not all programming is the same. In fact, programming can be split into quite different categories depending on what type of program you're writing or what type of hardware you're writing for. Different types of programming, let's call them programming styles, have different constraints and require different environments and design trade-offs for programmers to work effectively in that style.

Programmers working in different styles will care deeply about entirely different aspects of programming. That's why you often see programmers vehemently debating the merits of opposing programming methods without ever reaching agreement. From each of their perspectives, their way is right. The defining difference in the argument is actually one of context.

To get a general overview of the different programming styles out there, and to get a better sense of what other programmers are concerned about with their code, let's look at the various programming styles. Some of these styles I know quite well because they are my day job, some of them I'm learning, some of them I've dabbled in, and some of them I know only from what I've heard. I'll try to be careful in what I say about those styles that I don't know too much about. There may be other styles that I haven't thought of, but these should be the main ones.

Embedded Programming

The main programming style I've been doing for the last few years is embedded programming. In this style, you are programming for a particular microprocessor or closely related family of microprocessors. The software you write is called 'firmware' and it will be programmed directly into flash on the processor or an external flash chip connected to the processor. Normally, this firmware is not changed very often, if at all, during the life of the product in which it resides. It's firm, not soft, hence the name.

Even within embedded programming, the differences in constraints from one programmer to another can be quite large, depending on whether the programmer is programming for a beefy quad-core GHz ARM processor or a meager 8-bit micro-controller. In most cases, the processor is chosen to have just enough horsepower to do the job it's meant to do, or more likely, slightly less power than the job requires, and the programmer has to make up the difference with crafty coding skills. Low power is a common consideration when choosing an embedded processor, and much of firmware design involves figuring out how often, how long, and how deeply you can put the processor to sleep.

Embedded processors have a number of communication interfaces and peripherals, and the embedded programmer must become well versed in bit-banging registers in the processor to configure these peripherals to interface with the outside world through attached sensors, storage devices, network interfaces, and user interfaces. Programs are mainly interrupt driven with real-time deadlines to meet. An RTOS (Real-Time Operating System) will provide mechanisms for defining interrupt service routines, tasks to run when interrupts aren't being handled, events and message queues for communicating between interrupts and tasks, and locks and semaphores for synchronization.

Programming environments are most often proprietary and provided by the microprocessor vendor. All of the ones I've used have been Eclipse based, and they provide a debugging interface with a hardware emulator that you connect to the processor to provide the normal debugging features of breaking into and stepping through code, reading and writing to memory, and giving access to the processor's registers. They also usually display peripheral register values in a decoded, human-readable way, show various characteristics of the RTOS state, and allow some level of profiling of running code. Non-proprietary IDEs are available as well, but they tend to be expensive.

In general, embedded programming happens very close to the metal, and you have to exert fine control over the resources available in the processor. Programming is usually done in C or C++, although Lua, JavaScript, and Python are starting to make inroads. It's as close to classic programming as you can get, with all of the considerations of limited memory spaces, special hardware instructions, and printing characters through a UART terminal included.

Systems Programming

Systems programming is the design and implementation of software that interfaces between hardware and other types of software, otherwise known as operating systems. Windows, Linux, iOS, Android, and the RTOS that an embedded programmer uses are all examples of operating systems. Systems programming is similar to embedded programming in many ways because the programmer needs intimate knowledge of the hardware, but whereas an embedded program normally targets a specific microprocessor, an operating system will run on a wider variety of hardware and include drivers for many, many more peripherals.

Operating systems provide the basic services that other programs use, like disk and file management, virtual memory, preemptive multitasking, device drivers, and application loading to name a few. The systems programmer has to worry about designing algorithms that will have high performance on a wide variety of hardware, writing drivers that work with an incredible variety of peripherals, and making sure that programs can play nice together without stepping on each others toes or bringing down the operating system altogether. Security and reliability are constant concerns of the systems programmer.

Most systems programming will involve at least some C and more likely a lot of C. The core of the operating system, referred to as the kernel, is normally written in C. C++ and Java are also commonly used outside of the kernel. The development environment is as varied as the programmer that's doing systems programming, but there are often a lot of specialized tools written specifically to support developers working on an operating system. Systems programming requires strong knowledge of algorithms and data structures, a meticulous eye for detail, and an ability to think about software running at the low level of the hardware-software interface.

Language and Compiler Design

Designing languages and writing compilers and interpreters is similar to systems programming in that programming languages are an interface between hardware and the software programs that run on that hardware. When the language runs on a virtual machine (VM) it even further blurs the line between language design and systems programming because the VM provides many of the same services as an OS. A programming language is not an OS, though. It's a lower level construct than an OS, and while an OS provides abstractions for various hardware features and peripherals of the processor, programming languages provide abstractions for the machine instructions and computational model of the processor.

Like embedded programmers and systems programmers, compiler writers are concerned with low-level performance, but they are concerned with performance in at least three languages—the host language that they're writing the compiler in, the source language that is being compiled, and the target language that the compiler outputs. After all, the compiler's basic function is to translate from a source programming language that other programmers write in to a target language that either the VM or the processor uses. Most compilers are written in C, although some are written in other languages. Rubinius is a Ruby interpreter written in Ruby, for example.

Compiler writers need to know the deep, dark corners of these languages to make the host and target code as fast as possible and to cover all of the things that any programmer could possibly do in the source language. Programmers want fast compile times, good interpreter performance, and the best runtime performance they can get, so compiler writers need to be well-versed in all of the low-level optimizations they can do to squeeze every last bit of performance out of their code, both the code the compiler runs on and the code it produces. On top of that, the code for the source language has to be interpreted correctly in all cases, even cases that most programmers will never think to exercise. Compiler writers need to think about and deal with complicated edge cases that result from interactions between seemingly simple language features that would make anyone's head hurt. I can't even begin to imagine how hard it must be to write a compiler for the more complicated languages (I'm looking at you, C++).

Application Development

The field of application development is as wide and varied as embedded programming. It ranges from the creation of simple utility apps like Notepad or a calculator to huge, complex apps like Adobe Photoshop or Firefox. The bigger an app gets, the more its development looks like systems programming, but at its core, an app provides a user interface and features to help the user do something useful with the computer. A computer with only an OS doesn't do anything meaningful. It's the applications that give the user the power to create and consume in all of the ways we've come to depend on.

For the most part, performance doesn't matter as much in application development. Normally an application has huge amounts of memory, storage, and processor performance to work with, and it's normally waiting for user input—a slow process compared with the high performance of the underlying hardware. More computationally or I/O intensive parts of an app may need to be optimized for performance, but the code should be profiled for hot spots and bottlenecks before blindly trying to improve slow operations. It's easy to get fooled into optimizing parts of the app that don't need it and ignoring the parts that are actually causing poor performance. However, in most cases the application programmer can get by with writing clean, clear code in a straightforward way and letting the compiler, OS, and hardware take care of making the app fast.

The application programmer has enough to worry about with making the app as easy to use and useful as possible. Choosing the right features, organizing the app so that it makes sense to most users, and creating an awesome user experience is insanely hard to get right. Users are fickle and demanding (not on purpose as they have their own lives and stuff they want to get done), and striking the right balance of features in any application is a constant struggle.

The environments for application development are generally quite good. Debugging features are much better than those for embedded programming, and IDEs like Visual Studio and Xcode make building a GUI and setting up the boilerplate code for an application much faster than it used to be. Application development can be done in almost any language, but native applications are most commonly written in C#, Java, Objective-C, and, to a lesser extent these days, C++.

Mobile Development

I'm not convinced that mobile
development is much different than application development, except that
it's done on a different platform than the target platform of the app.
That gives mobile development some characteristics of embedded
development because you need to connect to the system that the code is
running on to debug it. Mobile development tools include a simulator to
run the code on the host platform so that more debugging information is
available while you're getting the app up and running. Otherwise, mobile
development is very similar to application development in most
respects.

Web Development

Web development is similar to application development in that the programmer is concerned with making a great user experience and producing a product that meets the needs of the majority of users for a given set of tasks. Also like application development, as a web application gets larger and more complex, development starts to look more and more like systems programming. The server infrastructure and services provided through APIs become the overarching concern as a web application grows and attracts more users.

Web development is different from application development in that network and database interfaces are a prerequisite for web development. A native application may have these things, especially the bigger applications, but a web application without them would be meaningless. The client and the server are linked, but undeniably separated, and the server needs to manage connections to hundreds, thousands, or even millions of clients whereas most native applications deal with a handful of users at most.

Web developers work in a wide variety of environments and languages. Text editors like Vim, Emacs, and Sublime are commonly used, but full-fledged IDEs like Eclipse, NetBeans, Visual Studio, or anything from JetBrains are also popular. To avoid reinventing a bunch of wheels in web programming, you'll use some kind of web framework, and there are numerous options in any language you choose. The most well known frameworks are (in no particular order) Ruby on Rails for Ruby, Django for Python, ASP.NET MVC for C#, Grails for Java, Laravel and Symphony2 for PHP, and AngularJS and Ember.js for JavaScript. Tools for web development are evolving quickly, and debugging requires a wide variety of skills from classic print statements and reading logs to modern site monitoring and testing with tools provided by various companies in the cloud.

Game Programming

I don't know much about game programming, since I've never made any serious video games, but I'll give this description my best shot. Game programming has elements of application development because of the game's user interface, systems programming because a game will normally have its own memory and storage management, and embedded programming because the game code needs to be as close to the hardware as possible and has real-time deadlines. The video game programmer is a slave to the frame clock, and everything that needs to be done for a particular frame—user input, computer AI, physics calculations, 3D model calculations, and graphics redrawing—needs to be done before the next frame gets drawn on the screen. That sequence needs to happen at least 60 times per second to make a smooth user experience.

Game programming may have more similarities with the next style, scientific computing, than anything else. The graphics programming is especially computationally intensive, and the graphics card is a massively parallel processor that's designed specifically for doing complex vector calculations. The most common game programming languages are chosen for their raw speed and closeness to the physical hardware that they're running on. That means C, C++, and assembly for most video games. Tools and environments are mostly custom and proprietary because they need to be so specialized for the type of development they're used for.

Scientific Computing

Surprisingly, scientific computing is most similar to game programming in that it is defined by massively parallel computation. While games model a fictional universe, the goal of scientific computing is to model a real-world system with enough accuracy to explore new truths about the system being modeled. Some examples of scientific computing include weather simulations, galaxy formation, fluid dynamics, and chemical reactions. Strong mathematics and algorithm knowledge is a definite requirement for scientific computing, and parallel programming is obviously common both when programming on a graphics card with CUDA and on a server cluster.

I'm hesitant to say that any of these programming styles is more complex or requires more skill than any of the others. Each style has its own set of issues, things that are challenging, and things that are interesting. They each overlap in interesting ways with other styles. Exceptional programmers populate every one of these programming categories, and what differentiates the programming styles is not how hard they are, but the types of problems that need to be overcome to create awesome software.

As programmers, as engineers, we solve problems all the time. It's a
significantly large part of what we do. How do we solve problems
efficiently and effectively? It requires a balanced mix of creativity
and hard work. Both are hard to achieve, and a good combination of the
two is even harder. Creativity requires getting yourself in a mood where
you can let your thoughts run free and play with ideas, and hard work
requires a mood where you can knuckle down and produce results. These
moods are in constant conflict, and you can be at your most productive
when you manage the two moods well.

I was going to
make this post about how creativity is not what most people think.
Instead of being driven by flashes of insight, I was going to argue that
it was driven mainly by hard work. While I still think that's true in a
sense, and I'll get into that more later, after looking at my notes and
links to references on the subject, I believe creativity is a
combination of insight and hard work in the form of intense thinking.
Both things require time and space to accomplish, and both are required
to creatively solve problems.

How to be Creative

I recently found this excellent talk by John Cleese on how to be creative. Much of his talk is based on the work of Dr. Donald W MacKinnon,
and although I haven't read the book, I thoroughly enjoyed the talk by
John Cleese. The gist of the talk is that there's no defined way to be creative, as that's somewhat of an oxymoron, but there are ways to enable creativity, and that is what Cleese focuses his talk on.

He starts off with an explanation of what creativity is, and it's not a personality trait, but a way of operating:

...the
most creative had simply acquired a facility for getting themselves
into a particular mood - a way of operating - which allowed their
natural creativity to function.

That mood is
playfulness. They would play with ideas without any immediate practical
purpose, but purely for the enjoyment of doing so. Cleese goes on to
explain the two modes of operation that he labels the open and closed
modes. Creativity requires an open mode of operation, but completion of
the idea requires a closed mode of operation. To be most efficient, we
must be able to readily switch between the open and closed modes.

The ability to get into the open mode requires five elements:

Space free from distraction

Time also free from distraction

Time playing with uncertainty before deciding

Confidence that silly thoughts may still be fruitful

Humor to keep the mind playful and exploratory

Once you achieve this setup, Cleese recommends about an hour and a half to play (with ideas)—a half hour to let your mind calm down and an hour of creative work. I realized that this time frame mirrors my own flow for
blog posts pretty closely. Every post is a problem that I need to solve,
and when I sit down at night to work on a post, I'll spend about a half
an hour collecting my thoughts, looking through my notes, and
considering what I want to write and how to write about it. Sometimes I
have to wrangle my thoughts into submission because my mind wanders
around, not wanting to focus on the task at hand. Then I'll have an hour
or so of good productive time where I can write down thoughts and play
with ideas in a pretty good state of flow. I'll reach a point sometime
after the two hour mark where I start to tire out and my productivity
slows down. I thought it had more to do with getting tired before going
to bed, but it might be as much a factor of having worked creatively for
an hour or two and I'm simply tired of being creative.

You
probably noticed there was not one, but two time elements in the list.
The second time element is surprising, and Cleese had a great
justification for it:

One of my Monty Python colleagues who seemed to be more
talented than I was never produced scripts as original as mine. And I
watched for some time and then I began to see why. If he was faced with a
problem and saw a solution he was inclined to take it even if he knew
it was not very original. Whereas if I was in the same situation, while
I was sorely tempted to take the easy way out, and finish by 5 o’clock,
I just couldn’t. I’d sit there with the problem for another hour and a
quarter and by sticking at it, would in the end, almost always come up
with something more original. It was that simple.

My work was more creative than his simply because I was prepared to
stick with the problem longer. So imagine my excitement when I found
this was exactly what MacKinnon found in his research. He discovered the
most creative professionals always played with the problem for much
longer before they tried to resolve it. Because they were prepared to
tolerate that slight discomfort, as anxiety, that we all experience when
we haven’t solved it.

I find this type of
thing happening frequently when I'm trying to solve program design
problems. I'll come to a workable solution fairly quickly most of the
time, but if I pocket that solution for later and think about the
problem a while longer, I can usually come up with a more elegant
solution.

Humor may seem out of place in solving
problems, but Cleese strongly held that creativity is closely related to
humor - it is a way of connecting two separate ideas that results in
something new and interesting. In the case of humor, it's funny, and in
the case of creativity, it's useful for solving a problem. He certainly
opposed the idea that humor and serious business should be separated:

There is a confusion between serious and solemn. Solemnity…I don’t know what it’s for. What is the point of it? The two
most beautiful memorial services I’ve ever attended both had a lot of
humor. And it somehow freed us all and made the services inspiring and
cathartic. But solemnity serves pomposity. And the self important always
know at some level of their consciousness that their egotism is going
to be punctured by humor, and that’s why they see it as a threat. And so
dishonestly pretend that their deficiencies makes their views more
substantial, when it only makes them feel bigger…ptttttth.

Humor is an essential part of spontaneity, an essential part of
playfulness, an essential part of the creativity we need to solve
problems no matter how serious they may be.

Solemnity
should have no place in the creative process. It kills our confidence
in being able to play with ideas freely and distracts us from thinking
fully about the problem by limiting thought to the safest, most
acceptable paths. Humor is definitely more productive. My coworkers and I
joke around a lot at work, and we get a tremendous amount of creative
work done. On the other hand, I've never heard someone claim that their
workplace is serious and they do especially creative work. More likely
seriousness is accompanied with words like deliberate, careful, and
protocol. Oh, and if a company tells you that they work hard, but they
know how to have fun once in a while, that's a big warning sign.

Hard Work is Still Necessary

Creativity
alone is not enough, and while creativity does involve hard work,
coming up with a great idea to solve a problem is not the end of the
task. Now comes the extra hard work of implementing the idea, resolving
all of the details that you hadn't thought of before, and actually
finishing solving the problem. Scott Berkun has written extensively on this topic, and it's some of his better writing. In his post on The Secrets of Innovation Secrets, he reminds us of how much work is involved in innovation:

If there’s any secret to be derived from Steve Jobs, Jeff Bezos, or any
of the dozens of people who often have the name innovator next to their
names, is the diversity of talents they had to posses, or acquire, to
overcome the wide range of challenges in converting their ideas into
successful businesses.

These people didn't succeed
because of flashes of insight that just happened to them, and they
didn't succeed by coming up with a great idea and selling it. The ideas
themselves would have been nothing if it wasn't for their superb
execution. (The importance of execution is one reason why patent trolls are so destructive to innovation—they
haven't done any of the hard work of implementing an idea, but they
want to get paid royalties simply for patenting an idea with no
intention of doing the hard work themselves.)

Even
the flash of insight that leads to an idea is the result of a lot of
hard work. If it wasn't for all of the studying, researching, and
experimenting that came before the actual moment of clarity, the idea
may not have materialized at all. Scott Berkun again has some clear reasoning on why epiphanies are more of a process than an event:

One way to think about the experience of epiphany is that it’s the
moment when all of the pieces fall into place. But this does not require
that the last piece has any particular significance (the last piece
might be the hardest, but it doesn’t have to be). Whichever piece of the
puzzle is sorted out last becomes the epiphany piece and brings the
satisfying epiphany experience. However the last piece isn’t necessarily
more magical than the others, and has no magic without its connection
to the other pieces.

I have this experience all the
time when I'm trying to solve problems (which is also pretty much all of
the time). I'll be mulling over a problem for hours, days, or weeks,
struggling to find a workable solution, and then the answer hits me all
of a sudden, usually while I'm laying down to go to sleep. I call it Bedtime Debugging
because that's when it normally happens to me, but other people have it
happen when they're taking a shower or brushing their teeth. It feels
like a sudden eureka moment, but it would never have happened if I
hadn't spent all of that time thinking about the problem, researching
options, and studying the code I'm working on. The final connection that
made everything make sense may have happened in a moment, but bringing
all of the other pieces of the puzzle together so that that moment could
happen took much more time.

Preparing for Epiphanies

I
spend huge amounts of time reading and learning. I never know when I'll
need to use a particular piece of knowledge, and the more of it that I
have at my disposal, the better. Constantly exercising my mind and
learning new things also keeps my thinking process flexible so that I
can connect ideas from different fields and think about problems in new
and different ways.

Our culture tends to romanticize the
eureka moment while ignoring all of the hard work that's involved in the
process because the eureka moment is so much more exciting than the
work that came before it and must follow it. For one of innumerable
examples, Cal Newport,
an assistant professor of computer science at Georgetown University,
contrasts the theatrical impression of Stephen Hawking's discovery of
Hawking Radiation in The Theory of Everything with the reality:

In a pivotal scene in the Stephen Hawking biopic, The Theory of Everything, the physicist is staring into the embers of a dying fire when he has an epiphany: black holes emit heat!

The next scene shows Hawking triumphantly announcing his result to a
stunned audience — and just like that, his insight vaults him into the
ranks of scientific stardom.…

In reality, Hawking had encountered a theory by two Russian
physicists that argued rotating black holes should emit energy until
they slowed to a stationary configuration.

Hawking, who at the time was a promising young scientist who had not yet made his mark, was intrigued, but also skeptical.

So he decided to look deeper.

In the (many) months that followed, Hawking trained his preternatural
analytical skill to investigate the validity of the Russians’ claims.
This task required any number of minor breakthroughs, all orbiting the
need to somehow reconcile (in a targeted way) both quantum theory and
relativity.

The reality of Hawking's discovery is a
clear example of the hard work involved in solving big problems. He
needed to have a lot of knowledge about multiple complex fields of
physics and develop new advances in those fields over a long stretch of
time to make progress towards his goal of answering a question he had
about a theory he had come across. Creativity was absolutely involved in
this process, but the eureka moment is a vanishingly small part of the
story. These instances of major breakthroughs and discoveries through
hard work are the norm, rather than the exception. After all, if these
moments were as simple and easy as they are portrayed, they would be
much more common than they actually are. We can't all just sit staring
into a campfire or reading under a tree and expect all of the answers to
hit us in the head.

In a way, creativity is only a
small part of succeeding in solving a big problem, such as producing a
great product, creating a market around it, and building a business from
it. The idea of what product to make is a drop in the bucket compared
to the colossal amount of work involved in this process. Yet creativity
is also an integral part of the entire process. Every step of the way
there are little problems to be solved and details to be resolved, and
doing this creatively is incredibly important. Creativity and hard work
are intimately woven together in the process of solving big problems.

What will we remember about the present day 30, 40, 50 years from now? What will future generations know about what goes on in everyday life today? It's hard to say what will be remembered and what will be forgotten, but I wonder how much history we're losing today.

Think about what you do on a daily basis, what kinds of things make up the hours of your day. It probably involves a lot of computer usage at home and at work, driving a car or maybe riding a bus, some forms of entertainment, and hopefully socializing with acquaintances and loved ones. We eat food either prepackaged or prepared at home, we worry about paying the bills, and we sleep restfully or fitfully for some number of hours, probably not enough. The specifics vary widely, but that generally sums up life for most people. (Note: life is dramatically different for different people all
over the world throughout history, so assume I'm talking about a group of people
with similar lifestyles when I refer to what life is like for people.)

Of course, the details are where things get interesting. What has changed about those details in the last 30 years? Probably quite a lot, especially when it comes to computers and the Internet, but for the most part day-to-day life 30 years ago wasn't too far removed from what it is today. Most people that were alive then have a fairly good memory of what it was like (although I was alive then, and I'm starting to have a hard time remembering what life was like before the Internet). How about 60 years ago? That's getting tougher. Less people alive today were around back then, and memories are fuzzier. How about 100 years ago? 200 years ago? Living memories of those times are all but non-existent. We have to turn to written works to get an idea of what those times were like.

Romanticizing History

I'm thinking about all of this partly because of a Stratechery.com article I read last week by Ben Thompson. I was discussing the loss of history with my wife, about how we've probably lost a lot of information about what daily life was really like in any given time period even if we have some amount of writing about that time. Then I read Airbnb and the Internet Revolution, and I'm thinking about it more. The entire article is an excellent analysis of Airbnb's relationship with trust, but the section on The Industrial Revolution was kicked off my thoughts on losing history again. In this section, Thompson is critiquing Airbnb founder and CEO Brian Chesky's post about Airbnb's new branding and mission statement:

I thought it fascinating that Chesky invoked the Industrial Revolution in his post:

We used to take belonging for granted. Cities used to be villages.
Everyone knew each other, and everyone knew they had a place to call
home. But after the mechanization and Industrial Revolution of the last
century, those feelings of trust and belonging were displaced by
mass-produced and impersonal travel experiences. We also stopped
trusting each other. And in doing so, we lost something essential about
what it means to be a community.

Chesky’s focus is on travel, but in reality no one actually did so.
Nearly everyone lived on subsistence farming, more often than not
working land owned by someone else; said landowners, along with the
church, exercised nearly complete control, with the occasional merchant
facilitating a bare minimum of trade primarily to the benefit of the
ruling class. The Industrial Revolution — and the accompanying
agricultural one — completely flipped this arrangement on its head.
Thanks to the efficiencies afforded by technologies like the loom and
mechanical power people were able to specialize and trade the outcomes
of their labor for a much fuller and richer life experience than what
they had previously.

I get that I’m putting an awfully neat bow on what was 150 years of
wrenching change. After all, I just basically described soul-destroying —
and often body-debilitating — work in 18th century sweatshops as
“specialization”; it’s a bit like Uber’s insistence on calling its
drivers “entrepreneurs.” And yet, when you consider how structurally the
old taxi medallion system resembled the landowner-peasant relationship
of old, why is everyone so eager to declare that the new boss is worse
than the old boss?

What's so fascinating about these dueling perspectives is that Chesky's perspective is a romanticized view of what life was like in agrarian society. He's asking us to imagine a life with modern day political and economic constructs, but with what we all imagine the social structures to be like in that day and age, namely everyone knowing everyone else in a tight-knit community. That lifestyle never actually existed. Thompson tries to relate a more accurate picture of agrarian society, and in the process romanticizes what life was like during the Industrial Revolution. He acknowledges the trick he was pulling, and in so doing reminds us of how easy it is to hold false historical perspectives because we are evaluating history through the lens of modern experience.

Written History

It takes a lot of effort and study to imagine what life used to be like ages ago. I remember in high school being taught multiple times to not think of historical events or novels in the context of the present day. The politics, economics, and culture were all different in the past than now, and the farther back you go, the more things were different. It takes knowledge of the entire historical context to appreciate the importance of books like To Kill a Mockingbird or Grapes of Wrath. These books certainly add to our knowledge of the time periods they were written in, but they are also better understood when we augment them with more knowledge of those time periods.

Historians have a fairly good understanding of recent history—meaning the last couple hundred years—because of the large volume of written works they have available to study. As we go farther back in time, resources get more and more sparse, and the resources we have get harder and harder to interpret. It's much harder to understand what life was really like in the middle ages from works like Le Morte d'Arthur and The Canterbury Tales or what it was like in Ancient Greece from The Iliad and The Odyssey. It becomes difficult to separate what is faithful to reality at the time and what is fantasy. Adding to the reduced amount of writing is the bias in who wrote. Hundreds of years ago, the land-owning elite had both the ability and means to write while the peasantry did not, so we get an overwhelmingly biased perspective of the past. Without enough information to determine what's fact and what's fiction, and a serious lack of common people writing about their day-to-day lives, it becomes far too easy to romanticize history in a way that's not entirely accurate.

We romanticize history in other ways as well. Most movies and TV shows give a biased or distorted view of what the past was like. The more popular the movie, the more likely it's exaggerating the truth or playing to a fantastic legend, like the Ancient Greek tales. After all, myth and legend makes for a much more interesting movie than real life does. It's quite rare to see a movie that's actually historically accurate, and our perception of reality becomes distorted by all of the fiction. Not intentionally, of course, and I love a good action movie about Spartans as much as anybody, but the distortions take hold all the same.

Our memories also do funny things to our perception of the past, this time a more recent and individual past. Almost everyone who had a decent childhood looks back on that time with rose-tinted glasses. I know my grandparents did, my parents do, and now I'm starting to as well. I look back on my childhood as an easier time when life was simpler and more worry-free. Of course this is not really true. Take any decade in the last hundred years and you can find all kinds of scary stuff to worry about.

The real difference is that I was a kid, and a kid's brain has natural defense mechanisms against worrying about the world outside of its immediate surroundings and needs. I was completely oblivious to the things my parents worried about when I was growing up, and they happily ignored what their parents worried about. I didn't worry about world politics or the economy; I mostly worried about doing homework, playing sports and video games, and eating as much pizza and junk food as I could. The brain also tends to forget the tedious day-to-day stuff, and even most of the negative aspects of the past, while remembering the good stuff. That gives us an especially biased view about our own past and the good old days.

Creating History

Considering the woefully incomplete picture we have of history and the biased views we have about our own past, I wonder how we will remember today. With the Internet we have more data and information being written, generated, and uploaded for the public record than ever before, but that may not mean we have a more accurate record of what life is really like today.

We may have more data available, but the sheer volume of data could be a barrier to a real understanding of today's reality for future generations. If the vast majority of information we have is tweets about shopping and pictures of food and cats, what will future generations think about us? Even though the volume of data we have is going up exponentially, the quality and meaningfulness of that data may be going down at a similar rate.

Reducing the friction required to post something in public view certainly increases the number of people posting and the frequency of posts, but it also means we are inundated with much more trivial posts. When people used to have to sit down and write out a letter with a quill and a bottle of ink, much more care was put into what was written down. But diaries and letters written on paper have fallen to the wayside. Now that you can snap a picture of that burrito you're having for lunch with the smart phone in your pocket and post it to facebook in seconds for all of your friends to see, that's what we get.

An astonishing amount of the Internet is also transient. Tweets disappear, links rot, and hard drives crash. The older something is on the Internet, the harder it is to find and the more likely it's gone forever. Projects like The Wayback Machine are trying to save some if it, but it's like trying to save some of Niagra Falls in a swimming pool. Future historians may not have as much valuable information about this age as we think they will.

The truth about the life of a peasant or trader or farmer from ancient times up to the post-war period has quite possibly been lost to history, and the farther back we look, the more likely we don't know the real story. That may be true of what goes on in everyday life today, but for the opposite reason—too much information instead of too little. These are not revolutionary ideas, nor probably are any of the ideas I write about. They're not newly discovered epiphanies, merely me trying to organize my thoughts and hopefully learn in the process. Therefore, there's no grand theory here about how society is collapsing because of our loss of history, no sharp conclusion about how we can save ourselves by doing better at generating and preserving knowledge, just a general awareness of the fact that much of life won't be remembered and what is remembered may not actually be how it happened or why. It's something to keep in mind the next time someone tells you how things used to be better in a simpler time, especially if that person is trying to sell you something. It may be worth asking, "How do you know what life was like then?"

It's time for my bi-yearly update on my Nissan Leaf experience. I'm on my second Leaf, having owned a 2012 Leaf SL for two and a half years before trading it in for a 2013 Leaf S. I've written extensively about both Leafs already, so I won't repeat myself too much here. Check out the EV tag for all the gory details. Suffice it to say, I love the Leaf, and after having driven an EV for three and a half years, I can't imagine going back to an ICE car. The Leaf is fun, torque-y, quiet, and oh-so comfortable to drive.

On Range and Battery Degradation

The one major issue with the Leaf is the capacity of the battery, coupled with how long it takes to charge it back up. It has a range of about 85-100 miles on a full charge in the summer, depending on driving conditions, so I'm limited to the city and the immediately surrounding area unless I do careful planning and have a lot of time. Those stars have not yet aligned, but I do enjoy zipping around Madison and coming back home to charge up in my garage. It's the essence of convenience. We have a Prius for the longer and far less frequent trips we need to take beyond a 40 mile radius of our house.

Because EVs are still a new and interesting technology, I keep records of my driving and charging so I can plot things like the change in range over temperature, battery efficiency, and estimated battery degradation over time. To read about the methodology I use, take a look at the two-year update of my 2012 Leaf or the first report of my 2013 Leaf. Basically, I track driving temperature, battery state-of-charge (SOC), mileage, and kWh consumed at the wall outlet. I always trickle charge off of a 110V outlet through a P4460 Kill-A-Watt power meter so I know exactly how much electricity I've used to charge the car.

Since the main question to answer about the Leaf is what kind of range it gets, I use my data to estimate the range I could get on every charge. I scale up the miles I drove to what it would be if I charged the battery to 100% and drove the car until the battery died. This is assuming the SOC is linear over the entire range, even though that doesn't seem to be exactly true. In my experience a 1% change in SOC will take you farther when the battery is mostly discharged than when it is mostly charged, but I don't have a good way to account for this so I assume it's linear. Then I plot these estimated ranges against the average temperature for each discharge cycle, and I get the following plot for 14 months worth of data:

This plot is interactive, so you can hover on points to get details and zoom in by selecting an area with the mouse. Clearly, the range has a significant dependence on temperature, with a range as low as 42 miles at sub-zero temperatures and as high as 110 miles in perfect summer weather. I very rarely use the air conditioner or heater, so range would be reduced from this data if climate control was used on especially hot or cold days. In fact, the outlier at 86°F and 78 miles of range was a day when I drove the family 53 miles with the air conditioner running to keep them comfortable. It was also a trip that was about half freeway driving at 65 mph, which further reduced the range. (For a great set of charts on the Leaf's range dependence on driving speed, check out the range charts at MyNissanLeaf.com.)

I split the data between the first 8 months and the last 6 months so we can see how the range has changed over time. Trend lines are shown for both sets of data, and the few outliers—one in 2014H2 and two in 2015H1—were ignored when calculating the trend lines. The two lines are practically indistinguishable at the warm end of the temperature range, and those points are further apart in time, taking place in the summer in 2014 and the beginning of summer in 2015. The 2014H2 range at the low temperatures is actually lower than the 2015H1 range even though the points at that end of the graph happened closer in time and the lower range points happened earlier, likely because it was slightly colder at the end of 2014 than at the beginning of 2015. Overall, it appears that the battery has had a negligible amount of degradation in the past 14 months.

I do what I can to keep my battery as healthy as possible, since a healthy battery will have a longer range over a longer period of time. To take care of the battery, I generally follow these guidelines:

Charge to 80%.

Do not charge if SOC is at 80% or above.

Avoid hitting the low battery warning at 17%, the very low battery warning at 8%, and turtle mode at the end of charge.

No DC Quick Charging.

Reduce the number of charging cycles by not charging every night.

Store the battery at a lower SOC, if possible, by not charging every night and delaying a charge if I know I'm not driving the next day.

Limit the depth of discharge (DOD) by charging before a trip that would take the SOC below 20%.

Limiting the number of charging cycles and limiting the DOD are in direct conflict, so it's a balancing act. I'm not sure what the best trade-off is between charging cycles and DOD, but I tend to err on the side of shallower DOD. My average DOD over the last 14 months has been 51%, meaning I normally drive until around 30% SOC and then charge up to 80%. I've gone as deep as 71% and as shallow as 17%. The following histogram shows the distribution of DOD cycles that my Leaf has had:

On Energy Efficiency

That leaves the Leaf's energy efficiency left to look at. I measure the energy used at the wall outlet as well as keep a record of the on-board energy efficiency meter for each month of driving, so I can plot those over time. I can also calculate the charging efficiency from these two energy efficiency numbers, and all three series are plotted in the next chart:

You can see that all three efficiencies got worse during the cold months of winter and have now recovered with the Leaf's efficiency meter reporting well over 5 miles/kWh as the weather has warmed up. I even set a new monthly record of 5.5 miles/kWh this month, as measured by the Leaf or 4.5 miles/kWh from the Kill-A-Watt meter at the wall. Charging efficiency for trickle charging is also up over 80% with the warmer weather. I'm not sure what the oscillating behavior of the charging efficiency was about last year, but it seems to have gone away for now. It possibly has to do with the coarseness of the Leaf's efficiency values.

I'm getting fairly good efficiency numbers with the type of commute that I have through the city of Madison, and so far I've used 1,740 kWh of electricity to drive 6,644 miles. Since I pay $0.18 per kWh, that's $313.20 total, or $0.047 per mile that I pay to charge my car. That's the equivalent of paying $1.41 per gallon of gas for a 30mpg car or $0.94 per gallon for a 20mpg car to drive the same distance. That's pretty nice even with the higher than national average price I pay for electricity (to support wind power).

Future EVs

The Leaf has been a great first EV experience for me, and I'm excited to see what the future holds for electric cars. So far the Nissan Leaf, Chevy Volt, and Tesla Model S have been the only practical EVs widely available, and they each serve different markets. The Leaf, being a pure EV with limited range, is a city commuter car. The Volt, with its gas generator, is the PHEV for people that need a full-range vehicle. The Model S is the EV for those lucky individuals that have $100k+ to burn on a car. Now the BMW i3 has entered the ring as well, and it's a combination of the other three cars—the electric range of the Leaf, the gas generator of the Volt, and some of the luxury of the Model S at a little higher price than the Leaf or the Volt.

These EVs have made some significant advances over the past four years, and soon it looks like there will be some bigger leaps forward. Rumors are surfacing that Nissan will increase battery capacity in the Leaf 25% for the 2016 model year, and double it for the 2017 model year. Chevy is getting ready to release the all-electric Bolt with a 200 mile range, and they're increasing the battery capacity of the Volt as well. Tesla is getting close to releasing the Model X SUV, and the mass-market Model 3 with a 200-mile range and a $35k base price will follow, hopefully in 2018. The next couple years are going to be interesting for EVs with at least three affordable cars becoming available with a 200-mile driving range. Hopefully other manufacturers will get in the game, too, and we'll have even more options to choose from. That kind of range could be a game-changer for EVs. I can't wait.