Lessons in Communication: Balancing Empathy and Professionalism

I want to share a story about a brilliant engineer whose personality, while unique and engaging, ultimately presented significant challenges within our team. This experience served as a powerful reminder of the importance of setting clear boundaries and navigating complex interpersonal dynamics when managing individuals.

By late 2023, our Ruby on Rails application had become increasingly fragile and difficult to maintain. Recognizing the need to enhance our team’s engineering fundamentals, we decided to shift our hiring strategy to attract individuals with a stronger foundation in core engineering principles.

Note: Rails facilitates rapid application development, which is a significant advantage. However, a team lacking strong engineering fundamentals can quickly encounter limitations as the application grows in complexity. This can lead to technical debt and hinder future development efforts.

Both the engineer and I tend to be quite expressive in our communication style. This shared characteristic fostered a sense of camaraderie, allowing for open and candid conversations in private. However, our more direct communication style sometimes clashed with the expectations of the broader team. I recognized this early on and began to gently guide her on the importance of adjusting the communication style in public settings.

While it’s generally advisable to maintain consistency in one’s communication, the engineer’s conversational style felt familiar and comfortable to me, making it difficult to consistently enforce professional communication standards.

She quickly adjusted her communication style, and the initial interactions seemed promising. I believe in providing challenging opportunities for my team members to grow, so I entrusted them with our most critical project of the year. I was eager to see them excel and showcase their talent. However, it quickly became apparent that the high-pressure nature of this project was exacerbating the existing tensions.

As the research progressed, I observed a gradual increase in the engineer’s stress levels. This became a recurring pattern: I would address their concerns, offer reassurance, and express confidence in their abilities, which would temporarily alleviate the pressure. However, within a week, the stress would resurface, creating a cyclical and unproductive dynamic. In retrospect, I realize I should have recognized the severity of the situation much earlier, but my own biases and a desire to support their success likely blinded me to the escalating issues.

I believe my shared background and generational similarities with the engineer may have inadvertently led to an overestimation of our compatibility and a reluctance to address the escalating issues more directly. I inadvertently granted more latitude than was appropriate, failing to recognize the severity of the situation until it reached a critical point.

It’s important to note that I value open and authentic communication in private settings. My primary objective is to understand and support my team members, and I believe that effective communication can take many forms.

While I am open to direct and even passionate communication in private settings, I cannot tolerate disruptive behavior in public forums. This includes raising one’s voice or engaging in disrespectful language during team meetings. Unfortunately, this is what happened during a code review session.

I had presented a code solution that did not align with the engineer’s preferred approach, and they proceeded to express their disagreement in a highly emotional and disruptive manner, raising their voice in front of the entire team. The shock and discomfort on the faces of my colleagues were palpable. This incident marked a significant turning point in the situation.

The following day, I issued a written warning along with a Performance Improvement Plan (PIP). The meeting that followed was understandably emotional. As always, I made a concerted effort to listen to the engineer’s concerns and perspectives. After a lengthy discussion, we concluded the meeting by outlining clear expectations for future behavior and performance. Unfortunately, the situation did not improve, and the employment relationship ultimately ended.

In retrospect, I realize that while I consistently listened to the engineer’s concerns, I failed to truly grasp the escalating severity of the situation. I did not fully recognize the extent of her frustration and the impact it was having on her well-being. This was a difficult and valuable lesson for me.

My previous approach, which emphasized a permissive environment for open communication, inadvertently failed to establish clear boundaries between appropriate and inappropriate behavior, particularly in public settings. I now approach private conversations with a greater emphasis on both empathy and clear expectations. While I still value open communication, I strive to maintain a balance between fostering an inclusive environment and upholding professional standards.

The Unexpected Teachers

There are several stories that I tell, whether you want to hear it or not about learning. There are two stories that mean a lot to me that I share as often as I can. I want to share them here.

In the late 1990s, I was not working in software engineering and it was not on my radar. I was working in metrology. Yes it is a word and it has nothing to do with weather. I was sold that it was a good career and was stable. Needless to say, I was ok with that and didn’t look much past it.

One day I overhead a manager from a different group talking with one of his technicians. I heard the technician say “Why do I need to learn about combustion engines?”. At first, realizing that our field has nothing to do with those types of engines, I wanted to hear the response. The manager asked a seemingly simple question, “Do you know how they work?”.

The response seems silly since the technician had zero interests in combustion engines. I walked away not thinking much more about the exchange. It wasn’t until later that night that I replayed the comments. The message that I extracted was there was something that the technician didn’t know, so why not take the opportunity to learn about the engines.

The comment was not intended for my ears, but I have taken that lesson with me. For almost 30 years, I have taken the opportunity to learn anything and everything that presents itself to me. It was that lesson that has carried me this far in my career. I was a self-taught software engineer for almost five years before I decided that I needed to get my degree. During those early days, I read everything. A lot of my Friday nights were spent at the book store and my then girl friend loved it. Honestly, she hated it but she understood what I was trying to achieve.

He doesn’t know it, but I owe my entry into this career to you Shawn. I tell that story all the time, because it had such an impact on my life.

Fast forward to the mid 2000s and then I saw something that taught me a similar lesson. I was working on web applications and we didn’t have mainstream JavaScript libraries like jQuery, so a lot of the code we wrote was for handling the browser quirks. Most people could see the writing on the wall that JavaScript would keep spreading throughout the industry.

One day, I was walking down the cubicles and I stopped at one of my colleague’s desk. I struck up a conversation about JavaScript and sharing the resources that I was using to get up to speed. She said to me that she didn’t need to learn anything new, because she already knew enough. To be clear, she was not being a know-it-all, she was a good person and not like that.

Her response didn’t sit well then and it further cemented my commitment to life long learning. My colleague stagnated and their career didn’t progress. In fairness, not everyone is so passionate about learning or growth and that is OK. If you are content and don’t have the desire to do anything new, then I respect that.

Those two lessons have served me well for that last 24 years and has made sure that I will always seek out opportunities to grow. I share these two stories with anyone who will listen because they have been so pivotal to my journey. Keeping a growth mindset has made me hungry and keeps me going. I hope you can find these two stories as valuable as I have.

The AWE Question

I have read several leadership books recently and they all have had great tips, but there is one book that stuck out. I subscribe to Amazon Books Unlimited and after finishing a recent book, I decided to pilfer through the books offered. I came across The Coaching Habit by Michael Bungay Stanier. The book lists seven questions that you can ask as an effective manager during coaching opportunities. These are the seven questions.

  1. What’s on your mind?
  2. And What Else?
  3. What is the real challenge for you?
  4. What do you want?
  5. How can I help you?
  6. If you are saying yes to this, what are you saying no to?

The AWE question or And What Else? was easy to implement and it has worked very effectively from the time I used it. I have a few employees that are hard to crack and get the conversation moving. When I start with What’s on your mind, I get a little bit of chatter but not too much. Then I drop the question.

Every time the AWE question was asked it blew open the flow of dialogue. I have spent an hour in a 1:1 and that is the only question that I was able to ask in addition to the first question. There were no awkward moments at all, it was all smooth and free flowing.

I have had 1:1s that were awkward where I could not get the engineer to pipe up and later paid the price when their true feelings came bubbling out. Everyone wants to be heard so the easy part is just listening, but getting a dialogue going can be a real challenge.

If you are in leadership and you have 1:1s or other coaching opportunities, I recommend reading The Coaching Habit by Michael Bungay Stanier. I loved it and I think you will too.

React-Intl outside your component tree

Recently while reworking our app to add multi-language support I came across the need to use the intl api outside of the component structures. I tried a couple of different paths, such as a singleton-like provider that is populated by a wrapper component when it is mounted. This worked fine, but was really ugly.

For my use case I have the need to load the language file (data) from the server at runtime, so we needed a way to dynamically load the intl provider after the fact. I didn’t find a way to do that, so we will have to make sure that the data is available when the components at the root are mounted (not a big deal). What I did find, however, was in their api I can create a new instance of the intl object outside of the provider.

There are some considerations with having two instances of the intl object floating around like memory usage, but for our user load that isn’t really an issue for us. To build this out we need to supply a two character locale string, so for that I am using the package locale2. I don’t think anyone could have made that package any easier to use. Like I mentioned, I needed to load the language data from the server when the page is rendered. To extract the language data, I use simple function to pull it from the window object. Now that I have all that I need, I can create the new intl object and return that as an export.

import { createIntl, createIntlCache } from 'react-intl'
import locale2 from 'locale2'

export const locale = locale2.substring(0, 2)
const cache = createIntlCache()

export const getMessages = () => {
    if (window['messages']) {
        try {
            return window['messages']
        } catch (error) {
            console.error(error)
            throw 'Failed to load messages from server'
        }
    }

    return null
}

export default createIntl(
    {
        locale: locale,
        messages: getMessages()
    },
    cache
)

That was all it took to access the intl object outside of the component tree. Now you can import intl and use it freely.

intl.formatMessage({ id: 'Hello' })

If you have any questions, leave a comment. Cheers

React-Intl and your multi-lingual application

If you are doing multiple languages in React, then this is the tool you want to use. Here is a quick tutorial on how to use it.

Since you want to allow multiple language everywhere in the app, they have create a wrapper control so that the api is available everywhere.

import { IntlProvider } from 'react-intl'

This library works off of json files that have the key/value pairs that give an id to the text that you want to show. Here is an example of the file that will be required.

{
    "app.get_started_button.title": "Get Started",
    "app.get_previous_button.title": "Previous"
}

You can see that it is a simple json file with only one level. The key is what you will use later to retrieve the text that you want. You will create a new json for each new language that you want to support. You will conditionally load that file based on the language. Now that we have a language file, let use the IntlProvider.

const en = require('./data/en.json')

const App = () => {
    return (
        <IntlProvider messages={en}>
            <MyEntryComponent/>
        </IntlProvider>
    )
}

export default App

Now that we have set up our provider with a file, we can move on to using the provider api. There are a couple of ways to use their api, as a higher order component or as a hook. I using functional components so naturally I use the hooks.

import { useIntl } from 'react-intl'

Now wire the hook in your component.

export default ({  }) => {
    const intl = useIntl()
    return <div/>
}

There are many methods in the intl object, but the one that I am going to show here is formatMessage. formatMessage takes a object with one property: id.

{
   id: 'app.get_started_button.title'
}

The id can be anything you want, but I tend to create a dot separated string based on where the text exists in the app. To wrap it up, all you need to do is pass this object to the formatMessage method.

export default ({  }) => {
    const intl = useIntl()
    return <div>
           {intl.formatMessage({id: 'app.get_started_button.title'})}
           </div>
}

That’s it. Now when you add new language files, you can load them conditionally and pass them to the provider. If you have questions, feel free to reach out to me on Twitter @hivie7510 or email me.

ICS Standards Compliant File Generator

For the second time in a year I need a package to create an ICalendar (*.ics) file in my projects. I tried a couple different packages, but they either didn’t work well or they did not have what I needed requiring me to modify it. I decided that I needed to just build one from the standard. I also have never published a package to the npm registry, so I figured it was time to do both. You can checkout the Github here.

For my immediate needs I required the ability to create an event or a collection of events. These come in the form of a VCalendar and a VEvent. I started googling to find the references for the standards. I came across ICalendar.org which seemed to have most of what I was looking for, but I found it hard to digest in the HTML format, so I decided to go straight to the RFC linked above.

I Started with a simple folder structure. The names are self-describing.

I wanted to follow a builder pattern and have the creation be fluid. This means that the builder is returned in each call so that you can chain the method calls. I like the way it looks and I think it is easier to read.

I wanted to make sure that I didn’t have to polyfill so I used the current version of js which is while you will see classes instead of functional objects. Both of the CalendarBuilder and the EventBuilder are almost the same, they have a constructor, build method, validation method and then the setter methods. Here is an example of the CalendarBuilder.

In the standard there are some supporting objects like an Attendee and Organizer so I have objects for those. Currently I am using the uuid package to generate the required uid field. I may look for another implementation because it is pretty large, but it is ok for now.

In the end, it is pretty simple to execute to get the ics text that you can use in a file or send to a download (if hosted on the web).

const {
    CalendarBuilder,
    EventBuilder,
    Attendee,
    Organizer,
    Role,
    CalendarUserType,
    RSVPType
} = require('ics-standard-compliant-file-generator')

/*
    
    To import the package you will need to either run this example outside of the root
    or modify temporarily the package.json to change the name.  Otherwise, the package
    will not install because there will be a name conflict 

*/

/*

    Start with creating a Calendar Builder, this does not need to happen at first but it is logical to start here
    The Calendar Builder is the container and the actual generator of the *.ics file

*/
var c = new CalendarBuilder()
c.setUrl('http://www.mycalendar.com')
c.setSource('http://www.mycalendar.com/test.ics')
c.setColor('red')
c.addCategory('Meeting')
c.addCategories('my meeting, you meeting')
c.setName('HOME')

/*
    
    Now lets build a single event by instantiating an Event Builder
    We can create the bare minimum required for an event

*/
var eb = new EventBuilder()
eb.addOrganizer(new Organizer('testOrganizer@gmail.com', 'Test Organizer'))
    .addAttendee(
        new Attendee(
            'testAttendee@gmail.com',
            'Test Attendee',
            null,
            'test-delegate-from@test.com',
            'test-delegate-to@test.com',
            null,
            'test-sent-by@test.com',
            Role.CHAIR,
            CalendarUserType.INDIVIDUAL,
            RSVPType.TRUE
        )
    )
    .setStart(new Date(2021, 0, 1, 20, 00))
    .setEnd(new Date(2021, 0, 2, 20, 00))
    .setSummary('Party Time')
    .setDescription("We're having a pool party")

//Now that we have described our event, we can add it to the Calendar Builder
c.addEventBuilder(eb)

//All that is left is to call the build the file contents
let icsContent = c.build()

//At this point you use which ever method you want to use to create the file
//For testing I just pushed the console output to a file
console.log(icsContent)

//The call from the terminal then becomes:
// node index.js > test.ics

After running this, you will get an output similar to this:

BEGIN:VCALENDAR
PRODID:HIVIE7510/ICS STANDARDS COMPLIANT FILE GENERATOR
VERSION:2.0
CALSCALE:GREGORIAN
UID:be58db63-760f-4cdb-a615-3b23063af98d
NAME:HOME
URL:http://www.mycalendar.com
SOURCE:http://www.mycalendar.com/test.ics
COLOR:red
CATEGORIES:Meeting
BEGIN:VEVENT
UID:e4be7bb8-e832-4d61-a231-7f29f292a831
DTSTAMP:20210101T195100Z
DTSTART:20210102T040000Z
DTEND:20210103T040000Z
ORGANIZER;CN=Test Organizer:MAILTO:testOrganizer@gmail.com
ATTENDEE;CUTYPE=CHAIR;
ROLE=INDIVIDUAL;
RSVP=TRUE;
DELEGATED-TO="MAILTO:test-delegate-to@test.com";
DELEGATED-FROM="MAILTO:test-delegate-from@test.com";
CN=Test Attendee:MAILTO:testAttendee@gmail.com
SUMMARY:Party Time
DESCRIPTION:We're having a pool party
CONFERENCE;VALUE=URL;FEATURE:AUDIO;
LABEL:Moderator dial-in:tel:+1-412-555-0123,,,654321
CONFERENCE;VALUE=URL;FEATURE:AUDIO;
FEATURE:MODERATOR;
LABEL:Moderator dial-in:tel:+1-412-555-0123,,,654321
CONFERENCE;VALUE=URL;FEATURE:AUDIO;
LABEL:Moderator dial-in:tel:+1-412-555-0123,,,654321
CONFERENCE;VALUE=URL;FEATURE:AUDIO;
FEATURE:MODERATOR;
LABEL:Moderator dial-in:tel:+1-412-555-0123,,,654321
END:VEVENT
END:VCALENDAR

I am still working on this, because I want to add more validation and add the other calendar objects that are compatible such as the VTodo and VJournal.

Recent Readings

Like I mentioned before, I have been “twittering” (is that a thing) with someone who has since been challenging my understanding of some social issues. She was the one who drove me to read Baldwin’s book The Fire Next Time which was great which segued well to Glaude’s Begin Again. This was a great book after reading about Baldwin , our Jimmy, as he prefers to call him. It follows his life and takes you through the challenges he faced writing about civil rights as a gay black man. It details his ventures over seas and how he, as a black man, was received.

Feeling even more inspired I picked up Color of Law. This was truly transformative in my understanding of the effects of systemic racism against black people. One of the most impactful was the explanation of the wealth gap. On the surface, and easily recognizable, is the pay inequalities between whites and non-whites. That is without discussing gender inequalities from being both black and female. There is a more subtle component of the wealth gap, home ownership.

I have never thought about the ability to purchase a home outside of the price barrier. There is a large swath of America that is below the poverty level, so it is easy to reason that home ownership is a tall mountain to climb. What hides even underneath that, debatable is how hidden it is, is the prejudice towards black people even to this day. Ok, that sounds bad enough but it gets worse. For a hundred years after emancipation there was hateful exclusion from buying homes in white neighorhoods. This was so systemic that the FHA actually had policies that required builders to make the neighborhoods “whites only” before they could get a loan and permit to develop. Even when the law prevented the discrimination, they did one better. They required homeowners to enter into a community agreement that they will not permit black homeowners.

I used to wonder how people had the money to do xyz, but now that I am a home owner I realize the power in home equity. I can take a loan to do almost anything, send my children to college or buy investment properties. That is something that can accumulate wealth over generations after I am gone. This ability to accumulate wealth from home ownership has been denied to black people for over 150 years. If you did the math, I include the years to present day. This goes so deep that I cannot put in a single blog, and I am certainly not expert enough in the topic to go further. If this strikes a cord or you are interested, please buy Color of Law. This was a phenomenal book that really recommend.

I know that I did not do this topic justice, but it really was an eye opener.

I just finished Frederick Douglass’ book My Bondage and My Freedom. I will talk about that in a future post.

New Agenda

I have been spending time trying to get the Jetson Nano to work and I have only made slight progress to get it to where I can use it effectively. In a previous post, I reviewed several books that I read recently and I gained a lot of knowledge, but something was missing. The books talked about the principles at a high level, but I think some of the lower level thoughts experiments were missing. I have decided to pause on the practical application for a bit, maybe a month or two, and focus on getting a deeper understand of the math.

Math is one area of focus, but on twitter I have been chatting with someone on social issues and it made me realize that there was a large section of my knowledge base that was void. Even more introspectively I realized that I am not great at making an argument. I know the content, but my ability to frame and stay on target is an issue. Given that, here are the new three books that I am reading:

The fire next time by James Baldwin.

I am only a quarter way through, but his detail of how he was raised and the paths that were available to him were small. Seeing his explanation of how the world (white America) changed how they seem themselves and the effects that it has on psyche is mind-boggling.

How Not to Be Wrong: The Power of Mathematical Thinking – by Jordan Ellenberg

This book is hard to put down. It takes you through a lot of examples where decision making happens and the mathematics that you can apply. This isn’t an exhaustive book on math, but it hits just write for where I am. In short, this book is awesome.

Deep Learning – by Ian Goodfellow, Yoshua Bengio, and Aaron Courville

I am holding off cracking the cover of this one until I finish the two above. This one is an actual textbook so I have high expectations. It digs pretty deep into the mathematics, so if I do this right I should have a much better footing than I have now.

In short, I am looking to learn math, social justice and argument. This political climate is brutal right now, so I am trying to stay off the television as much as possible to reduce my stress.

Please vote on November 3rd, our democracy is at stake.

Cheers

Jetson Nano Troubles

In my draft posts, I have a ton of notes on how I setup the nano, but none of it works. I have probably spent upwards of 10 hours trying to get it running. The main issue that I have is trying to get OpenCV to install correctly.

There were so many resources on the web that had different approaches, and just like my experience few of them worked for even fewer people. There was a script from someone at NVidia which downloaded, unzipped and did a few other things, but it didn’t compile.

I think I know why that script didn’t work. The last thing the script does is run cmake to generate the make file. Not my area of expertise, but it is not generating the makefile. I tried even barebones cmake .. but still nothing more than the CMakefiles folder. Honestly, I have no idea what I am doing, so I have going to wipe the drive and start over. I hope I can get that done tonight, but time will tell. I will have a step by step post once I figure this thing out.

Machine Learning Book Review

If you have been following along, you know that I am trying to become a data scientist. That means that I am reading more books that are probably healthy for a person to binge read. I wanted to highlight some of the books that I have been reading and some comments. I am going to list them in the order that I read them and I will close with the order that I should have read them in.

Data Science from ScratchJoel Grus

This really was an excellent book to start with. It game me a good overview of what the field looks like and how to use the tools – Python. Not knowing Python did give me some challenges, but I was able to work around this with Google. Like most of the other books that I read it starts with some foundation in math, which was good because I have been out of school for more than a decade. Overall I think this was a good place to start.

Deep Learning with PythonFrancois Chollet

After reading about Neural Networks and Deep Learning, I was hooked. I google for a book and this one popped up. I had heard of TensorFlow before, but I didn’t know about Keras. Keras is a helper library which makes things very easy. This book was written by the creator of Keras. This one is awesome and in depth. I learned a lot from it, but there was some fundamental things that were still a bit confusing even with my superior google sleuthing abilities. I am still reading that last few chapters because I felt I needed to take a break. Honestly my brain was full, but I am a glutten for punishment, so I moved to the next book.

Mathematics for Machine Learning

This one was not for the faint of heart. I read through the first few chapters, but just like the last book it only made my brain hurt more. It is really a textbook in disguise, but it is really good. I plan on getting back to it soon because some of the things that are missing for me are the more advanced math.

Deep Learning from ScratchSeth Weidman

This was the best book yet. Neural Networks are really simple in concept, but I was still having a hard time seeing that. Seth takes a great approach to teaching each concept. He breaks them down using the math, code and a diagram. This approach really worked for me. The biggest part that really drove things home was writing a the neural network from scratch. Learning to Use Keras was good, but without the deeper understanding it was all a little too much voodoo for me. I give this one 5 stars. After reading Joel Grus book, I should have read this one second.

Machine Learning with Python for Everyone – Mark Fenner

I think this is the book that I should have read second. It is so comprehensive in the breadth of topics, I love it. This one is also a textbook in disguise. I don’t have much to say other than stop reading my post and go buy it already.