Pragmatic Programmer - Notes

Aug 22 2020
While You Are Coding

We should avoid programming by coincidence—relying on luck and accidental successes—in favor of programming deliberately.

Always be aware of what you are doing. If you're not sure why it works, you won't know why it fails. Proceed from a plan, but be ready to change the plan if the environment changes. Prioritize your effort. Spend time on the important aspects.

Test your assumptions.

Document your assumptions, and also test your assumptions. If your assumption is right, you can make better, informed choice. If your assumption was wrong, well, be glad you tested it.

Don’t let existing code dictate future code. All code can be replaced if it is no longer appropriate. Even within one program, don’t let what you’ve already done constrain what you do next—be ready to refactor


If you don't have fundamentals or infrastructure correct, brilliant bells and whistles will be irrelevant. Prioritize your effort. Spend time on the important aspects.

Why Write Tests

Testing is part of programming. To write good tests, you have to understand the code you are writing the tests for. That's a huge benefit of writing tests. We usually work with a slight understanding of the code and think that we will worry about the edge cases, or error handling later, and never come to it.

Naming Things

Things should be named according to the role they play in your code. When you consider the role of a variable or function, you’re thinking about what is special about it, about what it can do, and what it interacts with. Rename and refactor when your understanding of a thing changes. Avoid misleading names.

Requirements: No one knows exactly what they want

Requirements rarely lie on the surface. Normally, they’re buried deep beneath layers of assumptions, misconceptions, and politics. Even worse, often they don’t really exist at all.

The typical client comes to us with a need. A response to a current problem. The need may be for a change to an existing system or it may ask for something new, can be either expressed in business terms or in technical ones. The mistake new developers make is to take this need and implement a solution for it. Good programmers help the clients understand what exactly they want.

Requirements are learned in a feedback loop. Your job is to help the client understand the consequences of their stated requirements. You do that by generating feedback, and letting them use that feedback to refine their thinking. 

Even at the end of a project we’re still interpreting what our client wants. In fact, by that point we’re likely to have more clients: the QA people, operations, marketing, and maybe even test groups of customers.

Maintain a glossary.

As soon as you start discussing requirements, users and domain experts will use certain terms that have specific meaning to them. Create and maintain a project glossary—one place that defines all the specific terms and vocabulary used in a project. All participants in the project, from end users to support staff, should use the glossary to ensure consistency. This implies that the glossary needs to be widely accessible—a good argument for online documentation.

Solving Impossible Puzzles

Identify the real (not imagined) constraints, and find a solution therein. Some constraints are absolute; others are merely preconceived notions. Absolute constraints must be honored, however distasteful or stupid they may appear to be.

The key to solving hard problems is both to recognize the constraints placed on you and to recognize the degrees of freedom you do have, for in those you’ll find your solution.

Go for a walk, work on something different. Let your unconscious brain work on the problem in the background. However, in order to have those eureka! moments, your nonconscious brain needs to have plenty of raw material; prior experiences that can contribute to an answer.  Or, explain the problem to someone, or even a rubber duck.

Ask questions. Why are you solving this problem? Do you really need to solve it? Has it been solved before? Is there a simpler problem you can solve, instead?  Continuously get feedback on what works and what doesn’t work as you do your daily job.

Were you handed a set of constraints when you signed on to yourcurrent project? Are they all still applicable, and is the interpretation of them still valid?

The Essence of Agile
  • Work out where you are.
  • Make the smallest meaningful step towards where you want to be. 
  • Evaluate where you end up, and fix anything you broke. 
  • Repeat until done. 

Context Matters

Have you or your team fallen in this trap? Ask yourself, why are you even using that particular development method? Or that framework? Or that testing technique? Is it actually well-suited for the job at hand? Does it work well for you? Or was it adopted just because it was being used by the latest internet-fueled success story?

Do What Works, Not What's Cool or Fashionable

There’s a current trend to adopt the policies and processes of successful companies such as Spotify, Netflix, Stripe, GitLab, and others. Each have their own unique take on software development and management. But consider the context: are you in the same market, with the same constraints and opportunities, similar expertise and organization size, similar management, and similar culture? Similar user base and requirements?

The Real Goal

The goal of course isn’t to “do Scrum,” “do agile,” “do Lean,” or what-have-you. The goal is to be in a position to deliver working software that provides value to your users by giving them more capability. 

 Civilization advances by extending the number of important operations we can perform without thinking. 

Ruthless and Continuous Testing

Many developers test gently, subconsciously knowing where the code will break and avoiding the weak spots. Pragmatic Programmers are different. We are driven to find our bugs now, so we don’t have to endure the shame of others finding our bugs later. Test Early, Test Often, Test Automatically.

Testing Thoroughly

How do you know if you have tested the code base thoroughly enough? The short answer is “you don’t,’’ and you never will.

Find Bugs Once, Fix them twice

Once a human tester finds a bug, it should be the last time that bug occurs, no matter how rare you think it is. Because it will happen again. And we just don’t have the time to go chasing after bugs that the automated tests could have found for us. We have to spend our time writing new code—and new bugs. 

So fix the bug as soon as you or QA find it, and immediately put a system in place so that that bug never happens again. 

Delight Your Users

Our goal as developers is to delight users, not just delivering working software in a timely manner, but to actually make our users happy when they use our software.

Users have a problem that needs solving within the context of their objectives and budget. It’s these expectations of business value that really count—not just the software project itself. The software is only a means to these ends.

Make sure you know about your users' expectations before you start working on a project. Continue to think about them as you progress, and try to not only meet them, but exceed them when you finish.

Talk to other departments

As our knowledge of the domain increases, we’re better able to make suggestions on other things that could be done to address the underlying business issues. Developers, who are exposed to many different aspects of an organization, can often see ways of weaving different parts of the business together that aren’t always obvious to individual departments.

Sign Your Work

Take pride in your work. “I wrote this, and I stand behind my work.” Your signature should come to be recognized as an indicator of quality. People should see your name on a piece of code and expect it to be solid, well written, tested, and documented. A really professional job. Written by a professional.

A Pragmatic Programmer.

The Shortness of Life

May 16 2020
Life will follow the path it began to take, and will neither reverse nor check its course. It will cause no commotion to remind you of its swiftness, but glide on quietly. It will not lengthen itself for a king’s command or a people’s favour. As it started out on its first day, so it will run on, nowhere pausing or turning aside. What will be the outcome? You have been preoccupied while life hastens on. Meanwhile death will arrive, and you have no choice in making yourself available for that.

It is not that we have a short time to live, but that we waste a lot of it. Life is long enough, and a sufficiently generous amount has been given to us for the highest achievements if it were all well invested.

In any situation in life you will find delights and relaxations and pleasures if you are prepared to make light of your troubles and not let them distress you.

So you have to get used to your circumstances, complain about them as little as possible, and grasp whatever advantage they have to offer: no condition is so bitter that a stable mind cannot find some consolation in it.

We are not given a short life but we make it short, and we are not ill-supplied but wasteful of it. Just as when ample and princely wealth falls to a bad owner it is squandered in a moment, but wealth however modest, if entrusted to a good custodian, increases with use, so our lifetime extends amply if you manage it properly.

Life is long if you know how to use it.

You will find no one willing to share out his money; but to how many does each of us divide up his life! People are frugal in guarding their personal property; but as soon as it comes to squandering time they are most wasteful of the one thing in which it is right to be stingy.

You are living as if destined to live for ever; your own frailty never occurs to you; you don’t notice how much time has already passed, but squander it as though you had a full and overflowing supply – though all the while that very day which you are devoting to somebody or something may be your last.

You will hear many people saying: ‘When I am fifty I shall retire into leisure; when I am sixty I shall give up public duties.’ And what guarantee do you have of a longer life? Who will allow your course to proceed as you arrange it? Aren’t you ashamed to keep for yourself just the remnants of your life, and to devote to wisdom only that time which cannot be spent on any business? How late it is to begin really to live just when life must end! How stupid to forget our mortality, and put off sensible plans to our fiftieth and sixtieth years, aiming to begin life from a point at which few have arrived!

No activity can be successfully pursued by an individual who is preoccupied.

Living is the least important activity of the preoccupied man; yet there is nothing which is harder to learn.

You must not think a man has lived long because he has white hair and wrinkles: he has not lived long, just existed long.

Each of us could have the tally of his future years set before him, as we can of our past years, how alarmed would be those who saw only a few years ahead, and how carefully would they use them!

On the value of reading and writing philosophy: This is the only way to prolong mortality – even to convert it to immortality. Honours, monuments, whatever the ambitious have ordered by decrees or raised in public buildings are soon destroyed: there is nothing that the passage of time does not demolish and remove. But it cannot damage the works which philosophy has consecrated: no age will wipe them out, no age diminish them. The next and every following age will only increase the veneration for them, since envy operates on what is at hand, but we can more openly admire things from a distance. So the life of the philosopher extends widely: he is not confined by the same boundary as are others.

It is inevitable that life will be not just very short but very miserable for those who acquire by great toil what they must keep by greater toil.

In this kind of life you will find much that is worth your study: the love and practice of the virtues, forgetfulness of the passions, the knowledge of how to live and die, and a life of deep tranquillity.

Everlasting misfortune does have one blessing, that it ends up by toughening those whom it constantly afflicts.

You must consider whether your nature is more suited to practical activity or to quiet study and reflection, and incline in the direction your natural faculty and disposition take you.

You must especially avoid those who are gloomy and always lamenting, and who grasp at every pretext for complaint. Though a man’s loyalty and kindness may not be in doubt, a companion who is agitated and groaning about everything is an enemy to peace of mind.

It is easier to bear and simpler not to acquire than to lose, so you will notice that those people are more cheerful whom Fortune has never favoured than those whom she has deserted.

How much happier is the man who owes nothing to anybody except the one he can most easily refuse, himself!

Think your way through difficulties: harsh conditions can be softened, restricted ones can be widened, and heavy ones can weigh less on those who know how to bear them.
Should Nature demand back what she previously entrusted to us we shall say to her too: ‘Take back my spirit in better shape than when you gave it. I do not quibble or hang back: I am willing for you to have straightway what you gave me before I was conscious – take it.’ What is the harm in returning to the point whence you came? He will live badly who does not know how to die well. So we must first strip off the value we set on this thing and reckon the breath of life as something cheap. To quote Cicero, we hate gladiators if they are keen to save their life by any means; we favour them if they openly show contempt for it. You must realize that the same thing applies to us: for often the cause of dying is the fear of it.

He who fears death will never do anything worthy of a living man. But he who knows that this was the condition laid down for him at the moment of his conception will live on those terms, and at the same time he will guarantee with a similar strength of mind that no events take him by surprise. For by foreseeing anything that can happen as though it will happen he will soften the onslaught of all his troubles, which present no surprises to those who are ready and waiting for them, but fall heavily on those who are careless in the expectation that all will be well.

‘What can happen to one can happen to all.’ If you let this idea sink into your vitals, and regard all the ills of other people (of which every day shows an enormous supply) as having a clear path to you too, you will be armed long before you are attacked. Know, then, that every condition can change, and whatever happens to anyone can happen to you too.

The next thing to ensure is that we do not waste our energies pointlessly or in pointless activities: that is, not to long either for what we cannot achieve, or for what, once gained, only makes us realize too late and after much exertion the futility of our desires.

We should also make ourselves flexible, so that we do not pin our hopes too much on our set plans, and can move over to those things to which chance has brought us, without dreading a change in either our purpose or our condition, provided that fickleness, that fault most inimical to tranquillity, does not get hold of us.

So we should make light of all things and endure them with tolerance: it is more civilized to make fun of life than to bewail it.

The mind should not be kept continuously at the same pitch of concentration, but given amusing diversions.

We must indulge the mind and from time to time allow it the leisure which is its food and strength. We must go for walks out of doors, so that the mind can be strengthened and invigorated by a clear sky and plenty of fresh air. 

Books I read in 2019

Jan 01 2020
  1. It doesn't have to be crazy at work
  2. Autobiography of Benjamin Franklin
  3. The Subtle Art of Not Giving a F**k
  4. Meditations
  5. Competing Against Luck
  6. Buffett's biography
  7. Brain Book
  8. Skin in the Game
  9. The Everything Store
  10. Peak
  11. The Little Book of Talent
  12. Risk Savvy
  13. The 4-Hour Workweek
  14. Wise Guy
  15. Enchantment by Guy Kawasaki
  16. Mysterious affair at Styles
  17. Manual by Epictetus
  18. Warren Buffett Speaks
  19. Disrupted
  20. Badass: Making Users Awesome
  21. I will teach you to be rich
  22. Purple Cow
  23. Crush It!
  24. How to Fail at Everything and Still Win Big
  25. Chop wood, carry water
  26. Food Rules
  27. The Art of Worldly Wisdom
  28. Refactoring
  29. Code Complete

Are your lights on?

Nov 30 2019
This is my collection of highlights and notes from Gerald Weinberg's Are Your Lights On? It's not a summary, but rather a copy + paste of the text that resonated with me most.
Are Your Lights On?
A problem is a difference between things as desired and things as perceived. 

The fledgling problem solver invariably rushes in with solutions before taking time to define the problem being solved. Even experienced solvers, when subjected to social pressure, yield to this demand for haste. When they do, many solutions are found, but not necessarily to the problem at hand. 

Without some common understanding of the problem, a solution will almost invariably be to the wrong problem. Usually, it will be the problem of the person who talks loudest, or most effectively. 

Early during your problem solving phase, ask yourself:
  • Who has a problem?
  • What is the essence of the problem?
Since any problem is a difference between a perceived state and a desired state, when we change a state to "solve" a problem, we usually create one or more other problems. Put simply, each solution is the source of the next problem. 

We never get rid of problems. Problems, solutions, and new problems weave an endless chain. The best we can hope for is that the problems we substitute are less troublesome than the ones we "solve". 

When something goes wrong in the software, we're inclined to blame the user, rather than the person who made the software. Human beings are so adaptable, they'll put up with almost any sort of bugs - until it comes to their consciousness that it doesn't have to be that way. Then comes trouble. 

Accompany a foreign traveler through your own country, for through the foreigner's eyes you will once again perceive the strangeness and awkwardness of your own culture. Take some object (piece of code) that you handle ever day. See it from the point of view of someone from another country who has never seen one before. Each new point of view will produce new issue to be addressed with the solution. 

Don't solve other people's problems when they can solve them perfectly well themselves. 

Many problems in our society stem from systems designers and decision makers who don't experience the problems they're "responsible" for. 

Try blaming yourself for a change. Think about the problem as being "my" problem, rather than somebody else's problem. 

Where problems come from? The source of a problem often contains some key element in its resolution. 

Most people with problems think they know what these problems are. They are usually wrong. Most people also think that they are not very good problem solvers. However, many times solving a problem is rather easy - once we know what the problem is. 

Most of us have had schooling - too much of it. We've developed an instinct that makes us seize upon the first statement that looks like a problem. Then we solve it as fast as we can, because exams focus on speed. 

In spite of appearances, people rarely know what they want until you give them what they ask for. 

Not too many people, in the final example, really want their problem solved, e.g. the treasurer who kept finding fault in the computer program because his salary was dependent on the job that the computer was trying to replace. 

A question that every would-be problem solver should ask before seriously embarking on any problem: Do I really want a solution? Though the question seems shocking, sometimes the "solution" isn't at all welcome, because it may put the solver out of a job. 

We never have enough time to do it right, but we always have enough time to do it over. OR,
We never have enough time to consider whether we want it, but we always have enough time to regret it. 

While solving problems, we often tend to regard "side effects" as the result of particular solutions. "They might not arise at all, and if they do, we can always refine the solution to eliminate them." How often does this naive attitude lead us into disaster?

The fish is always the last to see the water. 
When we contemplate problems, items to which we are habituated tend to be omitted from consideration. Only when the solution causes the removal of the habituated element do we become startled. The problem solver must strive to see the "water" in which the other participants unconsciously swim - the water which will be transformed to sand when the problem is "solved". 

My Job Went to India

Nov 16 2019
Well, not really. But it was the old title of Chad Fowler’s excellent book I am reading, which offers solid career advice for programmers. If you are a programmer, and want to keep your job and not get outsourced, you’d be doing yourself a favor by reading this book.


Aug 20 2019
Very little time is spent in writing code. Most programmers spend their time debugging and figuring out what's going on in the codebase they are working with. Fixing the bug is usually pretty quick, but finding it is usually hard. Refactoring is a skill that every software developer must have.
Refactoring needs tests. Read the code, gain some insight, and use refactoring to move that insight from your head back into the code. The cleaner code then makes it easier to understand it, leading to deeper insights and a beneficial positive feedback loop. This process will improve your conceptual mental models of the codebase and simplify your understanding of the domain. 

Code Smells
  1. Mysterious Name, that doesn't indicate the purpose of a variable, function, class or a module.
  2. Duplicated Code
  3. Long Function, Large Class
    • Difficult to understand and change
    • Does too many things
  4. Long parameter list
  5. Data clumps, 3/4 items together in lots of places
  6. Primitive obsession

Fundamental Refactoring Techniques

  1. Extract Method
    1. If you have to spend effort looking at a fragment of code and understand what it’s doing, then extract it into a function and give it an intention-revealing name. 
    2. Then, when you read it again, the purpose of the function leaps right out at you, and most of the time you won’t need to care about how the function fulfills its purpose (which is the body of the function).
    3. Extract small pieces first. Before you extract this small piece of a monster method, it looks like it won’t make any difference at all. After you extract more pieces, you’ll probably see the original method in a different way. You might see a sequence that was obscured before or see a better way for the method to be organized. When you see those directions, you can move toward them. 
    4. This is a far better strategy than trying to break up a method into large chunks from the beginning. Too often that isn’t as easy as it looks; it isn’t as safe. It’s easier to miss the details, and the details are what make the code work.
  2. Extract Variable
    1. Expressions can become very complex and hard to read. In such situations, local variables may help break the expression down into something more manageable. 
    2. In particular, they give me an ability to name a part of a more complex piece of logic. This allows me to better understand the purpose of what’s happening. They also improve debugging. 
  3. Rename Methods and Variables
    1. So that the code is more expressive and reads better like a prose. 
  4. Introduce Parameter Object
    1. For groups of data items that regularly travel together, appearing in function after function. 
    2. If you create a class for these items, you can capture the common behaviour over this data into class methods and add validation. 
  5. Combine Functions Into Class
    1. When I see a group of functions that operate closely together on a common body of data (usually passed as arguments to the function call), I see an opportunity to form a class. 
    2. Using a class makes the common environment that these functions share more explicit, allows me to simplify function calls inside the object by removing many of the arguments, and provides a reference to pass such an object to other parts of the system.
    3. This refactoring also provides a good opportunity to identify other bits of computation and refactor them into methods on the new class.

    Identify secrets that modules should hide from the rest of the system. 

  1. Encapsulate Record
    1. Favour objects over records/tuples. You can hide what is stored and provide methods to access the data. 
  2. Encapsulate Collection/Mutable data
    1. This makes it easier to see when and how data is modified. You can simply put a breakpoint on the setter. 
    2. Common mistake: Access to a collection variable may be encapsulated, but if the getter returns the collection itself, then that collection's membership can be altered without talking to the encapsulation.
    3. Force changes to the collection go through the owning class, giving you the opportunity to modify such changes as the program evolves. 
    4. Ensure that the getter for the collection does not return the raw collection, so that the users cannot accidentally change it. Instead, return a copy of the underlying collection. (watch out for huge collections)
  3. Replace Primitive with Object
    1. Often in the beginning, you represent simple facts as simple data items, such as numbers or strings. As development proceeds, those simple items aren't so simple anymore. 
    2. Create a new class for this data. Initially, it does little more than wrap the primitive, but you have a place to put behaviour specific to its needs. 
  4. Replace Temp with Query
    1. If you are breaking up a large function, turning temporary variables into their own functions makes it easier to extract parts of the function, as you no longer need to pass in variables to the extracted functions. 
    2. Allows you to avoid duplicating calculation logic everywhere, if the variables are calculated in the same way in different places. 
  5. Extract Class
    1. Classes grow as development goes on and become bloated. A class with many methods and a lot of data is too complicated to understand easily. Split it. 
    2. A good sign to know when to split a large class is when a subset of the data and a subset of the methods seem to go together. 
  6. Move Function 
    1. If a function references elements in other contexts more than the one it currently resides in, move that function together with those elements. 
    2. Move all the data and elements used by the chosen function if they fit in the new context. 
    3. Rename the function to fit the new context. 

Simplifying Conditional Logic

  1. Extract Conditional to a Function
    1. Complex conditional logic is one of the most common sources of complexity in a program. 
    2. Move the complicated conditional logic to a function with an intention-revealing name. 
    3. If you are doing a series of conditional checks where each check is different yet the resulting action is same, consolidate them into a single conditional check with the resulting action. 
  2. Replace Conditional with Polymorphism
    1. If you have several functions that have a switch statement on a type code, 
    2. Remove the duplication of the common switch by creating classes for each case and using polymorphism to bring out the type-specific behavior. 
  3. Introduce Special Case / Introduce Null Object
    1. If you find many parts of a code base having the same reaction to a particular value, bring that reaction into a single place. 
  4. Introduce Assertions
    1. Often, sections of code work only if certain conditions are true. 
    2. Such assumptions are often not stated, but can only deduced by looking through the algorithm, sometimes the assumptions are stated with a comment. 
    3. A better technique is to make the assumption explicity by writing an assertion. 
    4. An assertion is a conditional statement that is assumed to be always true. Failure of an assertion indicates a programmer error. 

Refactoring APIs

  1. Separate Query from Modifier
    1. A function should do only one thing. Differentiate between functions with side effects and those without. 
    2. Any function that returns a value should not have any side effects. 
    3. If you come across a method that returns a value but also has side effects, always separate the query from the modifier. 
  2. Remove Setters if not needed
    1. If you don't want a property to change once the object is created, don't provide the setter and make it immutable (read-only)
    2. Initialize the property in the constructor. 
  3. Replace Constructor with Factory Function/Class
    1. Factory function will call the constructor, but you can replace it with something else while testing. 
  4. Replace Function with Method Object / Command Object
    1. There are times when it's useful to encapsulate a function into its own object, called a command object. 
    2. The sole purpose of the command object is the execution of the method it's replacing. 


  1. Pull Up Method/Data
    1. If methods/data are duplicated in the subclasses, pull them up into the super class. 
  2. Push Down Method/Data
    1. If a method/data is only relevant to one subclass, removing it from the super class and putting it only on the subclass makes that clearer. 
  3. Replace Type Code with Subclasses
    1. This allows you to use polymorphism to handle conditional logic. This is most useful when you have several functions that invoke different behavior depending on the value of the type code. 
    2. With subclasses, you can apply "replace conditional with polymorphism". 
  4. Extract Superclass
    1. If you see two or more classes doing similar things, then pull their similarities together into a superclass. 
    2. Use 'Pull up data' and 'Pull up method' refactorings to move the common behavior. 

  1. Save the code you start with. Make sure you are using version control. 
  2. Make sure you can get back to the code you started with. 
  3. Make sure you have a test for the piece of code you are trying to refactor
  4. Keep refactorings small, and do them one at a time. 
  5. Don't mix different refactorings into a single commit. If you find one, add a comment to come back to it later. 

Jobs To Be Done

Mar 27 2019
What is the jobs-to-be-done?
  • A job is essentially the progress that a person is trying to make in a particular circumstance. 
  • When we buy a product, we essentially hire something to get a job done. 
  • Deeply understanding your customers' struggle for progress and then create the right solution and experiences to ensure you solve your their jobs well, every time. 
Questions to ask:
  • What progress is that person trying to achieve?
  • What are the circumstances of the struggle? Who, when, where, while doing what?
  • What obstacles are getting in the way of the person trying to make that progress?
  • What does success mean for them? With what trade-offs?
  • What causes that person to use a particular product and service?
How to identify jobs?
  • If you observe people employing a workaround or "compensating behavior" to get a job done, pay close attention. It's usually a clue that you have stumbled on to a high-potential innovation opportunity. 
  • What are the important, unsatisfied jobs in your own life, and the lives of those closest to you? 
  • Observe your customers using your products. In what circumstances do they use them? What are the functional and emotional dimensions of the progress they are trying to make? Are they using them in unexpected ways? 
How to trigger a change?
  • Identify the forces that compel change to a new solution. What circumstances create these forces? How can you improve them?
  • Identify the forces that oppose any change. What circumstances are creating these forces? How can you eliminate/reduce them?
How to get hired for a job?
  • New products succeed not because of the features and functionality they offer but because of the experiences they enable. 
  • Figure out what do you need to design, develop, and deliver in your product offering so that it solves the consumer's job well? 
The Goal
  • To develop your brand, one that customers automatically associate with the successful resolution of their most important jobs. 
  • A successful brand provides a clear guide to the outside world as to what your company represents
Avoid This
  • Surface Growth: Trying to create many products for many customers - and losing focus on the original job that brought you success in the first place. Hurts your brand. 
  • As you grow up, it's very common to lose focus on the job that sparked your existence in the first place. You start to act as if your business is defined by the products and services you sell, instead of the jobs that you solve. 

Books I read in 2018

Jan 15 2019
As a bibliophile, 2018 was a great year. I read 70 books and skimmed through many more, averaging at least five books per month. Here is a list of all the books I read last year.
  1. The Age of Absurdity
  2. Cracking the Tech Interview
  3. Show Your Work
  4. The Pattern on the Stone
  5. Rework
  6. The Art of War
  7. Mastermind
  8. Being Geek: The Software Developer’s Career Handbook
  9. The Pragmatic Programmer
  10. The Bed of Procrustes
  11. Free Will
  12. I Will Teach You To Be Rich
  13. Algorithms to Live By
  14. The Book of Five Rings
  15. On the Shortness of Life
  16. Why We Sleep
  17. Hit Refresh
  18. Organize Tomorrow Today
  19. 101 Things I learned In Engineering School
  20. 101 Things I learned In Advertising School
  21. 101 Things I learned In Architectural School
  22. What Got You Here Won’t Get You There
  23. Sum: 40 tales from the afterlife
  24. The 5 Elements of Effective Thinking
  25. Game Theory 101: Bargaining
  26. The Systems Mindset
  27. Brain Rules
  28. Dollars and Sense
  29. Change your brain, change your body
  30. Tribe of Mentors
  31. The Meaning of It All
  32. Who Moved My Cheese
  33. The Decision Checklist
  34. Triggers
  35. The Death of Expertise
  36. EntitleMania
  37. Deep Survival
  38. Skin in the Game
  39. Life Changing Manga of Tidying Up
  40. The Life-Changing Magic of Tidying Up
  41. Food: What the heck should I eat
  42. Thinking In Bets
  43. Stumbling on Happiness
  44. Everyone believes it: Most will be wrong
  45. Designing Your Life
  46. The Design of Everyday Things
  47. Finding Flow
  48. The Halo Effect
  49. Education of a Value Investor
  50. A Wealth of Common Sense
  51. Antidote
  52. Playing to Win: Strategy
  53. Errors
  54. The Investor’s Manifesto
  55. Thinking in Systems
  56. The Phoenix Project
  57. The Wizard of Lies
  58. The Dip
  59. The Art of Living - Epictetus
  60. Bad Blood
  61. The Effective Engineer
  62. Fighting Hydra
  63. How not to move back in with your Parents
  64. Genghis Khan and the Making of the Modern World
  65. A Random Walk Down Wall Street
  66. Young Money
  67. So Good They Can’t Ignore You
  68. Atomic Habits
  69. Seeking Wisdom
  70. Uses and Abuses of History

Young Money

Dec 21 2018
This is not a summary, but rather a collection of my highlights & notes from the text that most resonated with me, while reading Young Money: Inside the Hidden World of Wall Street's Post-Crash Recruits.
Young Money
For years, thousands of graduates of the world’s most prestigious colleges and universities have gone to Wall Street, most only halfway knowing what they’re getting themselves into. 

Most of the young Wall Street workers, especially first-year analysts in the investment banking divisions work the longest hours. It’s not uncommon for a first-year IBD analyst to work one hundred hours a week - the equivalent of sixteen hours a day during the week, then a mere ten hours on each weekend day. However, this doesn’t mean they are actually doing one hundred hours’ worth of work every week. In fact, many sit around idly for hours a day, listening to music or reading their favorite blogs while they wait for a more senior banker to assign them work. Most of these hand-offs happen at 6.30 or 7.00 pm as the senior banker is leaving for the day, giving the analyst a graveyard shift’s worth of work before he or she can go  home and sleep. 

Most of a first-year IBD analyst’s work revolves around gathering, organizing, and presenting financial data. If an investment bank is trying to convince one of its clients, that it should buy another company (to get the hefty commission in the process), the bank’s analysts first have to gather every available nugget of financial information about those companies, their competitors and the entire sector. Revenues, expenditures, margins, buybacks, dividends, trends, changes, stocks - all of this information, and much more, must be gathered, transformed and fit into ‘models’, which are nothing but big Excel spreadsheets that are used to calculate the specifics of the deal being proposed.

Once the model is made, the most information in it is put into tidy, organized charts and graphs, inserted into a template, and turned into a ‘pitch book’ - a professionally bound, attractive-looking book that, over the course of several hundred pages, tells Microsoft why, exactly, it should buy Github and how much it should pay. However, taking into account the incentives of the investment bank, this information is highly biased, skewed, and manipulated to cause the deal. (Never ask a barber whether you need a haircut!).

The investment banks are ruthless about making sure models and pitch books - both called “deliverables”, are perfect, down to the last comma and decimal point. And that’s where analysts come in. An MD wants a bar graph instead of a line graph on page 63, and it’s 3 am? A good analyst will wake up and snap into action. A VP finds a broken cell reference in cell L57  of an Excel model on Christmas Day? The analyst had better wait to open presents. It’s not the hours that kill you - it’s the lack of control of the hours, one analyst told the author. 

For first-year financiers - who just months earlier were happy, autonomous college students - the process of becoming human stock for Wall Street’s labor mill can be a blunt trauma. Among the young bankers the author interviewed, he saw disillusionment, depression, and feelings of worthlessness that were deeper and more foundational than simple work frustrations. 

Every year on Wall Street, first-year analysts who were once courted by college recruiters with lines about how they would be given meaningful, creative work and the chance to learn from top executives are shown the harsh truth: they are excel grunts whose work is often meaningless not just in the cosmic sense, but in the sense of being seen by nobody and utilized for no productive purpose. Some of the hundred -page pitch books analysts spend their late-night hours fact-checking in painstaking detail are simply thrown away after being given a quick skim by a client. In other cases, the client doesn’t read the deliverables at all, and the analysts’ work is literally garbage. 

If you calculate the hourly wage of wall street analysts, based on the number of hours they actually work, it often comes down to $15-$16 hours after taxes. 

Bad Blood

Oct 30 2018
In October, I dove deep into theme reading on scandals. Spent the cold nights binge-reading three wonderful books on the major frauds in three different industries. The biggest Ponzie scheme ever, the biggest medical fraud in Silicon Valley, and the collapse of Enron.

Bad Blood
This is one of the best-written books. Finished the 300-page book in a two-day reading marathon. It is an impeccably researched account of the Theranos saga. John Carreyrou is a two-time Pulitzer Prize-winning investigative reporter at the WSJ, and after reading the book, now I know why. Loved his writing style. He does the difficult job of explaining complex medical jargon to laypeople extremely well, and you never lose the central plot throughout the book. The book shows the insidious effects of ambition and growth gone horribly wrong.
The Wizard of Lies
Had to slog through this one, but I am glad I read it. Reveals deep insights into human nature. Adjusted for inflation, Madoff was already making millions of dollars from the legitimate sources of his business, and was already rich beyond belief. This book also shows how so many financial experts, hedge-fund managers, and wall-street analysts can be just as ignorant when it comes to investments, falling prey to social influences, biases and human irrationality. An interesting case study on perverse systems and wrong incentives.
The Smartest Guys in the Room
Skimmed this one, which chronicles the collapse of Enron, one of the most admired companies of the 1990. The book is very long, and I didn’t read most of it. Ended up reading the executive summaries. It can be a good read for business students, just to know what to avoid.

What Got You Here

Jun 13 2018
This is one of the rare management books that has a high signal to ratio. Most of them usually have one or two points to make and fill the rest of the book with anecdotes and examples to stretch the book.

The main thesis of the book is to avoid stupidity. 
  • We spend a lot of time learning what to do. We don't spend enough time learning what to stop. 
You need to learn what to stop doing, along with learning what to do more. Know when to stop.
what got you here.jpg 32.61 KB
The book lists twenty annoying habits. They are as follows.
  1. Winning too much: Know when it matters, when it doesn't, and when it's totally beside the point. 
  2. Adding too much value: The overwhelming desire to add our two cents to every discussion.
  3. Passing judgement: The need to rate others and impose our standards on them. 
  4. Making destructive comments: The needless sarcasms and cutting remarks that we think make us sharp and witty. 
  5. Starting with "No", "But", or "However": To suggest subtly, "I'm right. You're wrong." 
  6. Telling the world how smart we are. (Personally, I suffer from this and seriously need to stop.)
  7. Speaking when angry: Using emotional volatility as a management tool. 
  8. Negativity, or "Let me explain why that won't work": The need to share our negative thoughts even when we weren't asked. 
  9. Withholding information: The refusal to share information to maintain an advantage over others. 
  10. Failing to give proper recognition: The inability to praise and reward. 
  11. Claiming credit that we don't deserve.
  12. Making excuses.
  13. Clinging to the past.
  14. Playing favorites: Failing to see that we are treating someone unfairly. 
  15. Refusing to express regret.
  16. Not listening: The most passive-aggressive form of disrespect for colleagues. 
  17. Failing to express gratitude. The most basic form of bad manners. 
  18. Punishing the messenger. The misguided need to attack the innocent who are usually only trying to help us.
  19. Blaming others, except ourselves. 
  20. An excessive need to be "me": Hold in high regard our faults as virtues simply because they're who we are. 

Domain Driven Design

Jun 05 2018
After procrastinating for years due to its sheer size, I have finally picked up and started reading DDD. This is a must-read for developers of object-oriented software working on a complex domain. I found myself nodding on almost every sentence in this book, relating so much to my work at CityView, which has a super-complex domain of municipal software.
  • Every software program relates to some activity or interest of its user. That subject area to which the user applies the program is the domain of the software.
  • The heart of the software is its ability to solve domain-related problems for its user. All other features, vital though they may be, support this basic purpose.
  • To create software that is valuably involved in users’ activities, a development team must bring to bear a body of knowledge related to those activities. The breadth of knowledge required can be daunting. The volume and complexity of information can be overwhelming.
  • The messiness of most software domains is actually an interesting technical challenge. Creating a lucid model that cuts through the complexity is exciting.
Problems DDD solves:
  • When we set out to write software, we never know enough. Knowledge on the project is fragmented, scattered among many people and documents, and it’s mixed with other information so that we don’t even know which bits of knowledge we really need.
  • Domains that seem less technically daunting can be deceiving: we don’t realize how much we don’t know. This ignorance leads us to make false assumptions.
  • Domain experts are usually not aware of how complex their mental processes are as, in the course of their work, they navigate all these rules, reconcile contradictions, and fill in gaps with common sense. Software can’t do this. It is through knowledge crunching in close collaboration with software experts that the rules are clarified, fleshed out, reconciled, or placed out of scope.
  • Models are tools for grappling with this overload. A model is a selectively simplified and consciously structured form of knowledge. An appropriate model makes sense of information and focuses it on a problem.
  • Every model represents some aspect of reality or an idea that is of interest. A model is a simplification. It is an interpretation of reality that abstracts the aspects relevant to solving the problem at hand and ignores extraneous detail.
  • Useful models seldom lie on the surface. As we come to understand the domain and the needs of the application, we usually discard superficial model elements that seemed important in the beginning, or we shift their perspective. Subtle abstractions emerge that would not have occurred to us at the outset but that pierce to the heart of the matter.
Do we need Business Analysts?
  • In the old waterfall method, the business experts talk to the analysts, and analysts digest and abstract and pass the result along to the programmers, who code the software.
  • This approach fails because it completely lacks feedback. The analysts have full responsibility for creating the model, based only on input from the business experts. They have no opportunity to learn from the programmers or gain experience with early versions of the software. Knowledge trickles in one direction but does not accumulate.
  • A team of developers and domain experts collaborate, typically led by developers. Together they draw in information and crunch it into a useful form.
  • The constant refinement of the domain model forces the developers to learn the important principles of the business they are assisting, rather than to produce functions mechanically. The domain experts often refine their own understanding by being forced to distil what they know to essentials, and they come to understand the conceptual rigour that software projects require.
  • Domain experts have limited understanding of the technical jargon of software development, but they use the jargon of their field.
  • Developers, on the other hand, may understand and discuss the system in descriptive, functional terms, lacking the meaning carried by the experts’ language.
  • Across this linguistic divide, the domain experts vaguely describe what they want. Developers, struggling to understand a domain new to them, vaguely understand.
  • On a project without a common language, developers have to translate for domain experts. Domain experts translate between developers and still other domain experts. Developers even translate for each other. Translation muddles model concepts, which leads to destructive refactoring of code.
  • A project faces serious problems when its language is fractured. Domain experts use their jargon while technical team members have their own language tuned for discussing the domain in terms of design.
  • The terminology of day-to-day discussions is disconnected from the terminology embedded in the code.
The Solution: Ubiquitous Language
  • A project needs a common language. The domain model can provide the backbone for that common language, while connecting team communication to the software implementation.
  • The vocabulary of that UBIQUITOUS LANGUAGE includes the names of classes and prominent operations. The LANGUAGE includes terms to discuss rules that have been made explicit in the model. It is supplemented with terms from high-level organizing principles imposed on the model.
  • The model-based language should be used among developers to describe not only artifacts in the system, but tasks and functionality. This same model should supply the language for the developers and domain experts to communicate with each other, and for the domain experts to communicate among themselves about requirements, development planning, and feature.
How to Get There?
  • Initially the model may simply not be good enough to fill these roles. It may lack the semantic richness of the specialized jargons of the field. But those jargons can’t be used unadulterated because they contain ambiguities and contradictions.
  • It may lack the more subtle and active features the developers have created in the code, either because they do not think of those as part of a model, or because the coding style is procedural and only implicitly carries those concepts of the domain.
  • Persistent use of the UBIQUITOUS LANGUAGE will force the model’s weaknesses into the open. The team will experiment and find alternatives to awkward terms or combinations. As gaps are found in the language, new words will enter the discussion. These changes to the language will be recognized as changes in the domain model and will lead the team to update class diagrams and rename classes and methods in the code, or even change behavior, when the meaning of a term changes.
  • Committed to using this language in the context of implementation, the developers will point out imprecision or contradictions, engaging the domain experts in discovering workable alternatives.
  • Domain experts should object to terms or structures that are awkward or inadequate to convey domain understanding; developers should watch for ambiguity or inconsistency that will trip up design.
  • Recognize that a change in the UBIQUITOUS LANGUAGE is a change to the model.
  • When domain experts use this LANGUAGE in discussions with developers or among themselves, they quickly discover areas where the model is inadequate for their needs or seems wrong to them.
  • The domain experts (with the help of the developers) will also find areas where the precision of the model-based language exposes contradictions or vagueness in their thinking.
  • The developers and domain experts can informally test the model by walking through scenarios, using the model objects step-by-step. Almost every discussion is an opportunity for the developers and user experts to play with the model together, deepening each other’s understanding and refining concepts as they go.
Summary: Developers and domain experts have a close relationship. Domain-driven design crunches a huge amount of knowledge into a model that reflects deep insight into the domain and a focus on the key concepts. This is a collaboration between those who know the domain and those who know how to build software. Because development is iterative, this collaboration must continue throughout the project’s life.

Thinking in Systems

Apr 13 2018
Since reading Meditations by Marcus Aurelius, I had yet to come across a book with such a high signal to noise ratio. Just finished reading Thinking in Systems by Donella Meadows, and this fits the bill. I had to pause, think and ponder after reading each paragraph in order not to miss the profound underlying concepts. Very easy to read, this is one of those books that changes how you look at the world.
Thinking in Systems
What is a system?
A system is a set of things - people, cells, molecules, or whatever - interconnected in such a way that they produce their own pattern of behaviour over time, to achieve something. A system must consist of three things: elements, interconnections, and a function or purpose. Some examples include the digestive system, a company, solar system, etc.

How to identify a system?
  • Can you identify the parts?
  • Do the parts affect each other?
  • Do the parts together produce an effect that is different from the effect of each part on its own?
  • Does the effect, the behaviour over time, persist in a variety of circumstances?
Some properties of a system
  • Changing individual elements usually has the least effect on the system
  • If the interconnections change, the system may be greatly altered. It may even become unrecognizable, even though the same elements are in the system.
  • Changes in function(non-human systems) or purpose(human ones) also can be drastic.
Why Systems work so well

  • Resilience is a measure of a system’s ability to survive and persist within a variable environment.
  • It arises from many feedback loops that work to restore a system even after large deviation. Having redundancy is hugely important.
  • A set of feedback loops that can restore or rebuild feedback loops is going one higher level. Self-organization.
  • Resilience is not the same thing as being static or constant over time. Resilient systems can be very dynamic. Short-term oscillations, or periodic outbreaks, or long cycles of succession, climax, and collapse may, in fact, be the normal condition, which resilience acts to restore. Conversely, systems that are constant over time can be very fragile.
  • Loss of resilience can come as a surprise because the system usually is paying much more attention to its play than to its playing space. One day it does something it has done a hundred times before and crashes.
  • The most marvellous characteristic of some complex systems is their ability to learn, diversify, complexity, and evolve.
  • Self-organizing systems can arise from simple, basic rules.
  • A brilliant systems invention, provides a system stability and resilience.
  • Reduces the amount of information that any part fo the system has to keep track of, e.g. If you have a liver disease, a doctor can treat it without paying much attention to your heart or your personality. While programming in C#, I am not worried about binary or assembly code.

Why Systems surprise us

Linear minds in a Nonlinear world
  • Everything we think we know about the world is a model. Every word and every language is a model. So are the ways I picture the world in my head - my mental models. None of these is or ever be the real world.
  • Our models usually have a strong congruence with the world. However, our models fall far short of representing the world fully. This is both a blessing and a curse.
  • One cannot navigate well in an interconnected, feedback-dominated, complex world without taking their eyes off short-term events and look for long-term behaviour and structure; unless one is aware of false boundaries and bounded rationality; unless one takes into account limiting factors, nonlinearities and delays.
  • The sudden swing between exponential growth caused by a dominant reinforcing loop, and then sudden decline caused by a suddenly dominant balancing loop.
  • Side-Effects: Effects which one hadn’t foreseen or don’t want to think about. Black-swan events (Nassim Taleb).
  • Being less surprised by complex systems is mainly a matter of learning to expect, appreciate, and use the world’s complexity.

System Boundaries

If you wish to make an apple pie from scratch, you must, first, invent the universe - Carl Sagan.

  • There is no single, legitimate boundary to draw around a system. There are no separate systems. The world is a continuum. Where to draw the boundary around a system depends on the purpose of the discussion. The questions we want to ask.
  • Boundaries can produce problems when we forget that we’ve artificially created them. When we draw them too narrowly, the system surprises us. e.g. To avoid the sewage problem. If we draw the boundary around our home, we can throw the waste in the river. But the towns downstream make it clear that the boundary for thinking about sewage has to include the whole river.
  • We get attached to the boundaries our minds happen to be accustomed to. National boundaries, trade boundaries, ethnic boundaries, boundaries between public and private responsibility, between rich and poor, polluters and polluters. It is a great art to remember that boundaries are of our own making and that they can and should be reconsidered for each new discussion, problem, or purpose.

Layers of Limits
  • At any given time, the input that is most important to a system is the one that is most limiting. (It took me some time to wrap my head around this statement)
  • Any system with multiple inputs and outputs is surrounded by layers of limits.
  • There always will be limits to growth. They can be self-imposed. If they aren’t, they will be system-imposed.

Bounded Rationality
  • It would be nice if Adam Smith’s “Invisible Hand” was true, but it isn’t, most of the time.
  • Unfortunately, the world presents us with multiple examples of people acting rationally in their short-term best interests and producing aggregate results that no one likes. (While reading this, I couldn’t help but reflect on how so many problems in India are caused by this Tragedy of the Commons).
  • Bounded rationality means that people make quite reasonable decisions based on the information they have. But they don’t have perfect information, especially about more distant parts of the system.
  • We are not omniscient, rational optimizers. Rather, we are blundering “satisfiers” attempting to meet our needs well enough before moving on to the next decision. We often don’t foresee (or choose to ignore) the impacts of our actions on the whole system.
  • Trading Places: Suppose you are for some reason lifted out of your accustomed place in society and put in the place of someone whose behaviour you have never understood. It can be thought in both directions. Not only rich can be poor, but also poor can be rich. In your new position, you experience the information flows, the incentives and disincentives, the goals and discrepancies, the pressures - that go with that position. Would that such transitions could happen much more often, in all directions, it would broaden everyone’s horizons and increase empathy.
  • Seeing how individual decisions are rational within the bounds of the information available does not provide an excuse for narrow-minded behaviour. It provides an understanding of why that behaviour arises. Blaming the individual rarely helps create a more desirable outcome. Change comes first from stepping outside the limited information that can be seen from any single place in the system and getting an overview.
  • From a wider perspective, information flows, goals, incentives, and disincentives can be restructured so that separate, bounded, rational actions do add up to results that everyone desires.
Leverage Points: Places to intervene in a system
Places in the system where a small change could lead to a large shift in behaviour. Listed below in the increasing order of importance and leverage, and impact they produce.

Physical - Low leverage

12: Numbers
  • Important, especially in the short term.
  • Changing these variables rarely changes the behaviour of the system. However, they become leverage points when they kick off one of the items higher on this list, e.g. interest rates reinforcing compounding interest can make a big difference.
11: Buffers
  • In chemistry, a stabilizing stock is known as a buffer.
  • You can often stabilize a system by increasing the capacity of a buffer. If a buffer is too big, the system gets inflexible. It reacts too slowly, and costs a lot to build or maintain.
10: Stock and Flow structures
  • A stock is the foundation of any system. They are the elements of the system that you can see, feel, count, or measure at any given time.
  • Stocks change over time through the actions of a flow.
  • The plumbing structure of the stocks and flows and their physical arrangements can have an enormous effect on how a system operates. But it’s a rarely a leverage point, because changing it is rarely quick or simple. The leverage point is in proper design in the first place.
9: Delays
  • A delay in a feedback process is critical, relative to rates of change in the stocks that the feedback loop is trying to control. Delays that are too short cause overreaction. Delays that are too long cause damped, sustained, or exploding oscillations. Overlong delays in a system with a threshold, a danger point, a range past which irreversible damage can occur, cause overshoot and collapse.
  • Delays in feedback loops are critical determinants of system behaviour.
  • A system just can’t respond to short-term changes when it has long-term delays. That’s why a massive central-planning system, such as the Soviet Union or General Motors, necessarily functions poorly.
Information and Control - High Leverage

8: Balancing Feedback Loops
  • A stabilizing, regulating feedback loop which opposes or reverses whatever direction of change is imposed on the system. Any balancing feedback loop needs a goal, a monitoring and signalling device to detect deviation from the goal, and a response mechanism.
  • A complex system usually has numerous balancing feedback loops to self-correct under different conditions and impacts. They might be inactive most of the time, but their presence is critical to the long-term welfare of the system. One of the big mistakes we make is to strip away these emergency response mechanisms because they aren’t often used and they appear to be costly.
  • The strength of a balancing feedback loop is important relative to the impact it is designed to correct.
7: Reinforcing Feedback Loops
  • An amplifying or enhancing feedback loop, which reinforces the direction of change. These are vicious cycles and virtuous circles. The more it works, the more it gains the power to work some more, driving system behaviour in one direction.
  • Reinforcing feedback loops are sources of growth, explosion, erosion, and collapse in systems. A system with an unchecked reinforcing loop ultimately will destroy itself. Usually, a balancing feedback loop will kick in sooner or later.
6: Information Flows
  • The structure of who does and does not have access to information. Missing information flows is one of the most common causes of system malfunction.
  • Adding or restoring information can be a powerful intervention, delivering feedback to a place where it wasn’t going before.
  • This is a high leverage point, often popular with the masses, unpopular with the powers that be, and effective, if you can get the powers that be, to permit it to happen.
5: Rules - Incentives, punishments, constraints
  • The rules of the system define its scope, its boundaries, its degrees of freedom.
  • Strong leverage points. Power over the rules is real power. If one wants to understand the deepest malfunctions of systems, pay attention to the rules and to who has power over them.
Crucial Leverage Points. These are more abstract but most effective

4: Self-Organization
  • The ability of a system to structure itself, to create new structure, to learn, or diversify. The power to add, change, or evolve system structure.
  • The most stunning thing living systems and some social systems can do to change themselves utterly by creating whole new structures and behaviours. In biology, it’s called evolution.
  • The ability to self-organize is the strongest form of system resilience. A system that can evolve can survive almost any change, by changing itself.
3: Goals
  • The purpose or function of the system. All the leverage points above can be twisted to conform to the goal of the system.
  • Changing the actors in the systems is a low-level intervention, as long as the players fit into the same old system. The exception is at the top, where a single player can have the power to change the system’s goals.
2: Paradigms
  • The mindset out of which the system - its goals, structures, rules, delays, parameters arise
  • The shared idea in the stocks of a system, the great big unstated assumptions, constitute the system’s paradigm, or the deepest set of beliefs about how the world works.
  • Paradigms are the sources of systems. From them, arise the shared agreements about the nature of reality, system goals, and information flows, feedbacks, stocks, flows, and everything else about systems.
  • We might think that the paradigms are harder to change than anything else. However, it can happen in a millisecond, in a single individual. All it takes is a new way of saying. We change paradigms by building a model of the system, which takes us outside the system and forces us to see it whole. (My own paradigms have been changed that way, after leaving India and coming to Canada).
1: Transcending Paradigms
  • The highest leverage point is to keep oneself unattached in the arena of paradigms, to stay flexible, to realize that no paradigm is “true”, that everyone including the one that sweetly shapes your own worldview, is a tremendously limited understanding of an immense and amazing universe that is far beyond human comprehension.
  • It is to “get” at a gut level the paradigm that there are paradigms, and to see that that itself is a paradigm, and to regard that whole realization as devastatingly funny.
  • It is to let go into not knowing, it is to embrace into uncertainty, into what the Buddhists call enlightenment.
Living in a World of Systems
  • It is one thing to understand how to fix a system and quite another to wade in and fix it. For those who stake their identity on the role of omniscient conqueror, the uncertainty exposed by systems thinking is hard to take.
  • Systems thinking leads to another conclusion as we stop being blinded by the illusion of control. It says that there is plenty to do, of a different sort of “doing”. The future can’t be predicted, but it can be envisioned and brought lovingly into being. Systems can’t be controlled, but they can be designed and redesigned. We can’t surge forward with certainty into a world of no surprises, but we can expect surprises and learn from them and even profit from them.
  • Before you disturb the system in any way, watch how it behaves. This simple guideline helps to avoid many wrong turns down the line. Starting with the behaviour of the system forces you to focus on facts, not theories. It keeps one from falling too quickly into one’s own beliefs or misconceptions, or those of others.
  • Watching what really happens, instead of listening to peoples’ theories of what happens, can explode many careless causal hypotheses.
  • Starting with the behaviour of the system directs one’s thoughts to dynamic, to static, analysis - not only to “What’s wrong?” but also to “how did we get there?”, “What other behaviour modes are possible?”, “If we don’t change direction, where are we going to end up?”
  • Remember, always, that everything one knows and everything everyone knows, is only a model. Instead of becoming a champion for one possible explanation or hypothesis or model, collect as many as possible. Consider all of them to be plausible until you find some evidence that causes you to rule one out. This is the scientific method.
  • When one’s walking along a tricky, curving, unknown, surprising, obstacle-strewn path(a complex world), one would be a fool to keep their head down and look just at the next step in front of them. One would be equally a fool just to peer far ahead and never notice what’s immediately under one’s feet.

The Google Resume

Jan 25 2018
While preparing for the Microsoft and CityView interviews, I did a lot of meta reading on interviews and resume building. I came across a few really good resources such as The Google Resume from Gayle Laakmann McDowell. I also read a bunch of blog posts which I have grouped in this same post. 
This doesn't cover everything, but I think it covers the most important foundational elements. Also, this is not a summary and/or my thoughts on the interviews, but a collection of my notes and highlights from the books and blogs that resonated with me, so if the tone of the text sounds different, that's probably why. Here we go..

Setting expectations

If this is your first time looking for a job, or you haven't had to interview in a number of years, expect to invest some effort in preparing for the interview. It's usually the industry professionals that completely ignore this step, but some college students do as well. 

You're essentially studying for a test, don't slack off - it's going to be work. All of those things that you've been telling yourself don't matter (maybe you're a bit fuzzy on how exactly the internet works - do you really know what happens after you hit enter on the URL bar?) that you don't know - now it's time to address those gaps head on. 

For the sake of space, I'm going to focus on what a fresh grad needs to do to prepare and that's more consistent across companies (and it's a shorter list).

Data Structures

  • Array
  • Linked List
  • Stack/Queue
  • Trees (Tree, Binary Tree, Binary Search Tree, Red-Black Tree, etc. Learn as many as you can)
  • Heap
  • Hash Table (this is really important - understand all of the different collision mitigation mechanisms, understand what amortized constant-time means)
  • Directed/Undirected/Weighted Graphs
  • Trie (pronounced "tree")
  • Linked Hash Map (this is very specific, but comes up a LOT in interviews)
You should know the Big-O for insert, delete, lookup, etc. for each of these. Know how the mechanics work. It isn't a good interview questions, but you should be able to code every single one of these. Then, prepare real-world examples of when you'd want to use each of these and explain why it's the best choice. Data Structures come up in technical interviews in two way. The first is in coding questions where you're expected to use the right one at the right time. The second is on a comparison question - not connected to code - "why would you use X over Y in situation Z."


Again, make sure you actually code these for real when practicing. Simply reading code someone else wrote will not cut it. Open up your favorite IDE and start typing. This is critical because often times you actually have a gap in your knowledge, but your brain convinces you it's ok (this happens without you even realizing it). The only way to find these gaps is by writing code. Know all of the Big-O for this and how it's derived.

You don't have to go crazy here, but review a couple of:
  • Sorting algorithms (both comparison sorting and non-comparison sorting)
  • Tree traversals (just memorize all of these inorder, preorder, postorder, level order)
  • Traversals - Dijkstra's, A*, BFS, DFS (know the difference between DFS and BFS when would you use one over the other and why - hint, is usually matters when you don't have to search the whole space. Also make sure that you can code recursively and using your own stack/queue)
  • All the prefix-tree searches
Great, you're about 60% done now. Now you need to practice applying this knowledge. Find a source of interview questions (random websites, glassdoor.com, cracking the coding interview, etc.) Code answers to those questions. 

I strongly recommend forcing yourself to pretend you're in an interview setting. Most of these questions should be solvable in ~10-15 minutes, some will be more like 20-25. Time yourself. Before you write a single line of code, organize your thoughts and figure out the entire solution, then start coding. 

The coding part should be boring and straightforward. In the actual interview, do the same thing. Before you write a single line of code, make sure that you validate with the interviewer that your approach is a good one. Practice practice practice this stuff.

Fill Gaps

This is where you get to be honest with yourself. That long list of things you don't know that you keep telling yourself is ok because the stuff you don't know isn't actually important....well, it is. Even if it isn't, your interviewer might think it is and it's better to have a job than be right. Here's a list off the top of my head that I hear people say isn't important (but you really should know).
  • Writing code - (I put this here half as a joke. I can't tell you how many people with 15+ years of experience lose their mind when I ask them tow write some code with me. These "architects" do not end up getting jobs. Same goes for managers and other support positions. I know that you're not going to write production code, that's fine - you should be able to write some code, though.)
  • Bits and Bytes - Yes, you should understand how all that bitshifting stuff works in whatever language you're going to interview with. You should know what big and little endian are. Do a couple practice questions, even simple one. Try something like..."write a method to determine if the bit-wise representation of an integer is a palindrome."
  • How the internet works. This applies more to companies....yeah....it applies to everything these days. You should know how sockets work, you should know what TCP/IP is. You should know what HTTP actually is. Learn your networking layers and what's responsible for what. You don't need to know all of the details of the protocols, but you should know some of them and that they exist. This sounds daunting, it should only take a couple of hours.
  • Databases. Learn some basic SQL and data modeling if the job you're applying for uses databases.
  • Learn a bit about testing. Write some code and test it. What's TDD
  • If you've only ever used Windows....consider using linux for a bit.
  • Whatever else you can think of. A good mental exercise is to imagine yourself in an interview..."man, I hope they don't ask me about X." Figure out what X is and read about it.
The good news is, the things on this list usually are far easier to learn than you think they will be. These are usually scars from undergrad or gaps from a non-traditional route to CS that sound hard. They're all easier to tackle than you think.


Alright, almost done. Tech interviews aren't all about tech (they mostly are these days, but not completely). You need to come across as someone people want to work with. Smile, be energetic, be excited about the company, know what they do, have ideas about what they could be doing. You're almost certainly going to encounter some behavioral interview questions. You can prepare for these. 

I suggest coming up with 3 situations where you were working on a tech project and things went well, and 3 stories for when things didn't go well. Then practice telling the stories, make sure to include some setup information, what was the setting, what was the project, who was working with you, what was your role...then tell the story....then for the positive stories talk about the impact of your work, did you win, save the company money, what? For the negative stories, finish up by talking about what you learned and how you'd approach the problem differently in the future.

Parting Words

Get a good nights sleep and do the best you can. Expect to fail at some of these interviews, that's ok, treat it as a learning experience and recognize that there are both good and bad interviewers. It's possible for a terrific candidate to get thrown to a bunch of shitty interviewers and not end up with a job (happens more than people like to talk about). That isn't to say that you should use this as an excuse to not learn from the experience, but interviewing is a game. Don't try and fight the rules or think it's stupid. It is what it is and that's what's standing between you and the job you want. Learn to play the game and win by practicing :-)

Best of luck, sorry for the typos. For the people just getting started, you aren't a fraud, we all know how little fresh college grads know, we factor that in to the ramp-up process. Be prepared to work hard.

Don't Sell Past the Close 

To all you extroverts out there, I can't tell you how many times someone's been just a bit too honest. When I'm interviewing you, I'm your best friend. My goal is to get you as relaxed as possible for a couple of reasons. First (and really the main motivating factor in choosing to be nice), your performance is best reflected when you're relaxed. Freaking people out is expensive because some awesome engineers just freeze up when overly stressed in interviews (I've also found little correlation between interviewing-stress-paralysis and real-world-fire-drill-paralysis). 

I'm nice because I don't want to exclude certain types of introverts from the hiring pool. The other reason I'm nice is because extroverted people think we're friends. We aren't friends, I'm interviewing you. I don't care how much you think you're clicking with your interviewer. He's invited you on his boat already, etc. You aren't friends, so don't run your mouth.

It's human nature to want to form bonds with people and one way we make friends with people is by doing this elaborate dance of sharing secrets with people. Early on there's a tendency to share some extra truths, usually fairly mild, but in an interview setting - bad idea. Things I've heard:
"Yeah, I know it sounds impressive. But hey, between you and me, I only really had to work 5-6 hours a day to get it done."
"I know I'm not supposed to say this in an interview, but the real problem was my co-worker. He was such a stickler for the littler details we could never get any code pushed out." (Actually anything that would start with "I know I'm not supposed to say/talk about this in an interview - just avoid that).

Don't over-share. If you think something is going to make you look bad, it probably will.

Exceptions to this rule: There are a few things that people think are bad which are perfectly fine: 
  • Admitting you don't know something (better than making stuff up) 
  • Asking questions to make sure you understand the problem 
  • Saying that you're a bit nervous and want to take a couple seconds to compose yourself (totally fine, don't be overly dramatic about it, though)
You can be friends with the interviewers you like after you get hired. Don't give people reasons not to hire you for free.

Age of Absurdity

Jan 10 2018
I usually don’t read satire, but so far the best one has been “The Age of Absurdity” by Michael Foley, and it was one of the best books I read in 2017. It critiques the eccentricities of modern life, revealing some rather uncomfortable truths. I have tried to summarize the book to the best of my understanding, but it goes much deeper than my naive first impressions.
age of absurdity.jpg 36.56 KB
The book covers a broad range of topics from philosophy, spirituality, literature, psychology, and neuroscience for common ideas on fulfilment and happiness. It then investigates how easy or difficult it might be to apply such strategies in contemporary life, amplified by a culture of high expectations, conspicuous consumption, shallow partnerships and perpetual youth.

Entitlement and Potential
In this chapter, the author takes his stabs on an entitled, selfie-possessed, narcissistic and attention-seeking culture. There are some uncomfortable, but true passages in here. The demand for attention is increasingly strong, a consequence of inner emptiness requiring identity conferred by the approval of others. The need to be acknowledged as an individual is common in humans. In its extreme form this becomes a craving for celebrity, the desire to be noticed not just now and then by a few, but to be bathed always in recognition, admiration, envy and desire. This is also related to narcissistic self-promotion on social media and internet, and the desire to be famous.

The book explores the topic of endless potential, which can turn into a form of greed that believes there is always something better just ahead. Whatever is actually happening today is already so yesterday, and the only true excitement is the Next Big Thing - the next lover, job, project, holiday, destination or meal. As a consequence, the most attractive solution to problems is flight, to move on, or abandonment.

There is a related passage from another chapter, which I think is relevant here. In the age of entitlement, everyone wants to appear superior to everyone else, resulting in intellectual or other types of snobbery and a false sense of superiority. Much consumption or social media behaviour is driven by a futile attempt to get ahead of the pack - or a defensive need to avoid falling too far behind.

Modern Self-Help
This is my favourite chapter. It beautifully critiques the modern self-help industry, which incessantly promotes that you can have anything you desire, become anyone you wish to be and there are no limits to potential, achievement, and reward. The universe is an endless conveyor belt of prizes and all you have to do is send your wishful thoughts into the universe, and it will promptly deliver them to you (Remember the secret, anyone?). It’s a refreshing chapter, and reveals the many fallacies of naive wishful thinking, resulting from self-deception, self-justification and faulty self-righteousness.

A good chunk of the chapter is devoted to how we fool others, and in turn ourselves. The human capacity for self-deception and the talent for self-justification is extraordinary. The author humorously says ‘when it comes to justifying actions, every human being acquires the intelligence of an Einstein, the imagination of a Shakespeare, and the subtlety of a saint.’ There are good examples provided in the book to prove that not only does irrefutable evidence fail to destroy a delusion, it can actually reinforce and intensify the false belief. Unable to tolerate two dissonant beliefs, the mind simple eliminates the more inconvenient of the two.

The author explores the topic of depression and anxiety. I believe he relates it to modern self-help and self-esteem movement. ‘I must succeed’; ‘Everyone must treat me well’; ‘The world must be easy’; ‘The Universe owes me everything’. The first must is the curse of perfectionism, the second must is the curse of neediness, and the third must is the curse of plain stupidity.

The Assault on Detachment
The thesis of this chapter is what you need is detachment, concentration, autonomy and privacy, but what the world insists upon is immersion, distraction, collaboration and company. It mostly explores the topic of divided attention and being in a constant distracted state, and its long-term effects on the brain. My favourite part is his critique of open-plan offices.

A significant chunk is devoted to the ill-effects of self-esteem. The author concisely and very humorously attacks the modern self-esteem movement. It is both entertaining and thought-provoking at the same time. There is a lot of sarcasm and mockery of the sub-genre of self-help devoted to boosting self-esteem. There is a quote from Albert Ellis, the author of “The Myth of Self-Esteem”, which basically says that the self-esteem doesn’t offer society any compensatory benefits beyond the seductive pleasure it brings to those engaged in the exercise.

The author points out a few critical problems with self-esteem. The main problem is that it has no intrinsic value or principles, and does not even require effort. It is often narcissistic. He gives an example of the total confidence that many parents try to instill in their children. Usually, such high self-esteem is accompanied by low self-awareness, and many of them grow up with no understanding of their own faults or without any humility. Some may even go so far as to believe that their own faults are endearing. The chapter concludes with the promotion of detachment, and the holy trinity of Ss - Solitude, Stillness and Silence.

The Rejection of Difficulty and Understanding
This chapter explores the topic of irrationality and how emotions such as grief, panic, hysteria, hatred, rage sweep aside rational argument and reasoned thought. He argues that most of these dangerous emotions are based on fear, and a hedonistic culture, concerned as much with the avoidance of pain and difficulty as the pursuit of pleasure, is always fearful. There is a line that I especially like, “The people have never been more healthy and safe - and have never felt more unhealthy and unsafe.”

The only alternative to difficult thought and a lack of understanding is surrendering autonomy to a higher authority. This is the attraction of fundamentalism, which eliminates the struggle to establish truth and meaning, and all anxiety of doubt. There is no solution as satisfactory and reassuring as God or a prominent entity.

However, the main point of this chapter is not to provide an argument against emotion, as without emotion there is no compassion, love, happiness, or even rational decision-making. But emotion must be balanced by thinking, especially with negative emotions as they are much more powerful than the positive. It would be beneficial to develop a more sceptic and rational mind.

The chapter finishes with a detailed description of the workings of the brain and latest advancements in neuroscience. It distinguishes between our primitive emotional brain and more recently evolved rational pre-frontal cortex, drawing parallels from ancient philosophy and modern neuroscience.

There you go. It’s a difficult read, but a good one.

Hit Refresh

Mar 09 2017
The son of an Indian Civil servant studies hard, gets an engineering degree, immigrates to the United States, and makes it in tech. But wait, there is more to it. Hit Refresh is less about the personal life of Satya and more about the amazing transformation happening inside Microsoft. This is my informal summary of Hit Refresh, an autobiography of Satya Nadella.

I am usually sceptical to read biographies and autobiographies, to avoid the inherent narrative biases and survivor biases that come with them. As with many other autobiographies, there are examples of these biases in this book. However, the main reason I picked this book is to understand Microsoft’s makeover under Satya Nadella and the book does a great job of explaining that. It gives a fascinating account of Microsoft’s a journey towards the Cloud and provides his unique perspective on empathy, which is much different than the nowadays overly misused corporate buzzword.
hit refresh.jpg 28.29 KB
Satya became the CEO when Microsoft was struggling, trying to catch up with Google(search), Apple(smartphones) and Amazon(cloud). Windows PC and Phone markets were shrinking, employees were leaving and developers were frustrated. Within 3 years, he was able to transform Microsoft’s culture 180 degrees, establish Microsoft as a leader in Cloud Computing, and change its perception among the developers(open-sourcing of dotnet). Microsoft has embarked on a major transition toward becoming a cloud computing giant through Azure. Shares of Microsoft have more than doubled since he became CEO. Hit Refresh does a good job of describing this ongoing journey. He says in the book that he wanted to share these experiences in real time rather than looking back on them years later. I think this makes the book a much more interesting read as we can see the changes happening in Microsoft as they do happen.

The book follows three distinct storylines. First, he shares his own transformation from India to the United States. Second, it focuses on the transformation of Microsoft under his leadership. Lastly, it explores the future of Cloud Computing, Artificial Intelligence, and Machine Learning.

The first chapter gives a brief overview of his childhood in Hyderabad and journey to the States. It describes how his parents and Cricket influenced him and shaped his worldview. He also shares the personal story of his son Zain, who was left with cerebral palsy after suffering asphyxia in utero. He writes about how his wife taught him to face reality, help develop empathy and expand his focus from pitying himself towards taking care of their son.

Next few chapters explain the shift towards cloud from the typical enterprise software Microsoft is known for. I love the analogy of “Seeing the Cloud through the Windows.” He does explain the basics of distributed and cloud computing in simpler terms, which is nice. A brief summary of how Azure evolved from a secret project named Red Dog to the Cloud giant it is today is also very interesting. This really fascinated me because it involved not only technological innovations but also genius business strategies. The book doesn’t provide too many details about the new commercial model that Takeshi Numoto developed to measure consumption of cloud services and new ways to package the products for the customers. It would have been an interesting read.

For the final part of the book, the focus shifts to the future of technology. It explores Mixed Reality, Artificial Intelligence and Quantum Computing. It is interesting to see Satya’s thoughts on this classic Explore-Exploit problem. Should Microsoft continue enjoying their success, or explore something they are not sure about and pursue new opportunities? He briefly details Microsoft’s strategy for solving this puzzle.

Something I would have loved to read more in the book was the failed Nokia deal and how he handled it, and the thinking that went behind acquiring LinkedIn. Overall, it does a good job of bridging technology with business and provide a coherent narrative. I think the book is targeted towards Microsoft employees, customers and partners. It’s also a good read for aspiring/current Computer Science and Business students.

To conclude, it is all about how people and organizations can and must hit refresh from time to time. I definitely am convinced that Microsoft I grew up with in the late 2000s has definitely changed since Satya became the CEO.

Being Mortal

Mar 06 2017
While medical science has given us the ability to extend life, it does not ask – or answer – the question of if that extended life still has meaning. I read this book last year, but never got around to summarizing my notes. It is written by Dr. Atul Gawande, the author of “The Checklist Manifesto”. In this book, Dr. Gawande calls for change in the way medical professionals deal with illness and final stages of a patient’s life.

The Central Argument
Modern medicine has provided tremendous benefits, transforming birth, injury and infectious diseases from painful death to manageable treatment. However, in the big scheme of things, the goals of modern medicine run exactly opposite to the well-being of a human. The incentives of modern medicine is to prolong death, no matter at what cost. Often this extension comes at the expense of the quality of life of a patient.

A better incentive
If the incentive should not be to avoid death at the cost of quality of life, is there an alternative? The answer is in the second chapter, “Things Fall Apart”. The job of any doctor, is to support quality of life, which usually means two things:
  1. as much freedom from the ravages of disease as possible, and
  2. the retention of enough function for active engagement in the world.
Most doctors treat the disease and figure that the rest will take care of itself. If it doesn’t - well, then it’s time to send the patient to a nursing home. This is a medical problem. Give modern medicine a disease, and it can do something about it. But give it an elderly woman with high blood pressure, arthritic knees, and various other ailments, when the elderly woman is at risk of losing the life she enjoys–and doctors hardly know what to do and often only make matters worse.

The real issue
It is not death that the very old fear. It is what happens short of death - losing their hearing, their memory, their best friends, their way of life. There is a line in the book which really made me think: “The assisted living and the elderly nursing homes aren’t really built for the sake of older people so much as for the sake of their children”. We want autonomy for ourselves and safety for those we love. What happens when those we love want their autonomy, as well? This is indeed a paradox.

Many of the things that we want for those we care about are things that we would adamantly oppose for ourselves because they would infringe our sense of self. The elderly are left with a controlled and supervised institutional existence, a medically designed answer to unfixable problems, a life designed to be safe but empty of anything they care about. The three problematic issues of nursing home existence are: boredom, loneliness, and helplessness.

As one nears his end, one does not seek power, or more riches. They only ask to be permitted, insofar as possible, to keep shaping the story of their life in the world. To make choices and sustain connections to others according to their own priorities.

Letting Go
The insight from the book is to avoid unnecessary intervention - resisting the urge to fiddle and fix and control. People with serious illness have priorities besides simply prolonging their lives. Top concerns include avoiding suffering, strengthening relationships with family and friends, being mentally aware and not being a burden on others. The technological medical care has failed to meet these needs. Spending one’s final days in an ICU because of terminal illness is a kind of failure. Arriving at an acceptance of one’s mortality and a clear understanding of the limits and the possibilities of medicine is a process that might help change perspectives of modern approaches towards death.
being mortal.jpg 16.24 KB
My Thoughts
As I read this book, I couldn’t help but reflect on the amazing lives both my grandparents, who are both in their late 70s, are living back in India. As we live in a big joint family, they are surrounded by all their relatives all the time. They get to see their grandchildren every day. Almost every year they visit the homes they grew up in. They still get a major say in big decisions in family, such as marriage (and they keep pestering me). All my extended family members consult them for advice. Although they have the common health issues brought by the old age, their days are filled with joy and pure happiness.

As much I enjoy my newly acquired Canadian personal freedom, I do want the same quality of life shared by my grandparents, surrounded by the pestering relatives, uncles and aunts who are always in your business. It has it’s own meaning.