LeetCode Is Like Doping in Sports

How to prepare for coding interview is an open secret nowadays.

Search for LeetCode in GitHub. For a software engineer who is serious about changing job, he just needs to commit a couple hours a day for a month or two, going through the one hundred and seventy-ish coding problems in LeetCode for two to three times. Then he is good to go. As long as he has been a workable developer before, with the help of LeetCode and such, plus books like “Cracking the Coding Interview”, the chance is very high for him to pass the coding interviews in nearly all software companies (including Facebook, Linkedin, Amazon, Microsoft, etc., with Google being probably the only exception) — although some may still fail to nail an offer due to other reasons like design (e.g. “Tell me, how to design the Timeline in Facebook”) or communication.

LeetCode and such are like doping in sports (except for the difference in legality). They are very effective boosters that raise your performance in coding interviews. But the boosters only last so long. Before long, you will go back who you truly are. As the result, in the recent years, repeatedly I have seen developers writing production code with bugs that will never pass coding interviews. Here is a few real examples of such bugs (with necessary obfuscation and slight simplification for formatting and other obvious reasons), which had all previously caused (sometimes very expensive) live site incidents — it would be a separate topic about how come they slipped through code review and uncaught by unit tests.

Example 1: what if the length of the tokens array is 1?

internal static IPSubnet ParseSubnet(string subnetString)
{
   string[] tokens = subnetString.Split(IPHelpers.PrefixDelimiter);
   IPSubnet subnet = new IPSubnet();
   subnet.Prefix = byte.Parse(tokens[1]);
   //more code...

   return subnet;
}

Example 2: what if link doesn’t contain “.vhd”?

private string GetImageName (Uri link)
{
   string str = link.ToString();
   int startPos = str.LastIndexOf("/") + 1;
   int endPos = str.LastIndexOf(".vhd", StringComparison.OrdinalIgnoreCase);
   return str.Substring(startPos, endPos - startPos);
}

Example 3: what if bufferSize is 0?

public static int GetIndex(int bufferSize)
{
   int index = 0;
   while ((bufferSize & 1) == 0)
   {
      index++;
      bufferSize = bufferSize >> 1;
   }
   return index;
}

Example 4: what if fromTime is Feb.29, 2012?

// Setting certificate expiry.
endTime.wYear = fromTime.wYear + 1;
endTime.wMonth = fromTime.wMonth;
endTime.wDay = fromTime.wDay;

I am sure the engineers who wrote these bugs weren’t like this during the coding interviews. It’s just that in their day to day work, they are not asking themselves these “what if” questions as they would have during interviews. That’s because it’s not a part of them. They don’t have that habit. Their performance during coding interview was the result of preparation and the boosters. As the result, it’s very sad that in today’s tech industry, people produce their best quality code only during job interviews.

Of course, software engineers must be able to write solid code really quick, just like soccer players must run fast, basketball players must jump high and chefs must be able to slice the onions very thin. Good scouts make sure the players run this fast or jump this high year around, and can tell if the guy’s performance today is because of 5 cans of Redbulls or not. The challenge for the hiring in tech industry is to be able to exclude the influence of the boosters and find out what the candidate is really capable of in day to day work.

How Do We Measure An Engineering Practice

Note: in this article, I raised a question without answer. Rather, I wanted to point out that we have a problem to work on and there is a large space for new innovations and opportunities.

The problem is: how do we measure an engineering practice. How do we prove it works/doesn’t work; how do we prove it’s superior than other ways; etc.

For examples,

  • How do we measure hackathon? How do we prove it works; how do we prove that hackathon brings values which we won’t get in other ways; etc.
  • How do we measure the return of investment in unit test?
  • How do we measure DevOps? How do we prove that it’s superior to other models
  • … (the list can go very long)

Take hackathon as an example. There are a lot of arguments in favor of it. Most of them are subjective, about personal feeling and observation, and appeal to perception and using reasoning rather than numbers. For example, some said “lots of good ideas emerged from hackathons”. Then the question would be: would these ideas have been emerged anyway in other ways? How to prove that some of these ideas would never have emerged without hackathon? For another example, some said “hackathon boosts team morale”. Then the question would be: how do you measure the boost? Are you sending a survey to the participants? In companies, such surveys are not to be trusted. People are afraid of say negative things, especial to the things arranged/sponsored/initiated by top executives. If someone say “we found good hires from hackathon”, then the question would be: could you have found good hire equally effectively (if not more effectively) through other ways? Some arguments were logically flawed: “Facebook does hackathon, Facebook is successful, so hackathon must help make a software company successful”.

Talk about unit test. If someone uses “unit tests will help cut bug count by up to 90%” to support unit test, the number will get questioned really hard, since no two projects are the same. In many other fields, such as in sociology, we can exam tens of thousands of similar samples and use statistical regression to prove that “being exposed to bilingual environment from age 0-6 will help boost the annual income at age 30 by 2.5%”. That kind of study and numbers in sociology is sound and solid. But we can’t do that for software engineering. We don’t have thousands of similar software companies/projects to study and come up with some numbers like “companies that heavily invested in unit test get boost in their revenue by 5%”. Many people (including me) strongly believe in unit test and practice it in our daily work, not because we were convinced by some statements like “smoking increases the chance of cancer by x%”, instead, because we tried it and found it was helpful.

Look at DevOps. There were some data to prove that’s a good idea. But these data are not that solid to pass strict exam. “Job satisfaction increased by 10%” — according to what? Some internal survey? We know that people “engineered” such surveys to get the result the way they want to see. “Release cycle shortened by 50%” — could that also have been equally effectively achieved without DevOps? “Live site incidents reduced by 30%” — May be the team was already on steady trend toward higher efficiency. It’s a common logic fallacy that people mistakenly think when two things happen in sequence, the first one is the cause of the second one.

By questioning these, I’m not arguing that we shouldn’t be searching for and trying out new ways in software engineering to be more effective and produce better outcome. We should never stop searching and trying and getting better.

When we think we are becoming more data driven to adopt new practices, our approach of advancing engineering practice is still very pragmatic today: some people has got ideas and go ahead trying. Sometimes it works, sometimes it doesn’t. When it works, they tell people. Others have tried, see the benefit, and tell more people. More people follow suit and over the time, it became common and popular and eventually everybody adopts it as a standard way of doing things. When we want ourselves to become more data driven, we should realize that the data we use are often weak evidences, misuses of statistics or subject to interpretation.

A Manager Must Hide The Disagreement?

I came across a blog post about being a manager. The author believes that a manager can disagree up, but can’t disagree down and if the manager disagrees with the company’s decision, he must hide that disagreement (in front of his team). Speaking from my own experience (nearly 10 years as a manager), that’s wrong.

For the completeness, here is the original words in the blog:

It is your responsibility as a manager to support the company’s decisions. Not just to execute on them, but to support them, to communicate that support, and if you disagree then you must hide that disagreement in the service of the company. You can disagree up — though even that is fraught with danger — but you can’t disagree down. You must hold yourself apart from your team, putting a wall between you and your team. To your team you are the company, not a peer.

The impact of complaints filtering up is much different than the impact of complaints filtering down. In some sense as a manager you must manufacture your own consensus for decisions that you cannot affect. You are probably doing your reports a favor by positively communicating decisions, as they will be doing themselves a favor by positively engaging with those decisions. But their advice is clear: if you are asked your opinion, you must agree with the decision, maybe stoically, but you must agree, not just concede. You must speak for the company, not for yourself.

The right way should be “disagree and say yes”. There are two reasons why a manager should do so, in front of his manager as well as his team:

  1. You can’t fake it. We are all grown-ups and we are all smart people (with college degree and working in good companies after harsh interviews and emerging from all the job seekers). So we don’t give bullshit to each other because we can easily tell and when someone does, we tell him “don’t give me the bullshit, treat me like an adult”. We do social lying (“hey, your daughter is so cute”) but we all know what it is. We have to be ourselves or it will be very difficult and stressful to keep telling the lies. Manager is a particularly stressful job (not only need to take care of yourself, but also take care a number of people who report to you, directly/indirectly), so you don’t want to add more stress to it or you get burned out very quickly.
  2. You want to be treated the same way by your team, when you ask them to do something or do things in some ways that they disagree. At work, sometime it’s a dirty work that I got from my manager (who may have got it from his manager, so on and so on) and I just need someone in my team to get it done. Sometime it’s the right thing to do, but may be uncomfortable — just like getting my boy to brush his teeth. In all those occasions, I want my team to just say yes and do it, though they disagree. To build a team like that, the key is to show them that the manager is doing the same to his own manager, just like one day our children will treat us the same way how we treat our own parents today.

At the end of the day, if one finds he’s in disagreement with the company or his management chain so often, it’s a sign that he should find another company or another team.

Comment on Box’s Flaky

Flaky is a test tool that Box shared with the community about a year ago. In my opinion and own experience, the tool solves the problem it wanted to solve, but it’s a poisonous tool to have for any engineering organization who wants sustainable success. Here is the comment that I left on their blog post:

I was in the same spot in the past: a few years back, we’ve had tests that failed intermittently and the causes sometime were external to our component, but in other services owned by folks in the other floor/building. Naturally, we built a similar way to rerun the failed tests automatically.

Later, I found a problem in this approach: it discouraged people from doing deep investigation and hide some bugs in our own component. Discourage: as long as the rerun passed, no one would look at the failure in the first run. Hide bugs: there are product bugs that have intermittent nature (rather than causing some functionality 100% failing); also, there were test automation bugs that genuinely cause intermittent test failures (lack of test repeatability, or test automation reliability issue). It was also a slippery slope: over the time, the amount of rerun increased (since no one spent time looking at why the tests failed on first attempt), which caused the total duration of the test pass to increase.

Seeing those problems, I stopped the rerun. I told the team because our component has deterministic nature (rather than fuzzy logic products like face recognition, speech, relevancy, machine learning, …), our tests should be deterministic and highly repeatable. I forced the team to investigate every intermittent failure. It turned out that we found a lot of genuine issues in the product code as well as the test automation. We fixed them. I also tenaciously push all the teams (not only my own team, but also folks on other floors/buildings) to improve the design/architecture so that it’s easier to write more repeatable test automation. It paid off pretty well. After about 1 year since stopping the rerun, the amount of flaky tests significantly dropped (from more than 5% of the entire test automation to <0.5%). The total duration of test pass dropped. People are less frustrated by dealing with intermittent failures all the time.

In short, having a tool to automatically rerun failed tests is poisonous. It makes life easier now, but sends your engineering toward the wrong direction.

The Maximum Possible Size of A Meatball

A few years back, I read a ThinkWeek paper about the engineering waste in Microsoft. It presented such a picture: from bug management to test case management, from continuous integration to deployment automation, for every problem in software engineering, there are a handful different tools in Microsoft to solve the same problem. It did look awful. The author was advocating for a consolidation of engineering systems within Microsoft and I was in the same camp.

But since then, more and more I realized that Microsoft’s problem is far from being unique. It’s kind of very common in the software industry nowadays. For examples,

  • On the List of unit testing frameworks, it listed more then 40 different kinds of unit testing frameworks for JavaScript, 35 for Java, 64 for C++ and 28 for .NET;
  • On Comparison of file comparison tools, there are 24 different text file comparison tools and there are a couple others that are not on that list but I have used in the past;
  • When it comes to code review, the list is also long: Phabricator from Facebook, Gerrit from Google, Crucible, … For more, just search online.

At last, look at how many programming languages we have.

It’s inevitable that when more people use a tool, it becomes harder for that tool to meet all the needs, including some volatile/subjective measurements like “easy to use” and “good UI”, as well as meet the needs in time. When a tool gets more bloated as more people keep contributing to it, it becomes harder to learn the tool. When a common lib is used in more systems, the odds of a code change in the common lib breaking somebody becomes higher. The cost and difficulty to ensure no such regression grows worse than linearly. As the number of people/organizations who share with the same tool grows, it will get to a point where these costs, risks and difficulties outweigh the benefits of continuing to stick together. Then the only natural thing is to fall apart.

It’s just like making the meatballs. Small meatball stays as a ball for days. But as the meatball gets bigger, it becomes harder to stick together. When the size reaches a certain point, regardless how much flours you add and how hard and for how long you press the meat together, the big meatball will just fall apart as soon as you put it down. That’s the maximum possible size of a meatball.

A Parking Lot in Downtown San Francisco and the Free and Open Internet

In my experience, if a resource is 1) valuable, 2) has no fee, 3) is in limited supply and 4) open to use, inevitably it will get abused. Its available capacity and liquidity will sooner or later drop to near zero.

That’s just human nature. For example, if there is a parking lot (=valuable) in downtown San Francisco (=limited supply) which is free to park (=no fee) and doesn’t have any time limit such as “free to park up to 2 hours” (=open to use), inevitably it will be full all the time. People will come in the morning and leave their cars there for the whole day — why not? It’s free and no time limit. If I pull my car out to run a few errands, I’m afraid my slot will be taken immediately and I won’t find a slot when I come back. Instead, I better put a folded bicycle in the trunk. I can ride the bicycle around in downtown, so that I can park my car there throughout the day for free.

This actually happened for real in my workplace, for more than once. The pattern was:

  • We had a test cluster on which people can create virtual machines to run their testing (=valuable resource)
  • The test cluster was already paid for by our team budget, so everyone in the team can use it for free (=no fee)
  • The test cluster wasn’t big enough for everybody to use freely, nor could we increase the capacity (=limited supply)
  • In the beginning, we didn’t apply any policy (=open to use)

What happened very soon was that the test cluster was full and remained full. We found that people just didn’t delete their virtual machines after their testing was done. The behavior was self-enforced because the fewer people release their virtual machines, the harder to get a new virtual machine. Everybody suffered, though we repeatedly told everybody “please use it responsibly and be considerate to other’s need”.

At last, we set up the quota and time limit: each one can have up to N virtual machines and it requires manager approval to get more than that; each virtual machine will be automatically deleted after X days unless explicitly renewed. That solved the availability and liquidity problem and no one complained about not having a “free and open” test cluster.

This is why there won’t be a “free and open” Internet without fees or quota. This is why President Obama’s rules won’t help, if not make things worse. In his statement today the net neutrality, he put forward a few rules including:

  • No blocking
  • No throttling
  • No paid prioritization

Internet bandwidth is a valuable resource and in limited supply. To avoid what happened to the parking lot in downtown San Francisco and my team’s test cluster, we have to do one way or another: either set some quota (blocking/throttling), or charge some fees (paid prioritization). Valuable resource + limited supply + no fee + open to use = no one can use.

I Want An Owl

Harry Potter has an owl, Hedwig. I want one, too. For many times, I wished I had one. That would have saved me a lot of time and hassles. Here are three examples.

Example one: repair my iPad. Last Saturday night, the home button on my iPad stopped working. I went to the Apple Store in the university village in Seattle on Sunday morning. The store was full of people and I was told that the waiting time would be half an hour. So I made an appointment in the afternoon, hoping that would get shorter wait. But when I came back and checked in on time, I still waited more than twenty minutes until I got help. The rest didn’t take more than a couple minutes. Since I was still in warranty, I simply got a replacement iPad. I wish I had an owl, which can carry my iPad to the store, get replacement and fly back, so that I don’t have visit the Apple Store in person and wait in line.

Example two: pharmacy trip. We were traveling in San Francisco last year and in that night, my boy had fever and cough. My wife needed help but we had to get some Tylenol. It was after midnight and not quite easy to get a cab. It took me about an hour to get the Tylenol from a 24-hours pharmacy several miles away. If I had an owl, I would have sent my owl to the pharmacy so that I could stay with my boy and give my wife help.

Example three: garage door. Yeah, there are many people like me: I often don’t remember whether I have shut my garage door, so I come back from a few blocks away to double check. For the record, I did forget for a couple times. So it wasn’t always wasteful. But if I had an owl, I would keep going and send my owl back to take a peek. After that, the owl would fly back to where I am, which might have been several miles away from where I launched her.

Harry Potter’s owl only lives in the books and movies. The owl that I want will be a drone, a smart drone. It may take quite a few years to get there: that I can send my smart drone to run the errands for me. There will be things to iron out, such as what if somebody shoots down my drone and takes my replacement iPad; how will it launch and land in urban area; etc.. Affordability is a thing, too. But thirty years ago, a PC wasn’t too affordable and twenty years ago, a cell phone wasn’t too affordable.

I believe the dream will come true and when I am old, I will send my drone to pick up my prescriptions rather than going to the Walgreens by myself.

Exploratory Mode of GPS

GPS is making traffic congestion worse, as more people more rely on GPS to find their way home. GPS’ routing algorithm is so repeatable that from a given point A to point B, it always gives the same route (note: recently some GPS devices introduced the “eco” mode, whose routing algorithm optimize for less fuel instead of less travel time. But it doesn’t change the deterministic nature of GPS routing algorithm). Some time some people want to take a bit detour, knowing the local roads (rather than the highway that GPS suggested), which cars drive slower though, may have much less traffic which eventually may result in less travel time. But GPS always faithfully and promptly recalculate and suggest a new route leading back to the congested highway. I don’t have the exact data but I believe that as the result of GPS recommending the same route to everybody, the worth of time and fuel wasted and the extra emission will add up huge.

Another problem of GPS always recommending the same route is that it deprives our opportunity to explore. The best way to know the area that I live is to see where there are what in my own eyes. Often times, when I drive passing a corner, I noticed a nice shop and remembered to pay a visit later; I noticed that there was a farmer’s market on that street on Saturday morning; I noticed that there was a drive-through 24 hours Walgreens on that block; so on and so on. To me personally, such way (knowing my area by driving around) works better than Bing/Google maps, Yelp and yellow pages. Also, when I’m travelling in other cities, I have abundant time and I want to drive around to discover the things that I won’t see if I just follow GPS’ directions from A to B.

So for those two reasons, I think GPS should have the exploratory mode (or maybe “Surprise Me” would be a catchier name): instead of reliably always recommend the same route with the least travel time (or least fuel consumption), I hope I can switch my GPS into the exploratory mode, so that it adds some detours, as far as it only adds a couple minutes travel time or a couple miles distances. Better if the GPS can remember where I have been already recently, so that next time when it introduces the detour in exploratory mode, it takes me to the neighborhood where I haven’t been to recently.

Such exploratory mode may also enable a new monetization way: local business can pay the GPS/map providers so that the exploratory mode increases the odds to detour the driver to where that local business is.

In my opinion, such exploratory mode will be a good differentiator in today’s market, not too hard to implement and increases profitability.

Why Startups Use Misspelled Names

When I read the news these days, I see lots of startups using misspelled words as their names, though when you read them, they pronounce like legit words. A few of them have grown pretty big, such as: Flickr (flicker), Tumblr (tumbler) and Reddit (read it).

There are more out there:

The list goes on and on.

Why they are using misspelled words as company names? In one of his post, Jeff Knupp said: “Start-ups don’t make developers wear multiple hats by choice, they do so out of necessity“. Similarly, I believe startups chose the misspelled words as their names out of two necessities.

First, domain names are very expensive. It was said that XiaoMi paid tens of millions of dollars for the new domain name mi.com (was xiaomi.com). I also heard that JD.com paid a lot for the new domain name, to replace 360buy.com. I haven’t seen any rumor about box.com, but I believe the price tag must be at least multi million. To get more idea about the hefty price tag on domain names, go to godaddy.com and check it out.

Second, I guess those misspelled names are good SEO (search engine optimization). For example, see what you can get by searching for “louder” in Bing. But if you search for “loudr”, loudr.fm pops up as the first result.

Firefighting vs. Fire Prevention

One of my team members shared this article with me: Treat bugs as fires. The author said,

“There are software devs who follow a different approach. They focus on fire prevention, not fire cure. Sure, they have to put out fires. But they use each fire as an opportunity to learn how to prevent fires, and then they build new parts of the city in a way that prevents the fires they have seen. Over time, these teams live in cities that don’t burn down. They go weeks and months between alarms going off. They rarely even have building code violations (risks found by QA or build verification tools).”

There are very few number of such teams. It’s because balancing between firefighting vs. fire prevention is hard:

1. Firefighting is heroic and many managements reward such heroic behavior. If they don’t do so, there will be no fire fighters. The dilemma is: then, preventing fire is less rewarded than firefighting and it’s human nature to go after bigger rewards. So fewer people will do fire prevention and more people will do firefighting.

2. Few people stay in the same place long enough to start to harvest from their investments in fire prevention. To optimize for the outcome in 18 months, I would rather to cut a lot corners in order to ship a lot of shining features, get a promotion, and move on. The corner-cutting will hurt us after 2-3 years, but why would I care if I am not here anymore?

Both need to be address by the managements:

For (1), the managements have to first be conscious about how he/she is rewarding firefighting vs. fire prevention. Then find out a balanced way to encourage fire prevention while keep firefighters a desired job.

For (2), attrition is natural, but the managements can keep people stay a bit longer and can make ownership stable. It also depends on the management’s judgment. Management needs to point it out when people cut corner and punish people if it’s too much.

That’s why the management is so critical (especially the first line as well as middle management). If the management fails to steer the team toward the right balance between firefighting vs. fire prevention, or the management themselves only plan to be here for 18 months, the team/product has little chance to thrive.

Where we are in the history of software

I have been always thinking that we are very early in the history of software. Using timepiece as a metaphor:

  • The software in the 50’s and 60’s were like the sundial.
  • The software in the 80’s are like the clock made in 16th century: need to be wound daily, and off by a couple minutes daily.
  • The software today are somewhat like the first generation of pocket watch, such as those made by John Harrison: they are pretty sophisticated and works really well, but each of them took John a dozen years to make.

Today there are very few number of watches are handmade. Most of them are hand-assembled, or purely machine made. When we look at the craftsmanship a few centuries ago, we don’t think their techniques are too impressive. A teenage today probably knows everything that the greatest mathematics and physicists knows in the 17-18th century. I believe, in maybe 50 years from now, when people look back at us and how we make software today, they will have similar feeling.

Today, all software are handmade. It has been talked for a decade or two about producing software in the way how today’s plants produce cars. But I believe there will be another several decades when that become true. By the time we retire, I believe most of the software will be written by software. There will be very few of software engineers at that moment. Their main job is to write the “seed” software or component, to kick-start the whole software-writing-software chain. When software is written by software, bugs will be like the fires.