Tag: Ownership

Get In The Arena

Get In The Arena

Several months ago I had a need to cache function results across multiple executions of an API client. A quick web search revealed several solutions, the best fit being cachier. However, it was still missing a few important features I needed, and thinking it was the quickest solution, I wrote up a wrapper to implement these features and published it on PyPI.

One of the features was particularly tricky to get working without modifying cachier itself. Though I did get it working, I regretted not instead simply seeing if I could build my needed capabilities into that library itself and avoiding the wrapper altogether.

Turns out I had some additional free time, and took a crack at an integrated implementation of three key features, and turns out the maintainer of cachier was grateful for the contributions. I was also able to make additional improvements, which benefit all of cachier’s users, not just the one user (i.e. me) of a wrapper which is unlikely to get popular.

This experience was a good reminder that open source software is not built by a mysterious group of “other people” but by ordinary folks who graciously offer their limited time for the public good. Considering how much I’ve benefited from such generosity throughout my career, I’ve been thinking about what responsibility I have to the broader community. I’m not the only one. Do I have a professional obligation, or even a moral one, to contribute? Quite possibly, but either way, it’s something I’m going to do as long as I’m able.

Where My Mouth Is

Where My Mouth Is

As I get older, the more I’ve reflected on ways I can give back to organizations and communities that have had a big influence in my life. It’s why I contribute to open source projects. It’s why I respond to Stack Overflow posts (or at least try to periodically). And it’s why I give to the Wikimedia Foundation.

Despite it’s quirks and occasional inaccuracies, Wikipedia is a modern miracle of information that has shaped countless lives in inestimable ways. I find their mission statement a beautiful ideal: “a world in which every single human being can freely share in the sum of all knowledge.” Knowledge isn’t everything, but it’s a significant something; a necessary ingredient to human flourishing. And I’m happy to do my part to increase its presence in the world.

The Tie That Binds

The Tie That Binds

Read these two articles yesterday. On the surface they’re about different topics, but there’s a common thread: both call out an aspect of technical work that is often ignored, especially by the less-experienced.

The first tale, Our Company Fired the Best Developer and Project Manager, reminds us that “Getting your tasks done is half of the job. The other half is how you do it.” I’d go even further and say getting your tasks done is only a quarter of your job. The rest is how you do them, when you do them by, and most importantly, ensuring you understand why those are your tasks in the first place, and if perhaps you should be doing other tasks instead. Don’t climb the ladder only to find you leaned it against the wrong wall.

Coding Won’t Exist In 5 Years is yet another ChatGPT article, whose crux is the following: “Programming is the process of solving problems using a computer. Writing code is just one aspect of this process. It’s a necessary part, but it’s not the whole picture.” Yes, learn to write code well, but be aware you’re more valuable as an editor than as a drafter, and that’s only going to get more true as AI gets better.

That Personal Touch

That Personal Touch

Meeting regularly with your direct manager is an important mechanism for ensuring your work stays customer focused, getting actionable feedback and advice, and ultimately helping you achieve your career goals. This page captures a few of my thoughts on making them effective.

Firstly, you as an individual should own these conversations. Take the lead in setting an agenda, and come prepared with discussion topics. Your leadership has limited time, so use it wisely. Frequency and duration are up to you as well, though generally I’d say more frequent and shorter is better than one marathon session per month. However, there are times when longer discussions are needed, especially when goal setting and discussing performance.

Discussion topics can vary, though generally as a manager I’m less interested in discussing status on your day-to-day tasks and projects, unless you need advice or guidance on a specific issue you’re facing. I have other mechanisms to keep tabs on project health, so I’d much rather focus on personal development and goals. That being said, if you really want to give your manager a dump of what you’re working on (or just vent) that’s fine, but be careful not to use up all your time in this way.

Finally, I recommend taking notes during all 1-on-1 discussions, and especially having a mechanism for tracking action items for both yourself and your manager. I do that on my end for all my team, and share these notes in an email after each meeting, but using something more rigorous (like a ticketing system or task board) might be even better

Possible Agendas

Here is an example agenda I’ve used successfully:

  • Highlight / lowlight since we last talked
  • How can I help you this upcoming week?
  • What’s the status of your current annual goals?
  • Open discussion (you pick the topic)

And another agenda that also works well:

  • Personal check-in: how are you feeling?
  • Quick updates
    • Previous 1-on-1 action items
    • Tasks and projects
    • Current goals
  • Discuss current challenges and potential solutions
  • Recognize successes with gratitude
  • Create and review action items

And a third one:

  • Personal check-in
  • Task/project/goal progress
  • Review of priorities
  • Workload and expectations
  • Blockers
  • Feedback
  • Concerns

Discussion Questions

These are some questions I like to ask during a first 1-on-1 to learn more about how a person prefers to be managed:

  • What do you most need from me as a manager?
  • How do you prefer to receive feedback? In writing? In person? Another way?
  • How can I know when you’re struggling and need help?
  • Are there any manager behaviors that particularly bother you? If so, how can I avoid them?
  • What ongoing 1-on-1 cadence would be most helpful for you?

More generally, these are question I ask to help me as a manger how to make work more enjoyable:

  • What motivates you to perform at your best?
  • What do you wish you could spend more (or less) time doing?
  • At the end of the month/quarter/year, what would you like to say you’ve accomplished?
  • At the end of your career, what would you like to say you’ve accomplished?
  • If you could change one thing about work that would improve your life, what would it be?

These questions help me ascertain and guide someone’s career growth:

  • What impact do you think you’ve had so far? What additional impact would you like to have?
  • What aspects of your role do you love (or hate) and why?
  • What are you learning, and how are you growing here?
  • Is there a new project you’d like to work on? Or new goal you’d like to work towards?
  • What do you need training on? What do you need experience in?

Finally, these are question I ask to get feedback on my own performance as a manager:

  • How can the team improve its communication?
  • How can I help you be more successful?
  • How can we help you do more of what you enjoy?
  • How am I doing? What can I be doing better?
Automatic For The People

Automatic For The People

When I quit my first job after nearly 12 years, it was a shock to lose access to all the software I’d spent years developing. While I believe strongly in Egoless Programming, and resisting the notion of “my code”, so much reference material I’d built up was suddenly lost to me. I decided in that moment I needed to build up a portfolio that could not be taken away.

A few weeks ago I published Chrome Local Storage, a Python package that can read from and write to the Chrome’s browser’s internal storage, either one running locally or on an Android mobile device. The first draft didn’t have any CI/CD automation in place, but this weekend I fixed that.

It now automatically sets the version according to the git tag, runs some limited automated tests, runs a linter, scans both the code and dependencies for security vulnerabilities, and publishes builds to PyPI. All via Github Actions.

Did this project really need a complete pipeline? Not really, I doubt I’ll see much reason to modify it in the future. But I wanted to learn Github Actions, and I’d wanted to learn Poetry. Now I’ve done both, and have a publicly available reference to which I’ll always have access for when I need to build Python packages in the future. And if others need the same, they can use it as well.

Off To The Races

Off To The Races

In my previous post I mentioned an issue I had when building a CDK construct. As promised, today I’ll go through the problem I found: a dreaded race condition, which anyone who’s spent much time debugging software knows is a pernicious type of situation where behavior varies depending on the order in which various parts of the system execute, causing intermittent failures.

For background, part of the power of CDK is that it provides a framework for executing raw AWS API calls as part of a larger deployment. This is useful in numerous circumstances. For my construct, it enabled me to output several Managed Blockchain parameters that are available via API call but not from CloudFormation.

Under the hood these API calls are executed in a Lambda function that is created just for this purpose. This function has an IAM role, to which various permission policies are applied. For efficiency, it is only created once during a deployment, and then shared across all the API calls in the stack.

In order to keep my code well-organized, I’ve broken out the API calls in several places: one to gather data on the network member, and another to gather data for each peer node. And as a security best practice I want the permissions to be scoped as narrowly as possible. That means at each point in my construct where I call the function, I attach a policy that allows access only to the specific member or node being queried, via an explicit identifier.

Here’s the problem: IAM is an eventually consistent service, and thus policy updates are not immediately effective. Typical propagation time is only a few seconds, but it can take longer in certain circumstances. For the first custom API call in a CDK stack this is not an issue. The policy and role is created, and then the Lambda is created, the latter taking over a minute to be fully instantiated because it upgrades its dependencies at launch. However, on subsequent calls, because the Lambda is already warmed up, it runs immediately after the preceding policy update, and about half the time said policy is not yet effective, and the function fails due to a permission error.

It’s the “sometimes it works, sometimes it doesn’t” nature of race conditions that make them so difficult to track down. Thankfully I was able to identify and document my experience and pass it along to the CDK team. Anyone want to take a crack at a solution? I described several possible approaches in my write-up, with the “simple retry logic” approach likely being the best.

Putting Pen To Paper

Putting Pen To Paper

I spent some time today chatting with an early career colleague who’s looking towards a future career in the dark arts software development. Being the kind of person that enjoys the sound of my own voice, I enjoy these opportunities to pontificate. One piece of advice I routinely give is that good engineers write well, and developing this skill will pay itself back with copious dividends.

However, that shouldn’t be read to mean that quantity trumps quality. Far from it, keeping things brief is usually more difficult than not (I know I’m bad at rambling, kinda like I am now). Which is why I found this little article on the value of the humble readme such valuable advice.

The other day I published a blockchain solution on Github, and while I’m pretty proud of the code, the readme is in bad shape (as of today at least). For my next project (a refactoring of the core of this solution into a reusable CDK construct) I think I’m going to write the readme first, as the above article suggests. We’ll see how it goes!

Takin’ Care Of Business

Takin’ Care Of Business

Love them or hate them, ticketing systems like Jira or Asana are an essential part of modern software engineering. Misuse is rampant, but wielded well, ticketing systems align teams around common goals, unburden them from pointless status meetings, and unlock accelerated development with better accountability and fewer defects.

What are some ticketing best practices, you ask? I have thoughts:

  • Work of any significance should be captured in a ticket. My rule of thumb is anything that takes longer than a few hours.
  • Tickets are not a substitute for good requirements and design documentation. Instead they should capture specific tasks to be accomplished, including links to other docs as needed.
  • Writing tickets is not only the responsibility of the team lead or product manager; a team should own its ticket board. If the current set of tickets does not match the reality of what is being worked on, make it so be rewriting, breaking up, and deleting tickets as appropriate.
  • Being assigned a ticket is a form of promise. It says to the team “I will accomplish this task in this amount of time.” Each engineer should thoroughly understand all of the tickets assigned to them, proactively seeking out guidance if they don’t, and making clarifying edits as needed.
  • Know how metrics such as velocity and completion dates are computed. Their value is only as good as the ticket data used to calculate them (garbage in, garbage out), so ensure values like story points are accurately tracked.
  • Avoid Bricklin’s Law by embracing healthy use of a ticket system, and others won’t feel the need to add more status tracking. Done perfectly, it renders other status checkpoints redundant, maybe even those daily standups you dread.
  • Finally, tickets are a means, not an end. Don’t lose sight of your ultimate goals. If your ticketing process isn’t helping you achieve those goals, change it.

The above list is far from exhaustive. Any other suggestions out there?

Be Kind, Not Right

Be Kind, Not Right

Several months back I read The Phoenix Project, a tale about how one company changed its IT culture to great success. I found the advice mostly good, and the idea of dishing it out in narrative form kept things interesting, though I’d hardly call it a page-turner.

However, one aspect really bugged me about it: the “guru” character Erik is a real piece of work. Talking down to his colleagues. Deliberately getting names wrong. Assuming his own body odor smells of perfume, as the Amazon leadership principle warns against. In the actual world, without kindness, it doesn’t matter if you’re right all the time, no one will listen to you. This is just as true in the realm of technology work: ever been told to RTFM and felt like an idiot? You’re not alone. I have to fight being that kind of jerk, but it’s a fight worth having.

And of course it really shouldn’t be that hard of a fight. Just do the little things: be on time, be responsive, be quick to listen and slow to criticize. Be patient. Treat others as they wish to be treated.

Oh, and learn your colleagues names, both spelling and pronunciation. It’s a basic gesture of respect that goes a long way.

Word Salad

Word Salad

Yesterday I was notified via email that some of my personal information had been compromised by the ParkMobile app. Besides the obvious question of why it took them two months to contact users proactively (vs a post on their website), I found this paragraph a blend of confusing and concerning:

Encrypted passwords were accessed, but not the encryption keys required to read them. We protect user passwords by encrypting them with advanced hashing and salting technologies.

So many things wrong with the above. First, passwords should not typically be encrypted, and certainly not in a way that would allow a company to read them. The better approach is to hash them, which ParkMobile mentions later, but encryption and hashing are not the same thing. It’s hard to trust an organization that doesn’t know the difference.

Additionally, the adjective “advanced” gives me pause. It’s not communicating anything of value. Why not instead tell me the exact algorithm used, such as bcrypt, Argon2, or PBKDF2? Most likely the person writing the response doesn’t really understand the technologies used to protect passwords. And claiming something is advanced when one has no ability to know if such a claim is true screams Dunning-Kruger effect.

Ironically in an attempt to express competence, ParkMobile has done the opposite.