by David Xiang
Every software developer communicates differently. At one end of the spectrum, we have the introverted unicorn developers receiving tasks in small envelopes passed under the door. At the other end, we have the outspoken developers who insist on sharing their opinion with everyone. Software jobs require varying levels of communication. While it might be acceptable to stay quiet in an academic environment, communication skills become a deal-breaker when you work alongside non-technical colleagues—the unicorn might break down after having to sit in a two-hour business requirements meeting.
While it might be acceptable to stay quiet in an academic environment, communication skills become a deal-breaker when you work alongside nontechnical colleagues
For software development—as with any other technical discipline—it is imperative that we use the correct language in the correct setting. Thread vs. Process, Concurrency vs. Parallelism, etc. When we use the right language, our colleagues immediately understand what we’re talking about. If your co-worker is misusing a word, correct him or her and ask them to return the favor. Choosing the right words is extremely important from both a technical and non-technical perspective.
The Technical Context
From the technical perspective, choosing the right words at the right time can be tricky. One reason this is difficult is because we often jump from one technical context to another as we talk. This context switching becomes more natural as you gain experience, but it can be jarring if you’re learning many new words for the first time. Let’s talk through four of these so-called technical contexts: system-level, programming languages, third-parties, and your own applications.
If you decide to jump from Ruby over to Python over to Javascript, the word module can take on many different meanings.
When I say system-level, I am referring to anything that is a part of the operating system, raw computer, or distributed network. Abstractly, this is the hardware, or more colloquially, what our software is running on. As an aside, remember that the operating system is not really hardware. However, for most of us non-kernel developers, the OS is magical enough that we can refer to it just as hardware. That previous sentence is cringe-worthy for many readers, but I hope you catch my drift. Anyways, when you’re working in Linux there is a standard set of words and phrases that everyone has agreed upon. Your home directory is always your home directory. Generic-sounding words—process, group permission, scheduling—all have well-defined meanings within the language of Linux. Similarly, latency and bandwidth have special meanings when you talk about networks. Be careful, these exact words will reappear and be re-used in totally different contexts, but you should know exactly what they mean down at the system level.
Moving past the system level, what about the different programming languages? We use programming languages to describe business logic and model complex systems. For any language, respect its norms and constructs. This can be hard to master when you’re jumping from language to language. For example, don’t call your Ruby module an abstract interface, just call it what it is—a Ruby module. If you decide to jump from Ruby over to Python over to Javascript, the word module can take on many different meanings. It’s easy to interpolate one language’s constructs into another, so be careful not to make any cursory assumptions. Presuming that your Java generics are exactly the same as C++ templates, and continuing to call them template classes in Java is exactly the kind of mistake that can cause communication problems. Use the correct words in the right language context.
What about the external libraries and third-party services we don’t control? You will encounter generic words such as worker, controller, manager, scheduler, or foobar when working with someone else’s code. These nondescript words will have different definitions across different libraries, and no one can be expected to just understand them. To mitigate any confusion, strive to thoroughly understand the libraries, then use prefixes where necessary to clear up any confusion. This is equivalent to real life name-spacing:
“Oh, that code is in the Rails Controller.”
“How many Celery Workers are we running on that computer?”
Last but not least, you will create your own application-specific words for your own project. For effective communication, make sure the team is at a consensus on how things are named. If your team hasn’t developed a naming convention, bring it up and define whatever needs to be defined. During the next group sync-up, if your colleague says, “We need to refactor our secondary-layer arbiter orchestration meta classes!” everyone should know exactly what’s going on—even if the words themselves are ridiculous.
The Non-Technical Context
Within the organization, there will be business-specific words that the company will develop over time. These will be absurd names and acronyms that turn into normal company lingo. Despite the absurdity, these words must still be navigated and used consistently to make everyone’s life easier.
At a previous job, I spent a lot of time developing custom Customer Relationship Management (CRM) software and internal tooling. Every company can fire up Salesforce and track customers, but once you inject a CRM with industry-specific knowledge, things start to get complicated—modeling hospital patients is very different than modeling real-estate leads. The way an operator thinks about his or her industry is not going to match one-to-one with how you decide to implement your software. An internal business layer must be established between you and the industry experts. This layer is crucial and turns into the shared, non-technical, company language. Good operators will know how to translate business requirements to the company language, and you will know exactly how to take that and translate it into code. Take it upon yourself to define this business language.
This layer is crucial and turns into the shared, non-technical, company language.
In software, there is the concept of “overloading”— there is a similar concept at work in business. This happens when the shared company language is not well defined and one word begins to take on multiple meanings. Even worse than this, there may be holes in the language, causing communication breakdowns between business and technology. This is all part of the non-technical context that you must pay attention to! Develop this language with your colleagues and it will facilitate effective communication across all departments. The business guys may not acknowledge the problem, but you—the clear-thinking developer—will step up and define what needs to be defined. Everyone wins.
Precision
The right words at the right time facilitate precise descriptions. A sales pitch by its very nature can be fluffy and poetic, but a technical solution off the back of a direct question must be short and to the point.
Conclusion
Any situation—technical or non-technical—benefits from concise language. Use language that befits the context and the audience. When you get this right, your audience will automatically align on the same wavelength, as everything is understood by everyone. This is a priceless skill and will improve your effectiveness as a developer.
9: Embrace Confusion [Learning]
Tammy was one of the few women in CMU’s Electrical and Computer Engineering Class of 2009. She’s currently a software developer in Los Angeles and has been my friend for over ten years. I have seen the engineer grow in her year after year. After getting her MS in ECE, Tammy wasn’t sold on following through with tech. After a few years of unenthusiastic engineering, Tammy began dipping her toes in digital design. After being unimpressed with the laws of UX, she slowly found her way back to software. This chapter doesn’t do full justice to her journey, but it showcases invaluable traits for any engineer.
This is the third time I’m taking “Intro to C.” This class is old news for my friends and I desperately need to get through it. Third time’s the charm, right?
The first lecture isn’t bad—Introduction to the Syllabus. I got this. The second week rolls around and we get our first lab assignment. It’s something to do with pointers and I just don’t get it. It�
�s ok. I fight my initial impulse to flee and stick with it. I don’t exactly know how to start, but it’s not due just yet, so I still have some time. By the third week of class, the professor has moved on to a more complex topic, something to do with linked lists. What does a pointer dereference mean again? Do all intro classes move this fast, or am I really that slow? I have to digest pointers, finish the first lab, and keep up with all these new lectures.
I drop the class.
For the third time.
I’d found myself enrolled in CMU’s ECE program almost by surprise. I wasn’t die-hard about computers in high school, but it was a respectable school and a respectable field—definitely good enough for any 17-year-old. I knew it was going to be hard, but I didn’t think it would be that hard.
I knew it was going to be hard, but I didn’t think it would be that hard.
During the program, I felt isolated in my discouragement. I felt as if I was the only one who didn’t understand the lectures, the only one who struggled with the labs. Later in life, I would come to realize that these feelings were very, very normal. I’m very proud of my CMU degree, but at the same time I know I could have pushed myself harder. I spent five years staying relatively comfortable by avoiding some of the really challenging— AKA rewarding—classes.
After school ended, I slowly and steadily upgraded my mindset and changed my learning strategy. Here, I want to share a few important points that I’ve learned since obtaining my degree.
Dealing with Confusion
Every engineering discipline comes with its fair share of confusion. Programming can be enjoyable, but everyone goes through some late nights banging their head against the wall debugging. How you deal with this mind-numbing confusion is what’s most important.
Ever since I was elementary school, I’ve always enjoyed repetitive math problems. I could sit there and do multiplication and long division for hours. I knew what I was doing; I felt in control. This carried over into high school—algebra, trigonometry, calculus—it was all easy. The cakewalk ended the moment I stepped into university-level engineering.
Despite the discomfort, you must step up and embrace confusion.
All of a sudden, every assignment was open-ended. The professor gave us a few introductory lectures and set us loose on challenging coding labs. For me, I was not accustomed to this level of confusion. This wasn’t multiplication and algebra. I felt intimated, lost, not in control. I didn’t like it.
Over many years of working and being independent, I’ve slowly learned how to handle these feelings of confusion. Despite the discomfort, you must step up and embrace confusion. Many people underestimate this mindset. It’s not something that comes naturally, but it can be learned. This is an essential attitude for any engineering discipline.
Everyone Feels Discouraged—It’s Done on Purpose
I was not alone in my discouragement at CMU. The curriculum took a toll on everyone and I never realized the amount of extra time everyone put in just to stay afloat until much later.
For many engineering curriculums, the courses are purposefully designed to overwhelm you. The lectures move like lightning, the labs are intense, and you will fall behind. On top of this, the school instills a feverish sense of competitiveness among its students. You’re competing for the top scores in every class, the coolest internships, and the biggest job offers. To top it all off, whatever energy you have left goes into appearing competent in front of your peers. The atmosphere weighs heavily on every student.
If you’re feeling discouraged, I guarantee that your peers share similar feelings. Do not assume you are alone. Talk openly with other people, try to help each other, and never feel embarrassed about your own progress. If someone judges you by that, they are not worth your time.
You Have to Put in the Work
This is the most clichéd thing that can be said, but it must be said—you have to put a lot of work in! Putting in the work was a value I developed after embarking on my professional career. This was a natural evolution from what I call my old “just enough” mentality. Being exposed to a concept via a lecture and completing the homework isn’t going to cut it. Copying a piece of code and massaging it into a feature isn’t good enough. You have to go the extra mile and put in those hours. It’s the only way to get true value out of your learning.
When I got deeper into software as a professional, I started taking tons of online courses to supplement my knowledge. I offered to build free websites for my friends just to practice my coding. I became pro-active and left my comfort zone often. Sometimes I wish I had developed this mindset earlier in my life—I think my peers already had it in college—but I’m extremely grateful to have it now.
Thoughtful Questions
As developers, we must be comfortable independently digging for information. An awesome byproduct of doing your own research and reading instruction manuals is that you begin to ask more thoughtful questions.
If you provide a thoughtful question, you will get a thoughtful answer.
I’ve been blessed with the opportunity to work with extremely generous co-workers. I’m eternally grateful to them for spending their valuable time teaching me. To do my part, I always do my homework and come prepared with thoughtful questions.
“How does XYZ work?” is not a thoughtful question. It shows that you haven’t independently researched or dug for anything. This is a better question:
“I see that we built XYZ for customer request ABC. Why did we choose to use the FOO pattern for XYZ? Have we considered doing it using the MOO pattern?”
If you provide a thoughtful question, you will get a thoughtful answer. Other people’s time is precious—as is yours—so make sure you get the best out of it. Do your research, spend some time developing your questions, and don’t ask the same one twice!
Conclusion
The secret sauce for me has always been this simple idea—embracing confusion. During college, confusion caused me to feel intimidated, drop out of classes, and hold back with my studies. In my professional life, embracing confusion has steadily pushed me across disciplines and roles. At my current company, I started off as an entry-level product designer helping design banners, logos, and other marketing assets. Even though the work was enjoyable, there was always that small string leading back to coding waiting to be pulled. This mindset—mixed in with some consistent work and thoughtful questions—has enabled me to keep pulling that string and building my career.
We must be very comfortable being uncomfortable. When that level of comfort is our norm, challenges and foreign topics become enjoyable—dare I say fun—to encounter and take on.
10: Digging Yourself Out Of Demotivation [Career]
In the following story, Ross recounts his years writing software at a large consulting company. It showcases common forms of demotivation and, more importantly, provides methods to push through negativity. Every one of us can relate to the uninspiring hours writing code we don’t want to write. Ross’s story shows that there is always something you can do about it.
Demotivation is a subtle process. One day you’re honeymooning with a company, and the very next day you suddenly hate looking at the code. What just happened?
My first job out of school was with a consulting company. Ironically, this came after calling nonsense on consulting ever since I was a freshman. During fall semesters, companies would come give workshops about their new-graduate positions. These were excellent sources of free pizza and also mildly educational insomuch as they told you all about the different opportunities out there for new engineers. The consulting companies were the worst; the number of “synergies” and “fully-integrated solutions” mentioned made me want to flip tables. My freshman self would have scoffed at my senior self, but a job’s a job.
In a consulting company, projects come and go. Management sells this as a constant stream of challenging work:
“Nothing is ever stale!”
“You get to work with
“You’ll be solving a diverse set of problems!”
It’s a great sell, but my colleagues and I quickly developed a very different sentiment.
I was only two projects in and my motivation had already begun to fade. I felt hopelessly detached from my work. Management wasn’t lying—nothing was ever stale, and that was the problem. We had built nothing for ourselves. We had zero technical identity. When you take on a contract, everything you create eventually gets handed over to the client. It’s their product, or problem, after you’re done with it. I found myself in a brand-new code base every six months, with a severe lack of pride in any of my work. A lack of recognizable ownership is a particularly dangerous feeling for any software developer.
We had built nothing for ourselves. We had zero technical identity.
Let’s do a quick summary of the company dynamic. On the ground, there are a ton of software developer teams. Each team is given one big client project at a time. Every project has one, maybe two, business analysts. This role has recently won the award for “Most Generic Sounding Title of All Time.”
In the beginning, I underestimated the business analysts, but over time, I came to greatly admire them. It’s an extremely important and difficult role. These were the people who spoke directly to the clients and gathered all the information on each and every job. It’s a very simple job description, but not so simple when it comes to execution. They consider all the clients’ requirements and spec out the systems at an extremely high level. What are the inputs? Outputs? Edge cases over here, edge cases over there. Finally, they communicate all of that to us—the developers.
To round this out, we had project managers who would oversee a handful of projects. They would schedule meetings and make sure things were staying on track. Their main objective was to keep the software progressing and make sure the business analysts were staying on-point with the client requirements. I always considered these as glorified meeting schedulers, but, again, they played an extremely valuable role; without them, projects would fall apart.