Lessons from “Multipliers” by Liz Wiseman 

I received “Multipliers by Liz Wiseman” a month back from my manager as a New Year’s gift. This is probably one of the best management books I have read in recent times. The book is about how to multiply your team’s existing capabilities so that they are able to take on more challenges and deliver much more results. In this post I will share the learning I had from this book.

bookCover

Problem of under-utilisation

In my opinion, the main theme of this book is how to deliver more from existing people in your team. We are no longer in the era of behemoths like GE, where a company has infinite budget and hence can hire more people to improve delivery.  As a result, companies try to hire talented people upfront thinking that they will be able to deliver more and with good quality. I have noticed it first hand that companies have a difficult hiring process to keep away “bad” talent. However, when such talented people join the organisation they find the work not commensurate with the difficulty of hiring process. They feel under-utilised  and start looking for other opportunities either within or outside the organisation.

To solve this problem, we need leaders who can increase the productivity of the people around them, be it their peers, managers or team members. Such leaders are called multipliers. Similarly, there are leaders who have the opposite effect of decreasing the efficiency of people around them. Such leaders are termed as diminishers. The book is based on a two years research which studies the working style of both multipliers and diminishers.

Multipliers vs Diminishers

The following infographic explains the findings in a nutshell:

multiplierVSdimisherInfographic.png

One of the main difference between a diminisher and a multiplier is the way they see people around them. Diminishers are of the opinion that intelligence is scarce and hence they will have to do most of the difficult aspects of a task and show the way to people. On the other hand multipliers think that intelligence is abundant. People are smart enough to figure out how a task has to be done on their own. This fundamental difference in opinion defines the way in which diminishers and multipliers conduct themselves.

Empire builders vs talent magnets

It is seen that multipliers are the best bosses. “A players become A+” under them. They see themselves as a genius maker rather than a genius. As a result they attract the best talent through word of mouth. On the other hand, diminishers look for an all star team. They try to gather genius people only to make themselves look good. Once in the team, talent gets stunted.

Becoming a Talent Magnet

  1. Become a Genius Watcher: Consider 7–8 people you work with, and repeatedly ask yourself “why are they great at what they do?” until you uncover their raw abilities.
  2. Remove the blockers: Leaders most often know who the blockers are — the most common mistake is waiting too long to remove them.

Tyrant vs Liberator

Multipliers know the strengths and weakness of their people. They give them space and create a safe environment for them to work. On the other hand, diminishers work like a tyrant. They stifle innovation by calling the shots in every aspect.

Becoming a liberator

  1. Create space:
    • Shift the ratio of listening to talking. Multipliers are voracious listeners.
    • Release others by restraining yourself. Give soft opinions which are ideas for people to consider in their own thinking.
    • Level the playing field. Multipliers give opportunities to quieter voices in their teams to create a balance.
  2. Demand best work:
    • Multipliers know when people are performing below their standard and stretch them to grow. They ask questions like “Is this your best work?
    • Distinguish work from outcomes. When work is tied up to an outcome, people generally take short cuts. Multipliers set high standard for work, holding their team accountable for execution rather than results. Due to this, teams under multipliers experiments a lot as they know failures will be celebrated.
  3. Install rapid learning cycles:
    • Insist on learning from mistakes.
    • Admit and share your mistakes. This gives others permission to make and recover from their own.

Know-it-all vs Challenger

Know-it-alls give directives that show how much they know. They generally try to be the first ones to give solutions to problems. As a result, the team gives up on thinking and looks up to them for answers. This becomes a self serving cycle, reinforcing the know-it-all attitude.

On the other hand, a challenger tries to foster discussion by asking difficult questions. They try to ask the right questions rather than providing the right answers. When teams reach to a solution by themselves they start behaving like owners.

This facet of diminisher vs challenger is the most tricky in my opinion. There has to be balance between know-it-all and know-nothing-at-all. A challenger should strive to acquire knowledge which is important for them to ask the right questions. Teams generally lose respect for leaders who don’t have much context of the problem at hand as they ask irrelevant questions.

Becoming a challenger

  1. Ask a leading question: Question should lay the foundation of the challenge at hand. It should show the need of the problem. It might probably create a starting point.
  2. Let others fill the blanks: Even if we know how a problem is to be solved, we should leave out the important aspects to the team to figure out.

Decision maker vs debate maker

Diminishers are of the opinion that they should provide a decision quickly so that team can start with execution. They think that debate is optional and can be ruled out. However, it is a fact that in every decision debate happens. Either it happens before the decision is made or after. I have been part of the meetings where participants didn’t debate during the meetings but when they got out of the meetings informal debates happened. These informal debates generally don’t affect the decisions but lead to resentments among team members.

Multipliers on the other hand make debate part of the decision making process. As a result, they utilise the full capability of their teams by engaging them at every step of the decision making. This leads to well thought of decisions  and the team gets a sense of ownership.

Becoming a debate maker:

  1. Ask hard questions
  2. Ask for data: Discussion should be backed by data. Avoid letting opinions drive decision making.
  3. Ask each person: Everyone should participate. The leader ensures the balance of voices is heard.

Micromanager vs Investor

In sports, we see that a team’s coach doesn’t jump into the field and actually play for the team. Similarly, multipliers avoid the temptation to jump in and solve problems for the team. Just like an investor, they give required resources to the team so that they can produce results independent of them. Micromanagers on the other hand manage every detail in a way that creates dependence on the them. The team loses sense of ownership and consider the micromanager as a bottleneck.

Becoming an investor:

  1. Define ownership: Ownership of the project should be clearly defined by identifying the lead.
  2. Invest resources: Teach and coach. When people get stuck provide backup, but always “give the pen back” as soon as possible to avoid overstepping.
  3. Hold people accountable: Don’t intervene to save the day — it makes people feel small, and they’ll come to rely on it. Allow the possibility of failure.

Accidental Diminishers

Apart from discussing multipliers vs diminishers, the book also discusses an interesting concept which I relate to a lot. The concept is that of accidental diminishers. What do organisations do to their high performing employees? They either give them more work or promote them to leadership roles. However, throughout their career, such employees have focussed entirely on their own ideas and capabilities. When they get into managing other people, they generally don’t look beyond themselves. They generally miss out on the talent their new team has. Such leaders become accidental diminishers. Following are some of the ways we become accidental diminishers:

  1. Visionaries: Visionaries or big thinkers try to come up with the most important ideas themselves, since they have been doing that through out their career. However, this leaves little space for others to think.
  2. Idea people: Idea people have lot of ideas which in their opinion stimulates their team and provides inspiration. However, what actually happens is the team keeps on changing directions which drains their mental energy.
  3. Answer guys: Sometimes we are quick with answers, we try to solve problems in our head. However, it keeps other people from answering.

My key take away

My key take away from this book is that move from answers to questions.

q&a.png

Early in our careers we are hired to give answers and solutions as the problem we are working on is less ambiguous. We strive to be smart and have answers to almost everything. However, the value of providing answers diminishes over time. It is very difficult for a CEO to know everything in his/her organisation. On the other hand, the value of asking right questions increases over time. We should learn to ask hard questions which causes other people to pause and think. The end goal is to shift the burden of thinking from ourselves to others in the organisation.

Conclusion

I learnt a lot after reading this book. The concept of accidental diminishers was an eye opener for me. This book will help both individual contributors and managers to become multipliers and help their organisations reach the next level.

 

Further reading:

  1. https://insomanic.me.uk/leadership-lessons-from-multipliers-by-liz-wiseman-book-summary-b3de98e3e2d2

Understanding Event Loop

Event Loop is one of the most misunderstood concepts in Javascript. Since javascript is single threaded, it is still able to perform concurrent and async operations. Such operations are traditionally performed using threads in Ruby or Java systems. Through this post I wish to clear out some of the doubts on how Javascript performs async operations.

Event loop has been the key concept in non blocking I/O which has found its way from the browser to server in the form of Node.js. In order to understand event loop, it is important to understand how Javascript runs in general.

Call stack

When javascript runs a piece of code, it keeps reference of the current executing function in a stack which is called the call stack. When the function finishes execution it is removed from stack.

callStack

In the above example we have three functions (fn1, fn2, fn3). Following is the sequence of steps when javascript executes the code:

  1. Start execution using the main thread referred to as main() here.
  2. Identify the function which needs to executed and add it in the call stack.
  3. Identify other function which the current function executes and add it in the call stack.
  4. Upon completion of the function remove its reference from the call stack.
  5. Repeat steps #2 to #4 till the code finishes execution.
  6. After all the code has finished execution, remove main() from the call stack.

We can see call stack in action in browser when we get a javascript error.

Screen Shot 2018-01-20 at 1.31.06 PM

Here browser shows the call stack which lead to javascript error. This allows us to debug the code.

Single thread

Javascript doesn’t have the concept of threads. It has a single thread which executes code in sequential manner. It means that any function which takes a lot of time can block thread execution. When thread execution is blocked, browser cannot perform any function such as take user inputs. Essentially the page freezes. However, any non trivial application has computation intensive code. So there has to be a mechanism to handle such operations.

Async call stack

To solve this we write asynchronous code which performs time consuming operations in the background without blocking the main thread and uses callback mechanism to resume code execution. setTimeout is one such mechanism.

asyncCallStack.gif

setTimeout is one of the mechanism to write async code in Javascript. In the flow above, we have a setTimeout which will run the function passed to it after at least 5 seconds. The main thread executes setTimeout sequentially just like any other function call. Hence, the call the stack is similar to our previous example. However, after 5 seconds, the setTimeout’s callback magically comes into picture and gets added in the call stack. It means that Javascript wasn’t just executing the actual code, it was also keeping track of when to call the setTimeout callback. Clearly, this violates our assumption that Javascript being single threaded can do only one thing at a time. There is more to it that meets the eye. The magic referred to here is performed by the event loop.

Event loop

When we say Javascript is single threaded, we are referring to the Javascript runtime (for eg. V8, Blink). The event loop is what browsers provide. Following is the basic anatomy of a browser:

browser.png

  1. Javascript Engine: Javascript engines like V8, Blink provide the javascript runtime. It contains the function call stack and memory heap. Memory heap is used to maintain references to objects and functions required by call stack.
  2. WebAPIs: APIs like setTimeout, setTimeInterval are provided by the browser. These APIs are responsible to add callbacks in event queue. For eg. setTimeout(cb, 5000) will add the callback function cb  in event queue after the 5 seconds.
  3. Event Queue: Event queue contains functions which are to be added in call stack by event loop.
  4. Event Loop: Event loop is responsible to push the functions available in event queue to the main call stack. Event loop pushes a function only when the call stack is empty.

eventQueue.gif

Important thing to note here is that event loop will only add a call back from the event queue when it finds the call stack as empty. If Javascript’s main thread is busy executing a long running function, it would keep the callback in queue. The broader implication of this is that if we have long running functions which block the main thread, Javascript will not be able to respond to user events as they would be stuck in event queue.

 

Conclusion

Event loop is browser’s mechanism to perform non blocking operations. It does that by providing webAPIs (eg. setTimeout) which are capable of maintaining callback references in memory. The callbacks are added to event queue depending on the logic of  the webAPI (for eg. setTimeout waits for n milliseconds, XMLHTTPRequest waits for ajax call to finish). Event loop adds callback from the event queue and pushes it to the call stack where the callback is executed.

Bidirectional vs Unidirectional data flow architecture

MVC (Model, View and Controller) architecture has been in the industry for quite sometime. This pattern has served web applications well by decoupling their various components. The following diagram gives a high level idea of how interaction between different components work.

mvc.png

Controller is a broker between View and Model. The flow of data happens between model-controller and controller-view. Since view and model don’t have a direct communication hence they are unaware of each other. This allows us to change them independent of each other.

With the advent of complex frontend heavy applications (eg. gmail), this pattern found its way in javascript as well. The above diagram can be mapped to javascript applications as follows:

mvc4.png

On front end, data flows from the view to server due to user interactions (for eg. button click). Similarly data flows back to the view from the server in case of server updates.

For applications which have thin front end (i.e. no business logic in JavaScript), the role of controller is that of a data binder between model and view. For instance,


//Send form data to server on click of button
$('#clickMeBtn').click(function(){ form.submit();})
//Update view with data recieved from server
$.get('/get/employee', function(employee){
$("#employeeName").text(employee.name);
})

The above code does the basic functionality of relaying data back and forth between view and server.

However, for an application with good amount of user interaction adding such code can become repetitive and combursome.  In such scenarios, we can leverage AngularJS’s two-way data binding. This allows us to declaratively bind the view with model thereby relieving controller of this duty. For such thin applications, custom controllers don’t play a significant role and are just a support function to AngularJS.

mvcAngularJS.png

Hence, in a thin javascript application with considerable amount of user interaction we can have a bidirectional data flow directly between the view and server.

Things start becoming interesting and complex for applications which have thick front end. Such applications have a good amount of business logic on the client side as well. One case of adding business logic on client side is to make the application seem highly nifty and responsive. This leads to higher user engagement and retention. For eg. social networking sites like Facebook and Twitter have thick front ends as they want to give a user instant feedback and keep them engaged.

In such applications, controllers start to play a significant role. As a result, they come out of the shadow of AngularJS and start showing their influence on View and Model.

mvcAngularJSController.png

The above diagram shows that data can flow between view and model from either the controller or AngularJS. This kind of architecture gives us low confidence on how the view and model interact. We can never tell with surety if the view got updated logically or as a side effect by AngularJS.

In an application, view is a function of the data provided to it by the server. Mathematically speaking,

viewAsFn.png

Mathematical functions are pure functions, which means that a given input maps to the same output all the time.

In the current architecture, we cannot say with a high degree of confidence that given the same data from server will our application show the same view. This is due the fact that some parts of our view change which are not in our control (or not easy to reason about).

In such thick frontend applications, we have to introduce the concept of unidirectional data flow.

dispatcher.png

Here, view talks to a component called Dispatcher through actions. Actions are generated through user-generated events like click or keypress. Dispatcher figures out what data this action needs to update and sends it to the Application Store for further processing. Application Store contains all the state information of the application. It can also communicate with the server for updates. Updates to the store are listened by the View which in turn updates itself.

Since the flow of data is unidirectional, there is only one way through which view can be updated. As a result this gives us a high degree of confidence that our view is a function of data and hence is deterministic.

The above architecture is as simple as it looks. We can find variations of this architecture in the form of flux, redux and elm.

The implementation of this architecture can become a bit more involved as compared to an out of the box bidirectional data flow architecture. However, this gives us more control over how data flows in our application.

Conclusion

For thin front end applications with minimum business logic in JavaScript, we can deliver quickly with bidirectional data flow in the form of two-way data binding provided by AngularJS. However, for thick frontend applications we should rely on unidirectional data flow to get more confidence regarding how the view will be displayed based on the state of the application.

Further reading

The case for unidirectional data flow

Unidirectional User Interface Architectures

Books to read in 2018

For 2018, I have shortlisted 20 books to read from my never ending Want to Read list. The books are categorised in areas of my interest.

Software

  1. Coders at Work: Reflections on the Craft of Programming
  2. Continuous Integration: Improving Software Quality and Reducing Risk
  3. The Art of Capacity Planning: Scaling Web Resources
  4. The Cathedral & the Bazaar: Musings on Linux and Open Source by an Accidental Revolutionary
  5. Build Your Own AngularJS
  6. Clean Architecture
  7. Software Architecture in Practice 3/e
  8. Clean Code
  9. Deep Learning
  10. Code: The Hidden Language of Computer Hardware and Software
  11. Understanding Ecmascript 6: The Definitive Guide for JavaScript Developers
  12. The Nature of Code

Management

  1. Better Under Pressure: How Great Leaders Bring Out the Best in Themselves and Others
  2. The Manager’s Path: A Guide for Tech Leaders Navigating Growth and Change
  3. Herding Cats: A Primer for Programmers Who Lead Programmers

Business

  1. Energy and Civilization: A History
  2. The Start-Up of You: Adapt to the Future, Invest in Yourself, and Transform Your Career

Science

  1. Physics of the Future: How Science Will Shape Human Destiny and Our Daily Lives by the Year 2100

Tech Industry

  1. The Four: The Hidden DNA of Amazon, Apple, Facebook, and Google

Others

  1. Man’s Search for Meaning

Reactive programming vs Passive programming

Reactive programming has been quite a buzz word for quite sometime. It is often confused with programming in React.js. In this post I will share my understanding of what is reactive programming and when to use it.

Software programming is about implementing a business use cases in a language which computers can understand. High level languages have made programming easier and accessible for everyone. This has allowed us to tackle complex business problems such as e-commerce, health insurance. However, it is important to distinguish complexity into essential and accidental.

Accidental Complexity

Accidental complexity is the complexity introduced in a system by the architecture and programming paradigms. This is generally independent from the business problem.

Consider the following code snippet in Java to read a file:

InputStream fileInputStream = new FileInputStream(FILE_PATH);
BufferedReader bufferedReader = new BufferedReader(
        new InputStreamReader(fileInputStream));
String line="";
while((line = bufferedReader.readLine()) != null){
    System.out.println(line);
}

Following is the code in Python:

with open(FILE_PATH, "r") as file:
    for line in file:
        print(line)

Python achieves the same functionality with lot fewer lines of code. This complexity is not due to any business requirement. Solving such complexity is generally straight forward. In the above case, we can use class composition to reduce the lines of code.

Essential complexity

Some systems are inherently complex and take time to understand. Consider the following system:

delhi-metro-rail-map copy

The above image is a route map of Delhi Metro in India. Looking at the above map, it is difficult to find the exact route from station A to station B. There can be multiple alternative routes and some of them might not be valid. However, a color coded image can remove majority of confusion:

delhi-metro-rail-map

Now we can get a better clarity of how many different lines of trains ply in Delhi Metro. It binds stations on the same line much more clearly. Hence, solving an essential complexity involves finding creative solutions which make the complexity easier to understand. This is where the understanding of reactive and passive programming can help us.

A software is divided into modules with each performing a set of cohesive functionality. I will take an example of e-commerce checkout flow system. Consider two modules, Cart and Invoice such that if an item is added in Cart, Invoice should be update.

CartItem.png

One way to achieve this is to add dependency of Invoice on Cart, such that when Cart updates itself, it updates Invoice as well. Something like the following pseudo code in Cart:

addItemInCart(Item item){
    Invoice.update(item.price)
}

CartInvoice1

Another way to achieve this is to add dependency of Cart on Invoice such that Invoice updates itself when an item is added in Cart. Something like the following code in Item:

Cart.onAddItem(function(Item item){
    self.update(item.price);
});

The above code uses a callback function  which gets invoked when item is added in cart.

CartInvoice2.png

Notice the difference between the arrows in the above two figures. In case when Invoice is passive, Cart is dependent on Invoice. Hence the arrow is near Cart. In case when Invoice is reactive, Invoice is dependent on Cart. Hence the arrow is near Invoice. This is the major difference between reactive and passive programming. In reactive programming, a module is responsible to update itself as compared to passive programming, where other modules are responsible to update the module.

In a fairly complex system, managing dependencies is a critical aspect. Systems with clearly defined dependencies are easy to refactor and understand. For a module, dependencies can be described in two areas:

  1. How the module works?: A module will be dependent on other modules to complete its functionality. In our example, Invoice depends on Cart to update itself.
  2. What does it affect?: A module might affect modules which are dependent on it. In our example, Cart affects Invoice.

Hence a comparison of reactive vs passive programming in these two dimensions results in the following table:

Passive Reactive
How the module works? Find usages Look inside
What does it affect? Look inside Find usages

In case of reactive programming, we need to look inside the code of module to find out how it works as the module is responsible for itself. Similarly in passive programming, we need to find usage of a module across other modules as other modules are responsible to update it.

Dependency.png

Scanning through other modules is a difficult job. Incase the module is accessible publicly, it might not be possible to find out its reference. Hence a benchmark of when to use passive vs reactive programming is the ease of how vs what.

In general, software systems become complex when we don’t know how our modules work. Invoice can be updated by Cart but in future might be updated by  Discounts and Taxation modules. Reactive programming serves us well in such scenarios.

Further reading:

  1. Reactive Programming: Why It Matters
  2. The Reactive Manifesto

 

Thoughts on being a senior engineer

Having worked for almost a decade in software engineering, I generally pause and reflect on my journey. Have I produced enough value? Have I gained enough knowledge? Am I considered an expert in the field I work in? If I start over will I end up in the same position as I am now? What do my fellow engineers expect from me?

I have noticed that all these questions have a common theme. These questions are with respect to what others see me as. Such questions have no straight forward way of measurement, unless you have a mentor who can give unbiased opinions.

At times it becomes difficult to proceed in our careers without getting answers to these questions. Some engineers end up switching roles and move to management. However, I am of the opinion that they take some of these questions with them in the new role.

Although I don’t have answers to many of these questions, I do follow some practices which have helped me perform well in different roles through out my career. I wish to share some of them here:

  1. Always take out time for others: As a senior engineer, I have observed that fellow engineers want to bounce ideas off me. At times it’s for validation of an idea or to get a different perspective. I find such exercises really helpful. Even if I am in the middle of something, I try my best not to miss out on such opportunities. These small discussions are full of energy and enthusiasm. And I have seen otherwise introvert people opening up to me. Such exercises not only help others but help me as well. I can reach out to anyone when I need to bounce off ideas without the awkward small talk or ice breakers.
  2. Always do the right thing: A recurring thing which I have learnt from experience is that deep down, my subconscious knows what is the right thing to do in any situation. To meet a deadline, I have known that it is right to work on weekends or stretch yourself couple of hours in office. I have known that it is right to report or fix a glaring bug rather than waiting for quality analyst to do so. However, many times I have done the wrong things in such situations, may be out of laziness or out of pride and regretted in most of the times.
  3. Adopt a growth mindset: I have always wanted to work on the most challenging aspect of any project. Earlier in my career, I used to feel a bit disappointed when I was not approached first for such complex items. As a result, I either distanced myself too far from these items or prayed for them to fail spectacularly so that I can give a go at them and come out victorious. In almost all the cases, it used to be the former. I have realised that distancing myself from such situations help nobody. I miss an opportunity to contribute on something complex and people miss on my inputs. Now, I try to adopt a growth mindset by just asking if I can be involved in these projects. This has allowed me to be involved in challenging projects and people find me quite approachable as well.
  4. Create a schedule and stick to it: Early in my career, I didn’t have any schedule in place. I didn’t know where my time goes. I generally had the complaint that I don’t have much time to do the important stuff, even though I didn’t have much roles and responsibilities outside of work. To fix this, I started creating a schedule on my calendar by allocating time for things like reading blogs, reading news, watching an online course. This worked well till the moment I found a new activity which should be part of my schedule, for eg. solve one algorithm/ds problem daily. This involved rethinking about the schedule, removing some activity or reducing time from another activity. These iterations happened quite frequently, sometimes every other day. This led to frustration and confusion. I have realised that each schedule should be given a chance of almost 4 months to figure out if it works or not. This allows me to know with certainty what is feasible and what is not.
  5. Take care of your health: Software engineering is a profession which involves creativity and problem solving. This requires one to be alert and active throughout the day (at least during office hours). I have observed that my level of enthusiasm is directly proportional to how I am feeling health wise. I need energy to implement any new ideas I have in my mind. Hence, it is important to keep tab on what I am eating and have physical exercise every day.

These are some of the things I keep in mind in my everyday. Following these keep the nagging questions at bay for some time!

Thanks for reading!