Long Days Leave No Trace (Part I)
(一)
Another sweltering Saturday. The smog hung in the sky as if glued there, still blanketing the city. With Little Bao in tow, the three of us wandered through the children’s zone at Solana, planning for the little one’s future. My wife and mother-in-law flitted from one toy store to the next, while I—since I was pushing the stroller and couldn’t easily walk around—sat quietly with Little Bao and watched the children playing on the ice rink downstairs. Soon our attention was captured by two little boys running combat drills on the ice. Little Bao happily turned her neck to follow the puck, her eyes locked tightly on the black disk, every so often letting out a delighted “cheer”; and I sat silently watching the two “little men” fall again and again and climb back up again and again. The contest was fierce, yet neither side played dirty—enough to make the grown men on real hockey rinks blush with shame.
For days now, the follow-up coverage of the Tour de France doping scandal had been bringing down former heroes one after another. In the adult world, people’s craving for fame and fortune, their pursuit of success, has long since blown past the bottom line of ability or even morality. We have to admit it: this world is becoming more and more restless, more and more superficial. Those who can barely crawl wish they could walk at once; those who stagger along wish they could break into a sprint. A couple of days ago I idly searched Amazon for “learn in hours” and “learn in days,” and found 65 and 157 results respectively. “Master Java Programming in 24 Hours,” “Learn JavaScript in 21 Days,” “Learn Visual C++ in 30 Days”… Looking at that long list of languages that take enormous effort to truly learn and use, I couldn’t help but sigh that this restlessness has seeped into everything.
Little Bao was still giggling. That joy from the bottom of her heart, clean as a snowflake, made me genuinely envious. If it weren’t for the fact that last Sunday my wife had a serious talk with me about how I might better fulfill my responsibilities as a father in the years ahead, at this moment (a Saturday afternoon) I ought to have been sitting upright in the office pondering how to write some piece of code, rather than letting my thoughts soar in such a relaxed setting.
The upshot of our discussion was this: on the weeks with the big weekend, I should avoid going into the office to work if I could, and on weekdays it would be best to get home before seven on at least two days—which would greatly increase the time I spend at home with Little Bao and strengthen her sense of the role of “father.” In a city as crowded and nearly at the breaking point as Beijing, given the thirty-five-kilometer distance from office to home, getting home before seven means leaving the office at least two hours early, and praying the whole way that 1) there’s no accident (a low-probability event), 2) there’s no traffic control, 3) there’s no phantom traffic jam. A two-hour commute is within the tolerance limit of many Beijingers, but for me, more than an hour of driving to or from work already makes me miserable all over, let alone that despairing figure of two hours. So I decided to take the subway on the two days I head home early—that way it takes only an hour and a half to get home; and on the subway I can step away from code and the internet for a while, and read a few dozen pages of a book that has nothing to do with technology. As it happened, the book I read during last week’s two car-free commutes was The Remains of the Day—a novel I’d bought long ago and picked up several times without ever getting into. Mr. Stevens, the protagonist, uses the occasion of a journey to look back over his long career as a butler. Throughout the whole book he is forever recalling his past life, and constantly probing a serious question: what exactly makes a distinguished butler?
I have this book to thank for making me start to seriously review my own career. The thinking drifted on and off for several days, and much of the time simply hid itself in my subconscious, so that whenever I tired of work and stared blankly at the intersection of Zhongguancun East Road and Chengfu Road outside my window, it would pop out, freeing me for a moment from my heavy work and letting me roam freely through memory.
(二)
A blast from the coach’s whistle pulled me back for the moment. Just then, the two little guys began an attack-and-defense drill, and things got fun—the two little rookies slid from opposite ends of the rink along almost the same line toward center ice, and with a bang, crashed hard into each other and both went down. The coach came over, pulled the attacker aside, whispered a few words, and gestured a few times, and then the game resumed. The two raced from the two ends toward center ice; the defender kept his center of gravity low, eyes fixed on the puck as he glided at high speed. At the instant they were about to collide, the attacker made a sudden stop and cut sharply diagonally forward. Because the defender had lunged too hard, he couldn’t adjust in time, and had no choice but to let the attacker slip past him easily and score. Whether she understood the game or was simply happy, Little Bao waved both hands and let out a joyful shriek.
This is the role of a coach. They tell you what the fundamentals are, how to read the situation, and what qualities a good player should possess. Early in a person’s career, a good mentor is more important than anything. In the blink of an eye, ten years of my programming career have passed, and over these ten years I’ve been constantly exploring what qualities an excellent programmer ought to have. If only I’d had a coach back then to guide me and give me a direction to explore—how wonderful that would have been.
Unfortunately there was none. The software industry has no coaches, and no tradition of apprenticeship. Perhaps there once was, but ever since programmers turned from craftsmen into engineers, coaches and masters have ceased to matter. You basically don’t need the kind of skill a craftsman needs to make something out of nothing; all you need is the ability to solve some particular problem—in a sense, no different from a worker on an assembly line. This has also driven the best-seller status of those quick-learn books, because what they try to teach you is how to finish a task, not how to program. Of course, the internet is shattering all this, and programmers seem to be returning to the craftsman tradition. That’s good.
Though there are no coaches, virtually every software company assigns a veteran colleague to each new hire to serve as a “mentor” in a “symbolic” sense. I say “symbolic” not to deny the value of mentors, but to say that these mentors are not professional mentors; of the way of the teacher—“transmitting the way, imparting knowledge, resolving doubts”—the mentors at best lend a little help with the last item. Of course, for the company, the most important role of a mentor is to be a role model: through their work attitude, work habits, and work ability, they exert a subtle influence on new employees, especially those in the early stages of their careers.
The company where my career began was Digital China Network (DCN). If we define Google or Twitter as “excellent” companies, then DCN clearly belonged among the mediocre. Fortunately, DCN had inherited the old Lenovo foundation, and still had a batch of idealistic systems hotshots. Z was one such person. As it happened, I was assigned to his team. When I threw the question “what qualities should an excellent programmer have?” at my mentor, X, who was about to leave, he told me to watch and learn more from Z. After that, whether intentionally or not, I would go trouble Z more often, and he would always set aside what he was doing and cheerfully answer my questions. To solve a problem, he often worked late into the night; if a code discussion hadn’t gotten to the root of the matter, he would never let it go. Take code review: when you see a pile of logically flawless but stylistically WTF code, even if you want to curse, you’ll always compromise under the pressure of the release or of workplace politics. But Z wasn’t one to compromise. Smiling, he would relentlessly point out a dozen or so flaws in your code and have you go fix them. Many people think it’s enough for the logic to be correct, but Z expected the code (the algorithm) to be reasonable (harmonious) in time and space, and to achieve SoC. Outside of work, he was a carefree sort, often bursting into hearty laughter, his whole body reeking of smoke, so that even from far away you could feel his distinctive aura.
From Z, I found the first answer to the question I’d been chasing:
Truly love what you do.
I settled on this phrasing because I feel that words like “dedication,” “grit,” “diligence,” and “love of learning” are, to a greater or lesser extent, encompassed by it—or rather, are its natural consequence.
For me at the time, “truly love” meant spending more than twelve hours a day holed up in the office, working hard to figure out every technical problem I encountered. Soon I had OSPF down cold, filling the gap on OSPF left after X departed; then I independently developed IGMv3 and SNTP; and then I completed the extremely important port of the Linux 2.4 kernel.
(三)
Because of work, I gradually came to deal a great deal with S, from another team. S had wide interests; he helped build the team wiki inside the company, which greatly systematized the exchange of information and the sharing of knowledge. Previously our exchange of knowledge was mainly by email, which was very passive—useful and useless knowledge alike all became emails waiting to be opened. Open and read them? A waste of time. Don’t open them? Then later, when you need it, you won’t even know there’s such a thing sitting in your inbox. Under S’s promotion and maintenance, the team wiki greatly improved everyone’s efficiency in acquiring knowledge.
I learned from S that he had used an open-source piece of software called MediaWiki (the software Wikipedia runs on). I started playing with MediaWiki, and from there came into contact with LAMP, and gradually realized the importance of open-source software like Linux and MediaWiki. If Lin Zexu and Wei Yuan were the first in modern China to open their eyes to the world, then he was perhaps the first within DCN to embrace the wider world. People who did systems rarely paid attention to the trends of applications, nursing a haughty “Celestial Empire looks down on the barbarians” air; while people who did applications lowered themselves humbly to watch the changes in systems. Now grab any random person who works on routers and ask his view of web applications—nine times out of ten he’s still stuck at his understanding of LAMP; while people doing web applications have already pushed their tentacles into the user-space data plane. The reason: the more you work on systems, the more you want to control everything, and the more you tend toward closedness; while the more you work on applications, the more you depend on an ecosystem, and so you embrace openness.
S made me realize the power of open source and the greatness of open communities. With awe for MediaWiki, I began to learn PHP, and then, under his influence, learned Python, which is said to be used by “smart programmers.” I figured I was already a “real programmer,” so if I could become a “smart programmer” too, why not?
In this process, I found the second answer:
Embrace open source and free software; embrace the community.
In college I had once been a staunch Microsoft-ist: whatever Microsoft promoted, I supported; whatever Microsoft opposed, I opposed. Even at graduation I still naively believed that C# was the ultimate weapon for our generation of programmers. S pulled me out of that blind following just in time, and showed me a different world. The heat of the PRISM scandal is now gradually fading, but it has made people begin to grasp the importance of Richard Stallman’s ideas: open-source software is a matter of humanity’s freedom. Unfortunately (though perhaps I shouldn’t say this), both of my employers have contributed far less to open-source software than they have taken from it.
PHP and Python seemed to be of no help to the development tasks I was doing; the point of learning them was to understand the wider world, to understand why the most popular software gets built in such languages. To better put what I’d learned into practice, I built a tool in PHP and Python: a developer could submit a test task through a web page written in PHP, and a backend Python script, on receiving the task, would pull the specified version of the code, compile it, upload the compiled image to a directly connected switch, and then start running the regression scripts the test team provided. The efficiency gains my tool delivered drew my boss’s attention, and I was approved to use a PC and two switches, forming a complete environment for the dev team to practice CI (Continuous Integration).
In this process, I discovered the third answer:
Being able to constantly raise my own and the team’s efficiency through the technology I command.
Let me explain a little more. A real programmer finds it hard to suppress the urge to use his skills to change the status quo when those daily, repetitive, inefficient ways of working present themselves before him. At work (and in life too, of course), such inefficiencies are everywhere. For instance, periodically exporting some data from system X into Excel to make a report; or collecting weekly reports level by level to summarize the work.
This kind of inefficiency was widespread at the second company I worked for, Juniper.
Looking back on my career so far, I worked at DCN for two years and two months, at Juniper China R&D (CNRD) for five and a half years, at Tuke Quan as founder and CTO for two years, and then returned to Juniper CNRD, where I work to this day. So, as an employee, I’ve only ever worked at two companies, and therefore I can’t say for sure whether every software company has similar inefficiencies. But I feel that inefficient situations at work are everywhere; the question is whether they get discovered, and whether, once discovered, they’re worth doing something about.
(四)
The drill on the ice rink ended, and the little guys left the ice to rest. I let go of the stroller wrist strap, leaned my head over, and softly called Little Bao’s name. Little Bao was clearly still utterly absorbed in the rink, and was startled by my sudden movement. When she turned her head in alarm and saw it was me, she relaxed, smiled faintly, and turned back to watch the sport on the ice. Following her gaze, I saw a little girl of six or seven on the rink, earnestly practicing figure skating all by herself. Her movements were so deft, her posture so graceful, that you almost forgot her age. I thought: she has probably been practicing like this for quite a long time.
Seeing this, I couldn’t help recalling a discussion I’d once had with Y at Juniper about our hiring criteria. I didn’t understand why we didn’t give young employees—even fresh graduates—a chance. Y believed we needed experts, and an expert in a field, according to research, requires 10,000 hours of cultivation. I did the math: assuming forty hours a week, fifty weeks a year spent on some particular field or fields, then five years could make an expert. This is also why many companies require at least five to seven years of relevant experience for senior positions. But the reality is that in interviews, many people with five or even ten years of experience don’t necessarily live up to the years they’ve let slip away. I once met a programmer who had worked for eight years and, given editing and compiling environments like vim and gcc, couldn’t even correctly complete a very simple linked-list operation. What’s going on here?
I looked up the original wording of the “10,000 hour rule,” and it goes like this—“it takes approximately 10000 hours of deliberate practice to master a skill.”
The problem lies in “deliberate practice.”
What is “deliberate practice”? Piano grading has nine levels, and each level has its required techniques and scores. This is a series of deliberately designed exercises; each level is a bit harder than the last, yet with effort it can still be mastered. Once you’re thoroughly at home with Czerny, you can try a bit of Bach, perhaps a little Beethoven too, but you absolutely can’t go in reverse, nor can you skip around. Skipping around means the gap between your current level and the desired result is too large—perhaps already beyond what effort alone can reach.
Unfortunately the software industry rarely has such “deliberate practice,” and neither schools nor training institutions have a comparable system. So this society can mass-produce Grade 9 piano holders, yet cannot mass-produce qualified programmers. Many people with five years of work experience, converted into effective experience, may have only one year left; the remaining four are just repeating what they gained in the first. It’s like someone who, having mastered Czerny’s Practical Method for Beginners on the Pianoforte, keeps diligently and repetitively practicing the same material—even if he practices until he can play it off-book and with ease, what’s the use?
Thinking about our situation, it’s rather bleak. No suitable mentor to point the way, no established system to cultivate experts. Yet we still have to keep learning, keep updating our knowledge. For those programmers who haven’t yet “awakened,” a career is like the “rat race” of Rich Dad Poor Dad, wearing out the years in idle drifting.
So the best way to save oneself is to keep adding challenges, to push oneself out of the comfort zone. The specific method: challenge yourself with tasks that just barely exceed your ability—build (attempt) - measure (analyze) - learn (learn and summarize). Then repeat, over and over. This is the lean-startup model suggested in The Lean Startup, and it applies equally here.
Don’t read those books that promise you can master XYZ in so many hours or days. Life is short; read more of the works and essays of the masters—they can lift you to a new step; write more code, write more code that gives you a sense of conquest.
This is the fourth answer I found:
Constantly jump out of the comfort zone, and deliberately challenge yourself.
What comforts me greatly is that during these five and a half years at Juniper, the company offered various opportunities for me to learn and master the data plane, the kernel, and applications across three different teams. Thanks to L’s relocating to the US, I also had the chance to lead a team, and to put into practice the theoretical knowledge of leadership I’d acquired.
The ice rink was still buzzing with voices. Fearing the chill would make Little Bao cold, I didn’t dare linger too long. I pushed the stroller a bit farther in and sat down on a chair to rest a while. Little Bao raised both hands as if to protest, but when she realized that from her seat she could still see a corner of the rink, she gradually quieted down, her hands resting naturally on the stroller’s guardrail.
Funny to say, just before I left Juniper, L hosted a small English speech training to improve the managers’ ability to speak in public in English. My topic was “Move yourself out of comfort zone.” Later, by chance, I ran into L, who had also left Juniper, and he said he’d felt even then that I was going to leave. I asked why. “Because CNRD had already become a comfort zone for you—all you had to do was not make mistakes, wait quietly, and you could climb up bit by bit, and that runs counter to your character, especially to the feeling conveyed by your speech,” L replied.
Thinking about it, it’s true. My character has restless blood flowing through it, inherited from my father. In 1993, my father went alone to Hainan and Guangdong, like all the vigorous young people of that era, hoping to find work opportunities at the very forefront of reform and opening up, and to live out one carefree episode of his life. What set him apart from the others was that my father was then nearing forty, had a family and children, and still held the golden rice bowl of a doctor. Now I’m past thirty, and my father—promoted to grandfather—is over seventy; at an age when he should be enjoying his twilight years, he’s still fighting on the front lines, and in his spare time has published his first book as an editor, while hard at work compiling his second. My father is my role model, and fully surpassing him is one of my great ideals (of course, this is something a Darwinist must achieve—after all, each generation can’t be worse than the last, right ^_^). Unfortunately, I have yet to fulfill this ideal.
(五)
A language that doesn’t affect the way you think about programming, is not worth knowing. - Alan Perlis
Leaving Juniper, I chose to start a business and founded Tuke Quan. It was a wondrous journey, a journey that matured me a great deal. For the first time ever, I was writing software not for my employer, not for my payroll, but for my dream. Though that journey lasted only two years before I was forced, for personal reasons, to choose self-exile, those two years were, as Steve Jobs put it, when I began to connect the “disconnected dots.” My programming level began to develop enormously, my software-development thinking kept maturing, and I increasingly felt like a real programmer.
More importantly, I began to learn new languages. You may have noticed that after learning PHP and Python at DCN, I stopped learning new languages at Juniper—partly because I was consolidating my level in those two languages, especially Python, but the more crucial reason was that I’d begun to rest on my laurels. C made me a real programmer, Python made me a smart programmer, and I seemed unable to find a reason to keep learning new languages.
But starting a business changed all that. I had to learn JavaScript, because it’s the only standard on the client side. Although I’d first encountered JavaScript more than a decade earlier and used it to create some effects, my use of it back then was less “use” than “misuse.” At Tuke Quan, I truly came to know this prototype-based language afresh. Also, to weigh what kind of architecture would better serve future development, I spent a great deal of effort deeply understanding Ruby, comparing Ruby and Python. Through The World of Programming According to Yukihiro Matsumoto, I came to understand many of the ideas behind Ruby’s design. Although Tuke Quan ultimately chose Python/Django, this was a very beneficial comparison and reflection, and it helped me find the fifth answer:
Learn more than one programming language thoroughly, understand as many programming languages and their strengths and weaknesses as possible, and know the likely best path to solving a given problem.
Note that “learning thoroughly” and “learning” are two different concepts. “Learning” means you can use the language, you can write programs; “learning thoroughly” means much more:
- Understand the motivation for which the language was created, and deeply understand the ideas behind it.
- Master how to do online debugging and post-mortem analysis (coredump analysis).
- Master the language’s extensions and surrounding technologies. Such as the JVM for Java, or OS/CPU EABI for C.
- Master how to improve the efficiency of critical code, and how to extend the language’s capabilities. Such as NIF for Erlang.
- …
Many people who claim on their résumés to be proficient in C don’t know what happens behind malloc; people proficient in Python can’t write clean, beautiful code using metaprogramming. Such proficiency is really just barely “learning.”
By this standard, after ten years of muddling through, I can barely count as having “learned thoroughly” in C, can only say I’ve “learned” Python and JavaScript, and have only just begun to “understand” Erlang/Ruby.
Let me explain a bit more about why one should understand as many programming languages and their strengths and weaknesses as possible. For example, if the concurrency model of newly developed software is to adopt STM (Software Transactional Memory), and if, before technical selection, you know that Clojure implements STM at the language level and Haskell at the GHC level, then your choices might not be limited to the language you were previously using.
(六)
In any case, it is now quite impossible to turn back the clock. You cannot forever keep brooding over what might have been. You should realize that you have lived as well as most people—perhaps far better—and you should be content. - The Remains of the Day
Life is short,
[the] craft long,
opportunity fleeting,
experiment treacherous,
judgment difficult.
- Hippocrates
Perhaps the earlier gazing had used up too much energy—Little Bao began to yawn and rub her eyes. She turned her head, spread her arms, and looked at me with expectant eyes. I knew the little one wanted a hug.
Ten years ago I could never have imagined that ten years later I’d be so lucky, and so unexpectedly blessed, to have her—just as ten years from now I can’t predict what she’ll become. I can make “deliberate” plans for my career, and for her life, but I can’t control the outcome. In the past ten years I’ve come to many, many crossroads. As it says in The Remains of the Day, “You cannot forever keep brooding over what might have been.” What matters is that I made my choices. I’m glad my life’s experience is as rich as most people’s—perhaps far richer—and I’m glad I have so many, many stories to tell my child.
Oh, I forgot to mention another answer, the sixth—valid, of course, only for non-native English speakers:
Being able to read, write, and communicate freely in English.
What qualities exactly should an excellent programmer possess?
After nearly eight years of using vim, I’ve decided to give emacs a try.