Srikanth Sastry A Techie in Boston

Tale of two departures

Image by Maret Hosemann from Pixabay

Saying goodbye to a workplace where you have spent a considerable amount of time is never easy. But it can be made into a positive experience by the organization, or be made miserable. Netflix is famous for celebrating when an employee leaves by thanking them and wishing them well, and in contrast, Hubspot is know for firing something and calling it a ‘graduation’.

I have two stories to share on how my departure from two different organizations played out. Both both these stories, there were only good intentions all around, but yet, the executions of the departure were very different. The juxtaposition is instructive on its own.

First story: I said goodbye, and they said Au Revoir

Image by S. Hermann & F. Richter from Pixabay

In the first story, I had a meeting with my manager and told him that I accepted an offer with another company, and so was leaving. His immediate response was to check with me if there was anything he could do that will make me change my mind (he also prefaced that by saying that he thinks that the answer is ‘no’). After I said that my mind was made up, he thanked me for everything I had done so far, and said that he will set up meetings with various folks to help me transition my responsibilities.

With my consent, he immediately and discretely told members of my team, set up transition discussions, and then followed that up with an org wide announcement. Then, the entire team got together for a goodbye lunch, with everyone including the manager wishing me well. Finally, before I left, he said that he wishes me the best, but if things don’t work out with the new role, then I am always welcome back.

Second Story: I said goodbye, and they said uh.. wait, what?

Image by Alexas_Fotos from Pixabay

In the second story, I had a meeting with my manager and told him that I did not see my skills fitting the role, and that it doesn’t play to my strengths. So, I think serves both the org and me well to plan a transition for me to move on. He tried to convince me otherwise, and this went on for some time. I indulged his thoughts and arguments and made a good faith effort to pursue the avenues he suggested, but it only served to strengthen my initial proposition.

After I made my final decision, he asked to delay my decision until I had a new role. After I found a new role, he asked me to spend a month transitioning my responsibilities to someone else. But for over a week, I did not see any movement in the transition plan. Meanwhile, I am furiously preparing everything for the transition. Until about a week before my last day, there is no news of my departure, and no person or people to transition to.

With just over a week left, on my request, my manager calls the team together to announce my departure, except that he had already mentioned this to each of them private well over a week ago, but didn’t really provide any guidelines to them or to me about who else had been looped in. So, no one spoke to me about it, or to each other, and kept acting like everything was business as usual. It had become an elephant in the room and made everything uncomfortable for no apparent benefit.

Finally, the last few days were a frantic meeting spree with my transition of responsibilities to other folks, and my brain dump spread across multiple documents that was hastily reviewed by the team as my last day at work came and went.

My final goodbye was in an org-wide meeting where my manager thanked me for my contributions and wished me well.

Donts of processes for upward communication

Upward communication critical to organizational well-being and effectiveness. It is also notoriously difficult to get right due to the inherent power/authority differential involved in the hierarchy of any organization. Almost every place that I have seen upward communication done right focuses on mitigating this differential. Unfortunately, many organizations seem to be completely oblivious of how the existing power differential within a hierarchy can jeopardize upward communication.

Does your organization share this blind spot? For obvious reasons, it doesn’t help to ask the organization leaders about a blind spot. However, there are symptoms you can look for. Here are some examples, that I hope will help you see whether and why upward communication is failing in your organization. Note that all my experiences are from the software industry, and so I am focused only on software engineering organizations. So please keep that in mind as you read on.

Here are four IMHO important symptoms to look for.

  • Focusing on the format instead of a well thought out framework
  • Asymmetric commitment from the leadership on communciation
  • No reacting/responding to the contents of the communication
  • Not getting engineers’ buy-in

Format instead of framework

Any sort of ongoing upward communication tends to be only marginally useful if the organization does not have a framework within which the receive and process the communication. For instance, an organization may care about cross team collaboration, and could get information about this from employees through upward communication channels. However, without a framework for the employees to provide that feedback, the organization may not be able to glean much.

Unfortunately, organizations tend to conflate framework with format/template. When this happens you tend to see rigid templates or formats within which upward communication takes place leaving little space for nuance, reflection, and awareness to unforeseen issues. An example should make this clearer.

I worked in an organization which asked employees to fill out a weekly report. This report had mandatory questions such as “On a scale of 1 to 10, how happy were you working with other teams?” On the face of it, it might seem reasonable. But consider the following scenario.

An engineer who has had a bad week at work and wants to communicate that upward. She fills out her weekly report outlining her frustrations and why she hasn’t made as much progress and what’s blocking her. She proceeds to submit her feedback, but the tool rejects her submission because she didn’t answer the mandatory question. Effectively, the organization is saying “unless you give the information we seek, in the form that we prescribed, we are not interested in listening to you”.

When scenarios like these repeat themselves often enough, both the organization and the employees end up with blinders on what can and should be communicated. And that creates blind spots in the organization.

Asymmetric commitment for communication

When an organization sets up expectations for upward communication, it is automatically asking its employees to invest time and effort into it. If the organization does make a corresponding commitment on its end, it becomes demotivating for the employees, and any upward communication becomes either perfunctory or severely biased.

I recall a case where senior leadership wanted regular progress updates from all teams, for slightly different audiences and use cases, the content was required to be slightly different. The 'solution' to this issue was that team leads fill out almost identical, but slightly different, contents in an online form, a doc, a presentation, and a spreadsheet so it is all available for senior leadership when they want to review it. This is a really good example of asymmetric commitment. The effort here is expected entirely from the employees, and little from the leadership.

In contrast, I worked in organizations where management and leadership worked on upward communication along multiple avenues depending on how the engineers worked, and how the engineers liked to communicate. There were weekly/monthly sync up meetings where the management and leadership took notes, which the engineers communicated in the manner that was most convenient for them (including just talking, or presentations, or code changes, or screenshots, or even demos). Apart from that, the managers were also always sitting with the teams they supported, paying attention to the chatter among engineers and engaging when they realized some important decision were being made. The mangers participated in the decision making by proving additional context as appropriate, noted the decision that the engineers took, and made it a point to follow up on its execution while making an effort to not be intrusive.

That is an example of the leadership and management demonstrating their commitment to upward communication.

Reaction to upward communication, or the lack thereof

One of the expectations following upward communication is that the leadership with react to the communication, and then follow through on their commitment to address the issues brought into focus. When this redressal and follow through is missing, the impact is palpable and the consequences can be detrimental.

A common example where I have seen this is when the teams are expected to report progress and roadblocks, but the roadblocks are ignored by the leadership with the assumption 'the team will figure it out'. Or worse, at times, the leadership actually does not know what to do, but instead of making that a discussion, they choose to remain silent (for reasons that could constitute its own blog post). I assume I need not elaborate on the negative consequences of that behavior!

In cases where the leadership acts on upward communication, the impact can be dramatic and hugely positive. I recall two distinct cases in two different organizations I worked at, where the entire team had an unfavorable review of their manager. In response, the leadership immediately asked the managers to transition to a non-managerial role and re-org’d the teams so that they can have a different (and hopefully) more effective manager to support them.

Not getting engineers’ buy-in

Any upward communication process that does not get the engineers’ buy-in is bound to have limited success. Interestingly, this precipitates more communication processes that also do not have employee buy-in, and the cycle continues.

In one of the organizations I was at, the leadership, for reasons unknown, determined that a bespoke task tracking/project management tool be used. Very few engineers, if any, liked this tool. Yet, this was the tool of choice and decreed to be so. Not surprisingly, the tool was not well used, and so the leadership did not get the information they were looking for with respect to work done/progress made, etc. In response, the leadership created a new role that was focused on upward communication, and insisted that every team dedicate one person to perform this role. This not only took away one engineer from already resource-constrained teams, it also asked that engineer to execute a role that they weren’t really selected/skilled for. Naturally, that didn’t fare well either. There was improvement in upward communication as far as the leadership was concern, but it was not sufficient. So, the leadership decided that, harkening back to the Industrial Age, all teams should follow the exact same and synchronous development cadence and report progress on that exact cadence of the leadership. This cadence fit some teams better than others, and you can imagine the morale in the teams that ended with the short end of the stick there.

At no point during this entire affair did the leadership actually sit down with the engineers in various teams and actually ask them how the teams like to get work done, and how leadership could work with each team to accomplish the goals of the upward communication that was being sought.

Responding to concerns as a people manager

You are the people manager for a team, and a team member comes to you with a concern. How should you approach it? I have been in this situation multiple times, and have admittedly made some wrong turns. After some corrections and learning, here is what seems to work well for me (although YMMV). If you like lists, here is a snapshot of the path I take.

  1. Listen
  2. Empathize
  3. Don't take notes
  4. Descend into the particular
  5. Check with others
  6. Socialize, if the issue is common
  7. DO NOT become an apologist for status quo

Note that this doesn’t talk about the resolution for the issue. That is very specific to the issue at hand. What I have is more of an approach to understanding the issue in a manner that is respectful of the stakeholders. With that disclaimer, let’s unpack each of those bullet points.

Listen

Source: https://richmondmom.com/2017/02/22/what-i-say-and-what-my-kids-hear/

When someone in the team you support talks about how things are not a 100%, just listen. And I mean really listen. Take what they are saying at face value, even if you suspect something else is at play. Be non judgmental. Give full attention here. This is a lot harder than it sounds! Beware of you mind trying to make connections with that you are hearing. Resist that impulse. Repeat back to them what they said, but in your own words. Ask for a confirmation if you have captured their thoughts and feelings well. Rinse and repeat until they respond affirmatively.

Empathize

source: https://www.pxfuel.com/en/free-photo-qwnsc

Now that you know what the team member is talking about, do not respond yet. Stop to empathize with them, or their situation. Even if you do not agree with them, still take the time to understand where they are coming from and why they are feeling the way they are. Talk to them to make sure you do understand where they are coming from. It is important not to come across as someone with all the answers, or worse, with condescension. It is important that the person feels validated and not diminished for sharing what they did share. Not giving them that luxury is a sure way to get them to express themselves less and hold things within themselves until it gets to a point where they decide to leave.

Don't take notes

Original Image by StartupStockPhotos from Pixabay

Really, put your pen, phone, laptop (or whatever you use to take notes) down. Taking notes during this process does harm on two fronts: (1) it impedes your listening and your ability to empathize, and (2) it can have a chilling effect on the other person's candor.

When you start taking notes on what you are hearing, your brain stops listening because it's too focused on ensuring that what it hears is making it into the notes. This directly impacts empathy in that when you don't listen, you cannot empathize. You might think that by the other person see you take notes, they get the impression/message that you care and you want to make sure nothing is lost/forgotten. However, when it comes to matters where they want to be heard as much as they want their concern addressed, they are looking for a real conversation, and taking notes decidedly gets in the way.

Many such conversations where a team member is bringing a concern comes with an automatic expectation of some form of confidentiality and discretion; otherwise, they would have brought this up in a group and not in private. The moment you start taking notes, you are giving the impression that everything they are saying is 'on the record and in writing' so to speak. This makes the speaker guarded; they no longer feel comfortable speaking in a fluent stream of thoughts; they might feel the need to measure their words lest it be misinterpreted from the notes.

Descend into the particular

Image by Gerd Altmann from Pixabay

After hearing the person out, remain focused on the specific issue they are bringing up. Do not try to generalize. By generalizing you risk losing important details that might be critical to addressing the issue. Also, when it comes to such issues, it helps to solve the exact problem at hand first, and then look to address the general case outside the scope of what the team member is bringing up.

For instance, I had a team member come up to me and say that their lead engineer was micromanaging them too much. The lead would literally look over the engineer's shoulder and insist that the engineer do things exactly the way the lead wanted them to do it. To get away from the lead, the engineer started working away from their desk, but the lead ended up following them to where ever the engineer was and proceeded with the same behavior. Here the engineer is coming to me for a solution for this particular issue, and it does not help for me to start thinking about generalities such as hostile work environments, issues of gender and under-represented minorities, or workplace aggression. Instead, I chose to focus on the two individuals involved, and the current situation that needed addressing. I strongly recommend you do the same!

Check with others

So, you listened, empathized, kept your focus on the issue at hand. Next, we start trying to resolve it no? No! Don’t try to solve the issue yet. Check with others to see the issue is more widespread than the single individual.

There are multiple ways to do this, and it really depends on the issue at hand. You can bring it up with others in various contexts and situations, but be sure to respect the original team member’s privacy and discretion. And do this urgently. Letting too much time go by sends the wrong signal to the person who brought up the issue in the first place.

By checking with others you get an important signal. Is the issue singular int hat it is just this individual facing it, or is it an issue that multiple people are facing it, but one only of them brought it to you attention. This signal has a strong bearing on which way to proceed next.

Socialize, if the issue is common

If you find that the issue raised actually affects more than one individual, it is important to socialize it. It conveys that the organization is willing to engage in difficult conversation for employees' benefit, and it is important that everyone sees that. Of course, you have to mean it, and actually follow up with actions that address the issue.

DO NOT become an apologist

This is a strong temptation. Given what you know about how your organization and your leadership works, you might want to explain how the issue arose due to misunderstandings, or how the person who brought up the issue is misinterpreting things, or how things really are working the way things should and all that this person needs is a little faith and patience, etc. The argument doesn’t matter. The mistake is to make any such argument at all.
By becoming an apologist for the status quo, you are effectively victim-blaming. You are telling the person who brought up the issue that it is somehow their fault that this unpleasant situation has come about. You can only imagine the ramifications of that insinuation. So, just don’t try to justify any part of what happened.
Once you have these pieces in place, whatever resolution you come up with likely to be better received, and therefore, result in a better outcome.

Git may not be the best for SaaS companies

Yes, I realize that this is going to be pretty controversial :) Let’s dive in, shall we?

In the past half decade or so, Git has sky rocketed in popularity and is becoming the defacto choice for version control. While I understand its popularity, I have found it to be a poor fit for one specific, but popular, environment: SaaS development in a medium to large size enterprise.

Let’s take a quick look at what developing software in a SaaS enterprise is like. For the most part, it involves a significant number of developers concurrently committing code to a single master branch with frequent releases to prod and no long lived branches or versions. In a services environment, it also includes coordinated deployment of multiple services that have complementary server and client API spec.

While Git has been used in such environments with varying degrees of success, I have seen teams really trying to work around Git rather than Git just work for them. I have seen Git get in the way when teams get large, when teams get siloed into their own branches, when teams starts working with junior developers, and when having to develop across multiple services. While there are mechanisms in Git workflows and tools to mitigate this, it only adds additional complexity to developing software instead of taking it away.

Scaling Git with team size

Git branches for large teams

Git serializes all commits. So it does not scale well for large orgs natively. The common way to get around this is with more branching. Each team and developer ends up creating dependent branches from master, and either does a best effort merge into master, or designates one engineer to deal with the mess of merging multiple feature branches into master. Note that all this overhead make sense if you are having named releases and have to maintain multiple versions of the software. But in the SaaS world, you are continuously releasing to prod. There is not need to keep v2.1 around that is 8 weeks old! So all this overhead becomes an artifact of using Git.

Instead, consider Mercurial or Perforce where you can have concurrent commits as long as the commits don’t touch the same files or modules. Here is it much easier to support concurrent updates to master across different engineers who are not working on the same set of files. Granted, this can potentially break build on master despite each of the individual commits not breaking the build, but with a good CI set up, it should be quick to catch and easy to fix. And as a long as the master is in good health, you cut another release and move on.
The use of branches in Git brings me to the next issue that I have seen with Git in SaaS software development environments.

Git encourages branching despite conceptually not needing it

Source:https://flic.kr/p/8BkA3f
License: https://creativecommons.org/licenses/by-nc-sa/2.0/

Anyone who has used Git has heard "never commit directly to master". The common pattern is to create a feature branch for development. Let's consider this for a minute. In a SaaS deployment with continuous release, you want every diff to go into master asap, and have it deployed so that you can iterate faster. With Git, you end up doing this with creating a new branch, committing changes to it, getting it reviewed, and then (if you are smart) squash merging it to master. Now, if a team is developing a feature together, the pattern becomes that of creating a feature branch that everyone commits to, and after the feature is complete, you merge into master. Conceptually, you really just want to "commit directly to master", but in Git bad things can happen with less than well-seasoned developers if you allow it. So you create branches. Effectively, Git is forcing you to create branches.

This pattern leads to two problems: (1) Large features do not hit prod iteratively in small merges; instead they hit in one large merge to master. This has its own issues with stability and bug discovery earlier during the SDLC. (2) Unless an org is extremely vigilant against branching, you are likely to see long running ‘feature branches’ that compete with the main branch for attention. In practice, this means all fixes end up needing porting across multiple branches and the longer this goes on, the more feature branches diverge from master, which makes merging that much more unpleasant, and so it tends to get postponed making problem worse. Are there workarounds to prevent this from happening? Sure! You can write any sort of framework and tooling around Git. Have I see it often enough to think it’s standard? Not even close!

Really, all you need is to be able to release from master, and if there is a bug, just fix it in master, and keep adding features to master. There is no need for anything more sophisticated.

The above issue with branches is actually the symptom of a bigger attribute of Git: complexity.

Git is complicated; a little too complicated.

Git is complicated, and there is no way around it. Git (much like C++) makes it way too easy to shoot yourself in the foot. It gives way too much power to all developers including ones who shouldn’t have it, and don’t want it. As a junior developer, I cannot count the number of times I ended up with a detached HEAD on Git despite doing very simple operations. In general, git makes it very hard to follow simple workflows. It is way too easy to get into a bad state from which recovery is very difficult, if not impossible. But that’s the benign case. Git allows you to do all kinds of crazy stuff including rewrite history. This can be very dangerous in the hands of an inexperienced developer. A bad merge to master can put your report in a state from which rollback is near impossible.

It is easy to dismiss this argument with “With great power comes great responsibility”, but the fact of the matter is that (1) having inexperience developers is to be expected and your VCS should be robust to their shenanigans, and (2) most developers don’t want to be an Git expert. They just want to be able to write good software without the tools getting in their way, which Git steadfastly refuses to do.

Even with experienced developers, Git can get contentious/tricky. Just ask a bunch of developers if you should merge or rebase, and watch the fireworks that ensues.

Git encourages multiple repos, and that’s not always a good thing

Git does not like large repos; the recommended way around the complexity of a large repo is to split your codebase into multiple repos. This multi-repo approach to services creates a problem in the (micro)services world. Where do you define the source of truth for a service endpoint API spec? This problem is accentuated when using frameworks such as gRPC, or Thrift. Where do you store the Thrift/protobuf message definitions that need to be accessed by both the client code and the server code? Servers and clients are often distinct services that are implemented in different repos. If you define them in the server repo, then how do you ensure that when you change the API spec on the server side, the client will pick that change up as well? (Remember that this is enterprise environment where we control both client and server). Sure you can use git submodules, but that is not without its hassels. Developers could pinky swear to keep the definitions in sync, but we all know how that often goes.

More generally, Git has encouraged us to move away from mono-repos, and I think that’s a mistake. Note that mono-repo vs multi-repo and monolith vs micro services are completely orthogonal issues. You can have a mono-repo with all micro services implemented in that single repo. Alternatively, you can have a single service implemented across multiple repos. Git’s constraints on scaling for larger code bases has created new set of problems that need working around, but if you were to use a different solution like mercurial or even a centralized version control, then the problem wouldn’t exist in the first place.

When should you build for survival?

Previously, I wrote about building for survival vs. success building for survival vs. success. Briefly, when building for survival, your only goal to get the product working for the specific usecase, and in contrast, when building for success, you are building to solve a bigger class of problems within the broader context of your solution space. In this post, I will talk about when you should be build for survival, and when for success.

A Straw Man

On the face of it, it seems like an easy answer: "build for survival, when survival is at stake; otherwise, build for success." But unfortunately, that answer hides a multitude of assumptions, and oversimplifies the real-world within which the software development process operates. So, let's first breakdown the assumptions, and then address the oversimplification.

The assumptions

The first assumption here is the notion that we have a common understanding of what it means to say that a project/product's "survival is at stake". And the second assumption is that building for survival in all such cases will actually help.

Is your survival at stake?

Let's examine the first assumption: we can agree on what it means for survival to be at stake. Sure, in the extreme cases, we can all agree on this notion (e.g., a startup has a runway of 6 months, and additional funding depends on delivering an alpha in 3 months), but moving past that, things become a lot more subjective.

Consider a new project/product incubating within a well established company such as Facebook or Google. Is it's survival ever at stake? How about a project that involves building/dismantling infrastructure with a fixed, slightly aggressive, deadline; would it's survival be at stake? The answers to the above questions are not always obvious, and they can be different depending on who you ask. They can differ depending on where you are in the organizational hierarchy; it can even differ among developers within the team.

Ok, so your survival is at stake. So should you build for survival?

Now on to the second assumption: when survival is at stake, building for survival is actually the right thing to do. Again, there are some obvious cases where this is the right call. What about a case where the survival of your medical diagnostic software is at stake; would building for survival actually be the right thing (given that 'break things' is a corollary of 'move fast')? How about when you realize that you were a little too optimistic about what the product could accomplish with the limited resources you have; is building for survival still the right thing (ask Microsoft about Windows Vista)?

The oversimplification made here is that we only ever have two choices: survival, or success. This is almost never the case. You can almost always negotiate. You can negotiate on deadlines, on scope, on resources, on expectations, and on outcomes. Without taking all of the above into account, the discussion of survival vs success is meaningless.

So, when should you build for survival vs success?

While you have to evaluate every situation independently and holistically to determine which approach is the right one to take, here are some rule-of-thumb symptoms that suggest that you should be building for survival.

You are resource constrained, and failure is an option

When you are resource constrained, then there is a good chance that you cannot afford the time/effort/resources that a principled approach to software development demands. Recall, that in such a case, I talked about renegotiating the original parameters and expectations. However, they are not always negotiable. (E.g., you might have only a few months' of runway, and your investor might not be willing to fund you in case of milestone slippage.) In such cases, failure becomes a better option than renegotiation (almost vacuously). Here, building of survival makes sense.

Your environment is highly uncertain

High uncertainty is often a good trigger to build for survival. High uncertainty often requires you to 'fail fast'. If you are working on experimental technology, or on nascent problem spaces, there really isn't much to grok without actually building something and test things out. In other cases, it might not be possible to know if you are solving the right problem; this happens often when your customers tend to "know it when they see it".

Your survival is more important than stakeholders' risks

This one is less obvious. It could well be the case that your survival is at stake, you are resource constrained, and there is no negotiating. However, there still are situations when you should not build for survival. One big situation is when the stakeholders' risks trump your survival.

The most egregious example I can think of is in medical technology. If you software you are building is for (say) medical diagnosis, and a wrong diagnosis can mean the difference between life and death of a patient, then you should never, ever, ever build for survival. From here, you can extrapolate to all other situations where your stakeholders' risk outweighs yours.

You are solving a one-time problem

This one is tricky, because solutions to one-time problems have a nasty tendency of sticking around a lot longer than they should. However, in principle, if you are writing software that is going to be used just once, and then discarded, then you should consider building for survival. However, please ensure that that software will NOT persist past it's primary use. Incidentally, if your work involves building prototypes and proof-of-concept works, then you are almost definitely building for survival.

There are multiple ways to enforce this: (1) do not put it into version control at all, (2) put the code in a new repo that is nuked on a timer, (3) prevent importing modules from this codebase to anywhere else, etc.

Can you think of any other situations where building for survival is warranted? Let me know in the comments.