I had a conversation last year with a developer I respect and admire. They were talking about how they just couldn’t seem to blog, though they wanted to.
Some quotes from them:
For me it’s mostly about structuring the text and getting in some kind of flow. I know what to say, but every sentence is difficult to formulate in a way that I’m happy with it.
Not sure if it makes sense or not. I see some people write a blog post about something in an hour (or quicker), and it’s like magic to me. I have about 50 topics for things I’ve been thinking about really hard that I would want to share with others, but just getting started writing is a huge roadblock.
I thought I’d post some points of response to them on the off chance it helps someone else, because it’s certainly not the first time I’ve said these things.
There is a fantastic book that you might find interesting about this. I read it during college and I still keep a copy with me. It’s called “Bird by Bird” by Anne Lamott – it’s a quick read and the way it’s written is kind and funny.
Two aspects of that book really stuck with me, and I think are applicable to software as well as writing:
A related concept for productivity is batch work. I got some great advice on this from Ali Spittel as well (thanks, Ali!) Do one task across multiple things. You have 50 topics you want to write about. Maybe pick 5, and spend a solid hour doing nothing but coming up with a small bulleted list outline of what you want to say. Then maybe your next batch will be ensuring that the “why this matters” (to your, or to your audience) is clear. Etc. etc. – however you work, do one task at a time across multiple articles rather than trying to tackle one article at a time. It helps keep you in a similar head-space which helps focus and flow.
Another technique I used to use with folks I worked with was akin to rubber ducking. I’d ask them what they wanted to express or say about a topic. Then I’d ask a few completely open follow-up questions like “what do you think is most interesting about this?” etc. And I’d just write down parts of what they say and repeat it back to them. Things would click and they’d say “oh, yeah, that sounds like a paper.” So you might want to let yourself try rambling and talking about it out loud and just jotting down key phrases as you go.
Also, take the pressure off! Your blog posts don’t have to be canonical references that stand the test of time. Anything you put out now is going to help someone who isn’t you level up. Also, people will have questions and feedback – no matter what.
Writing, like giving conference talks, is definitely a muscle memory. I used to sweat giving talks and now I can structure a 60 min talk and deliver it with very little notice. When I’m out of practice writing, I find it’s hardest to get back into the habit. But once I’ve built up the muscle again by forcing myself to do it, it does get easier.
Last tip – something I do personally.
My blog is on GitHub, and therefore is a repository that can make use of GitHub issues. I post ideas for entries into those issues. I give myself no requirements for it, so as not to get in my own way. I jot down whatever I have. Sometimes it’s bullet points, or an observation, or a killer one-liner (in my eyes at least :sweat_smile:) that I want to build something around. Sometimes those things sit there. Then I’ll take some time to go break down the ideas. Every once in a while I’ll think “wow, that’s essentially pretty much written” and I’ll create a PR for it and polish it up. My goal is that once it gets into a PR it gets out the door ASAP before doubts grow or before it stagnates.
There are a lot of possible ideas sitting there. They’re not all gold, and they don’t have to be! Sometimes I’ll realize I didn’t want to write about something as much as I thought and I’ll close it; sometimes I’ll get in a writing mood and draft 5 items from my notes. But having the list and having the notes broken down is crucial for me.
Post your favorite tips for getting un-stuck in the comments!
]]>Caveat up front: There are lots of ways to do this well; this is just one way that happened to work without a ton of effort on my part.
The job description is a way for you to live your company’s culture. Use that to your advantage. Does it reflect the values of your organization? Does it reflect the way you intend to show up as a leader? Think about key words and ideas that reflect your culture/value that you feel strongly about and work them into the post.
Job posts are a filter – and that’s okay!
I believe the art of a good job post is candidate self-selection. I want to inspire candidates who would be a great fit to self-select into the role, and I want candidates who wouldn’t be a fit to self-select out.
That means that a job post in a sense has to be performative – it should evoke a response in order to get candidates to do one of those two things.
In our case, here are some key phrases I used and the signals I hoped to send to get candidates to self-select:
Phrase | Impression |
---|---|
“We are embarking on the next phase of our product offering” | A sense of adventure and also the unknown. |
“We’re also looking to the future with an eye toward new products” | People looking to learn and build, and who are comfortable in emerging work streams. |
“We are operating on the cutting edge of our ecosystem. Our platform runs on .NET 8 (on the first day of its launch!)” | Staying current, learning together, moving quickly. A “no BS” signal and a “low management/process overhead” signal. |
“We embrace and cultivate a culture of humble leadership and support. We thrive on input and collective ownership.” | Team members will need to provide input; we want and need to be comfortable driving things forward. We will support each other. |
“We take our work seriously, but also care about work/life balance.” | It’s not a 9-5 job; we need people to care about impact. We also have flexibility because we’re more results-oriented than time-oriented. |
“If this sounds like you, we encourage you to apply, even if you don’t tick every box” | We care about helping people grow. Our goal isn’t to just weed people out our “hire elite people”. |
“You don’t mind a little bit of chaos. 😅” | We need people who are comfortable in dynamic environments and are willing to help things grow. People who need well-established systems or lots of process will not do well here. |
“You care about radiating information and ‘working out loud’” | Attracting people who are happy to work transparently, which is important for a small team. |
“You know that we all grow together.” | We want someone to be comfortable both learning & teaching. |
“a team that wants to level each other up” | Again, growth mindset and expecting that to be a two-way street. |
“You want to continually improve your working process and tools to enable you and your team to deliver better and faster.” | Continual improvement and the motivation involved to accomplish that. |
“You’ll talk directly to the hiring manager” | We’re a no-BS company. |
“Salary: Depends on experience. We’ll make sure nobody’s time gets wasted.” | I had a decently large range on the salary, and I wanted people to know I was interested in paying what they’re worth in our market, and I also didn’t want to waste time doing a negotiation dance if I could help it. |
The goal of all of these phrases: to get motivated people who are tired of being constrained and who want to do their best work on a team that moves quickly to self-select in. And conversely, people who might be looking to hide amongst process or shuffle along in a 9-5 kind of way in a big org would hopefully self-select out.1
Several applicants made reference to the description of “humble leadership” and “thriving on input”. People also had great follow-up questions about the “chaos” that helped me go deeper into conversation to see which candidates would bring the most to the org. Several were excited about the growth opportunities and were attracted to the idea of building new and emerging things. And a few candidates mentioned “leveling each other up” as a strong positive signal for them.
The structure of a job post also sends a message and is performative in its own way.
I like to structure a post in the form of:
Here, I add brief company background in terms of mission and who some of our customers are. I give a brief look into the future of where the org or team is going. Here is also where I put a lot of the signaling phrases above about culture and organization and the tools we want people to be excited to work with.
I try always to include a phrase similar to:
If this sounds like you, we encourage you to apply, even if you don’t tick every box. It’s okay to let us know where your strengths and weaknesses are on this list.
I want to ensure that great candidates don’t fall victim to imposter syndrome and opt-out because they’re weak on one bullet point. I also give special considerations to candidates to tell me where they’re weak on things, because it indicates self-awareness and a willingness to grow.
I try to keep the list of bullets here to the absolute “day 1” skills. The rest should be able to be learned. I also add a list of additional skills and note that “We’ll prioritize candidates who bring one or more of the following” to further encourage stand-out candidates to self-select in.
The skills list here contains technical skills but also core skills around attitude & philosophy (“you value ‘working out loud’”, etc.) – we want to people to self-select in when they feel like it describes them.
I keep this more high level and tend to talk about the ways this role will contribute to team goals, and a little about the day to day.
I also try to mention an area of focus for the role. This is partly to help set expectations, but also to see if people ask any questions about that specific focus (a strong positive signal in my opinion).
This section exists specifically to send a signal that we want people to want to grow, and we’ll support that. Our goal isn’t to have team members just churning out the same code all day long. This is a great place to attract folks who have a development skills and may be seeking more ownership in the overall delivery process but don’t know how to acquire those skills, which might be “day 1” skills in other roles.
This is the hard part. I think job posts will perform best when they come from someone who’s the hiring manager or close to the hiring manager, and who can speak to the highlights of the organization’s culture. That’s what allows a job description to be infused with authenticity.
The key phrases you use in the job description and the signals you send are things that have to be based in your organization’s current reality instead of wishful thinking. Otherwise candidates – or, even worse, new hires – will sense this and feel duped, leading to bad outcomes and wasted time.
If you can’t post authentically positive things about your organization / team, you probably should work on that first. Let’s make job descriptions real again.
I had a number of candidates I really liked for this position, and in the end, I was able to make offers to two phenomenally talented coders.
In many cases, applicants saw this job post through messages from other professionals in communities who sent it to them and said “this sounds like you”, and they felt the job description authentically described a place they wanted to be. That feels like a resounding success.
Nothing wrong with that, by the way. I don’t think someone’s job has to be their life. But I do need a certain dynamic in our organization at this point in time. ↩
Dear reader, I’d love to save you some trouble there.
In software development, feedback loops are key. If we can iterate 10 times on something while our competitors are still getting their shoes on, chances are we’re going to come out ahead. This ability to adapt and respond to change is one of the driving forces at the heart of agile software development. Many loops exist all over our organizations, and the more we improve those loops, the more we improve our organization.
They involve scheduling and logistical acrobatics, they steal focus, they cost a lot of money, and they often lead to more follow-ups and work (not to mention more meetings.)
What can we do to get ahead of and shrink these expensive feedback loops?
What is the outcome of a meeting? Surely we can try to get to that outcome faster.
If your meeting is to… | ..then try this instead |
---|---|
Make an announcement | E-mail, Organization Chat e.g. Slack or Teams. A notable exception here is around organizational alignment on crucial topics, where you may need all the people to hear the same thing in the same place at the same time. |
Get Feedback/Consensus | Set up a form and send via e-mail, start a discussion thread, take a poll in your chat tool, do one-on-one outreach |
Reach people who don’t read your e-mails | Accept that those people might be too busy or too disinterested. Maybe they don’t need to be involved. If you have a decision to make, make it without them. Also, try more communication channels. Chat tools, phone, one-on-one meetings, etc. Also, ask for feedback on why your emails aren’t resonating. |
Present awards or praise | Private congratulation and a public e-mail announcement? Make a part of another meeting? (meetings for praise/celebration can be very nice; just do it consciously.) |
Brainstorm | A meeting might be helpful for this. But ensure you facilitate, do the prep work, and block off time |
I got this one from Al Pittampalli’s great book, Read This Before Our Next Meeting.
How can we make a decision if we’re not doing it as a group in meetings?
Ever been in a meeting where you or others realized you weren’t really needed halfway through? Painful, right?
Every meeting invite should contain:
Beyond just listing those items, you have to ensure that you actually stick to it, so if the discussion deviates, others who have opted out (more on this shortly) will have a chance to weigh in. If people can’t miss a meeting because of an inevitable important side conversation, painful meeting bloat will continue.
Sometimes when you invite people to a meeting, they feel that they have to attend. This leads to a lot of wasted time.
State in your meeting invite if it’s OK to opt-out and when – but also that the work of the meeting will go forward without the attendees who aren’t present. If someone really does feel they’re critical but has a conflict, they can ask for a re-schedule (or better yet – delegate their proxy to someone else).
This will drive a focus and energy for the meeting, because the time constraint ups the ante and because there’s a shared sense of being accountable for the outcome.
Don’t let the meeting invite just be an empty space.
Maybe you’re in an organization where this advice sounds like it comes from another world. I was once in such an organization, and used the techniques above to start a shift after reading Al’s book. Whenever I got the chance to run a meeting there, I’d send a short write-up of these rules, either to individual meeting attendees or as part of the invite. I framed it as an experiment – “this is something I’m trying that I think will help all of us. But in order for it to help, I have to stick to it.” I spent time prepping for my meetings. I made sure the notes were there. I celebrated when someone didn’t have to attend, or when we finished early. I called out people who had clearly done their prep work and thanked them. I asked for feedback on how my facilitation could be more effective.
I started to notice signals that something was taking hold when others began adopting my rules and I got positive feedback on how attendees felt. People were more energized and engaged around our topics. And, since the people who weren’t interested could opt out, the more engaged people had less noise around moving things forward. I also started to use this to opt out of meetings that clearly didn’t add value for me, which in some cases led those organizers to ask for feedback which I could use to discuss facilitation techniques.
Your mileage may vary, but I hope this helps. Let me know in the comments if this resonates, and tell me some of your techniques for improving meetings!
]]>docfx
to publish the NUnit docs, because it has a lovely capability of generating docs for our API reference in addition to all our articles.
However, one thing I often yearn for – that I get on this Jekyll blog and some others I work with – is the ability to have a live preview within a pull request of what the generated site will look like.
Because the source code for the API docs is in the nunit
repository, and the docs live in the docs
repo, it’ll be a little extra complicated.
Nevertheless: Let’s make it happen.
Below are the steps in our docfx build process – I’ll break them down one at a time:
- uses: actions/checkout@v4
name: Check out the code
Self-explanatory; we need our code if we’re going to build it.
- name: Get latest NUnit Asset dir
uses: dsaltares/fetch-gh-release-asset@master
with:
repo: 'nunit/nunit'
version: 'tags/v${{ env.NUNIT_VERSION_FOR_API_DOCS }}'
file: 'NUnit.Framework-${{ env.NUNIT_VERSION_FOR_API_DOCS }}.zip'
token: ${{ secrets.GITHUB_TOKEN }}
Because the source code that contains the DLL is in another repository, we use this GitHub action to pull the file via pulling a specific tag (currently hard-coded. I’ll get around to fixing that. Probably.)
- name: Unzip NUnit Asset zip file into its own directory
run: unzip NUnit.Framework-${{ env.NUNIT_VERSION_FOR_API_DOCS }}.zip -d ./NUnit.Framework-${{ env.NUNIT_VERSION_FOR_API_DOCS }}
- name: Copy NUnit Asset dir
run: mkdir ./code-output && cp -r ./NUnit.Framework-${{ env.NUNIT_VERSION_FOR_API_DOCS }}/bin/net6.0/* ./code-output
We unzip the asset file and copy it to the right spot.
- uses: "nunit/docfx-action@v3.0.0"
name: Build with Docfx
with:
args: docs/docfx.json --warningsAsErrors true
With that in place, we run docfx
to mash everything up into one deployable site.
- name: zip site contents
run: zip -r _site.zip docs/_site/
- name: Archive site artifacts
uses: actions/upload-artifact@v3
with:
name: siteArtifact
path: _site.zip
We zip up and archive the site contents. This is just for reference.
- name: Start deployment (PR only)
if: ${{ github.ref != 'refs/heads/master'}}
uses: bobheadxi/deployments@v1
id: deployment
with:
env: preview_${{github.event.number}}
step: start
token: ${{ secrets.SEAN_PAT_TO_MANAGE_ENVIRONMENTS }}
This creates a new deployment environment for the PR number and creates a deployment to it with a status of started.
Note that it requires a personal access token that has the authority to manage environments.
- name: Deploy to Netlify (PR only)
if: ${{ github.ref != 'refs/heads/master'}}
uses: South-Paw/action-netlify-cli@v2
id: netlify
with:
# note that the --json flag has been passed so we can parse outputs
args: deploy --json --dir './docs/_site' --message 'preview [${{ github.sha }}]'
env:
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }}
This uses the Netlify CLI to push all the site’s files. We can see it in Netlify because it’s a separate preview build with its own message.
Note that it requires a Netlify site to have been created and to produce an Auth token and a site ID, which I store in GitHub secrets for this action.
- name: Update Preview link comment
if: ${{ github.ref != 'refs/heads/master'}}
uses: marocchino/sticky-pull-request-comment@v2
with:
header: previewlink
message: |
Preview link: ${{ fromJson(steps.netlify.outputs.NETLIFY_OUTPUT).deploy_url }}
I was happy with this one. It uses a great GitHub action to post a sticky comment and uses the JSON output of the Netlify CLI to post the URL.
- name: Finish deployment
uses: bobheadxi/deployments@v1
if: ${{ github.ref != 'refs/heads/master'}}
with:
env: ${{ steps.deployment.outputs.env }}
step: finish
status: ${{ job.status }}
deployment_id: ${{ steps.deployment.outputs.deployment_id }}
env_url: ${{ fromJson(steps.netlify.outputs.NETLIFY_OUTPUT).deploy_url }}
token: ${{ secrets.SEAN_PAT_TO_MANAGE_ENVIRONMENTS }}
And here we go ahead and mark the deployment to the preview environment as “finished”.
Thanks to so many people who’ve worked to make others’ lives better, my experience was largely in googling around to discover that people had already done all the things that I needed to do! I look forward to being able to contribute more of that myself if I can ever find something that needs doing.
We can’t leave those environments hanging around in our GitHub. So we delete them, using the same id format that we used when we created them.
on:
pull_request:
types: [ closed ]
jobs:
prune:
permissions:
deployments: write
runs-on: ubuntu-latest
steps:
- name: delete environment
uses: bobheadxi/deployments@v1
with:
step: delete-env
token: ${{ secrets.SEAN_PAT_TO_MANAGE_ENVIRONMENTS }}
env: preview_${{github.event.number}}
Once I got all the moving parts working together, it was an absolute delight to see it in action and I’ve used it so many times since. I hope this article helps someone else arrive at this place in slightly less time than it took me. Questions and feedback welcome in the comments!
]]>Hope you or someone you know might get value out of it.
]]>Today also happens to mark 6 months since I started at SCT Software as VP of Innovation & Products. That represented a big move for me – becoming responsible for leading an emerging engineering organization.
I’m a big believer in keeping a “good stuff” list. My experience so far has felt phenomenal, and I figured I should take my own advice and take stock here. Below are some of the highlights of the past 6 months. I’ll try to lump things together into some general categories. NONE of these things happen without an awesome team and environment – I don’t work in a vacuum. But I’ll list things I had at least a large part in.
This is a personal post and this list is just for me, but I’d still be happy to hear any questions about it in the comments!
docker-compose up
and have everything they need.That’s one of my favorite phrases. I feel like I’m doing some of the best work of my career, and I can’t wait to see what will happen in the next 6 months. There are plenty of ways for me to grow and learn still, and plenty left to achieve. I feel empowered and supported and like I’m working to be better at extending that feeling to others every day. I’ve got an excellent team and an organization with great bones. So when I think about what’s next, I’m excited.
]]>When setting teams up for success with modern software delivery, I’ve found it helps to create “successful paths of least resistance”. Here are some things I’ve tried, learned, and had success with in the hopes they might help someone else. I prioritize understanding the state of these things first if I don’t see them in an environment I enter.
All of the tips I share below assume that you have built trust and spent a good chunk of time listening to people/teams and sensing patterns of possible improvement.
Software delivery is a team sport. Any approach that tries to improve things without caring about and for the people who will be impacted is a recipe for things to go wrong.
Not sure if you’ve done that enough? Here’s a barometer: if you’ve listened enough, some of these suggestions will seem like great ideas and others will fall to the back of your backlog because you’ll have a feeling they might not apply.
If you haven’t worked to build trust and rapport with your team, do that first.
With that said, let’s look at some techniques that have accelerated the happy path on teams I’ve led or been a part of.
A quick introductory note: when I say “modeling behavior”, I mean “demonstrating the way you’d like your teams to act”. What you do is who you are. Your actions will influence the actions of others on your team.
Explicitly ask for feedback. Discuss ways people like to give and receive feedback. Authorize people in one-on-one settings to provide this feedback, especially in front of a group. And celebrate the heck out of it when it happens. You will not always be perfect at this; I’m sure not! But working at it continuously will help you and your teams flourish.
I also have some thoughts on how I model pull request creation and PR review, for those who are interested in that specific approach.
I’ve found that GitHub Flow tends to hit a sweet spot for teams that didn’t previously have a good happy path. One main branch with short-lived pull requests off of that main branch is a model that can fit into most developers’ heads. This makes it easier to talk about how software is delivered.
NOTE: This won’t work as well if, say, you’re delivering multiple branches of software at a time (e.g. supporting 1.x and 2.x for various customers). It’s important to recognize the practical limitations here; if you’re in that situation, you’ve likely already discovered a different happy path.
Software development is a team sport. Teams self-organize. If people want to pair/mob on a problem because that will produce the best output, then that’s what I want, too. I try to think of a ticket assignee as an ambassador for the work; I’d like them to provide the update but I trust a pair/mob to operate as a team. There’s no competition for who can complete the most tickets; We succeed together or not at all.
If it doesn’t already exist, automating continuous integration on all pull requests can be a game changer. We can shift a lot of quality control “to the left”, helping developers avoid bad merges before they happen. This sensible default provides a happy path that improves quality. You can then add on to it – think about spell-checking for docs, or automated security review, or image optimization, or tests that will help.
If these don’t exist, I try to – at a minimum – add the foundation and infrastructure so they can begin to exist. Then, I add a few basics. Over time I’ll use these, or will come across opportunities to help the team use them.
GitHub and other tools allow developers a choice of merge styles when PRs are merged. I’ve found that in most cases, especially if adopting GitHub-flow-style PRs and automating continuous integration on them, the “squash and merge” option is a great default. It squashes many small commits, keeps one commit per PR, and still ties things back to the PR for future reference. This also frees developers to feel they can make many small commits (which I’m a fan of) without polluting the main branch when things are merged in.
So in my teams, if a default hasn’t been strongly established, I typically make “squash and merge” the default option. I’ve yet to hear a complaint.
I strongly recommend introducing Dependabot or RenovateBot to provide the ability to track and surface updates for your code an infrastructure dependencies in an automated fashion. Keeping dependencies up to date is too often forgotten until it’s a big chore. Creating a sensible happy path around this will improve both security and the developer experience of your teams. It also will probably lead to a few (likely inexpensive) lessons on the importance of reading release notes before merging (or improving your CI system to better detect issues with some dependencies).
I always create or update the README
file for a repository I’m going to be working in regularly. I add the information I wish I knew that’s relevant to the code, and aim to give a new team member a smooth start. This might include conceptual introductions, tooling installation instructions / scripts, historical context, etc.
Zooming out a little bit from an individual codebase, I also think it’s important to give new team members a landing page on day 1. I tend to ensure this includes a checklist of the things that need to be done – both by them, and for them – as well as helpful links and frequently asked questions. I try to make a new team member’s first task be to improve the on-boarding page and README
for anyone who comes after them; this explicitly empowers them to question things, which sets the tone for their tenure in addition to improving the content.
If they don’t exist, I try to create paths of least resistance for people to radiate information – to put things out there in ways that help synapses fire across the group or organization. This takes some experimenting to find what works for your specific context, but some successes I’ve had in the past include:
#TIL
) channel or space where people can put helpful tips and celebrate learning.#dadjokes
channel and a #twinning
channel (for when people looked to be dressed the same IRL or in a virtual meeting).#megaphone
channel or similar, when you want people to re-post something or hype something up.We can disagree on rules or formatting considerations all we want, and I find it best to be flexible in matters of style. But, there should be some tooling and process to auto-enforce the rules we care about.
One way to do this is to run your formatting tool all the time. For example, there’s a great GitHub Action for the dotnet-format
command. You can use it to run all the time and commit changes back to the branches. Now nobody has to think about the rules unless they disagree with them. And if you disagree, you can meet about it, update your .editorconfig
file, and auto-format your codebase to be in-line with the new preferences.
One rule I like for this that I learned from somewhere a long time ago is the “30 minute rule”. As in: don’t ask for help until you’ve spent 30 minutes on trying to solve an issue yourself, but don’t wait longer than 30 minutes to ask for help. I like it because it’s an easy thing to remember and it applies to everyone regardless of seniority.
Similarly, improving things is important. Try to regularly hold retrospectives, or at least continually ask what can be improved and praise people when they note those opportunities. “Developer Experience” is a legitimate category of software development work, so I try to ensure it always exists somewhere as a formal bucket to capture those suggestions as well.
This is by no means a complete list, but I have to stop here lest I spend way too much time trying to wrack my brain for every tip I’ve seen or lived. Tell me about your happy path in the comments!
I’m not a believer in “root cause”. There’s almost never only one cause of these things. ↩
I believe these sorts of things are context-dependent. My current context is as a VP in a smaller organization who’s leading multiple SaaS product efforts with a small team while building up our delivery acumen. And it’s going well.
Some – probably many – of these notes may be widely held; you’ll certainly see them echoed in thinking about agile, devops, and modern leadership. I’m not claiming to have invented these things; I stand on the shoulders of giants. This is a summary of how I’d explain these things in conversation.
As VP of Innovation & Products, Innovation is right there in the title. What does that mean?
There are a lot of definitions that I like, but I’ve settled on my own language:
Innovation is the act of continually reinventing ourselves and our approach so we can add value and delight.
I think creating delight applies both to our customers and to our fellow colleagues.
Everyone should be able to:
I want to work on a great team that levels each other up. I want to do great individual work, but also I want to produce the kind of impact that is only possible with the sum of our skillsets.
There are things we do over and over again as a team/organization. The more of those loops we complete and improve upon, the faster we’ll deliver great impact and adapt where needed. Whenever we shrink one of these loops, it’s like compound interest that makes us better over time.
Much of what is below is an extension of this principle.
I depend on our collective insight. I have a vision and work to find alignment with our team, but we’ll only ever be as good as the issues we surface and resolve.
Questioning me often involves a little back and forth because I’ve typically put a lot of thought into something and so I need to go deeper. I’m working on “leading with inquiry” so that I don’t come off intense or defensive in these moments, because having someone improve our vision/tactics is almost always a favorite moment later.
I’ve written plenty of crap code. I’ve been lucky enough for people to provide great reviews and level me up. That’s what I want for everyone.
It’s good to remember that anyone can teach, anyone can learn, and we need ourselves to be critical of each others’ code so we can get better. That requires us to he humble about our code, and to understand that our code is not the measure of our worth as developers
Get something out there and iterate on it. Don’t try to make it perfect. There is a cost to the delay. Shitty first drafts win over that every time.
Don’t get me wrong: great first drafts – when they happen – are even better! But too often things go undone or untried because we don’t feel they’re polished enough.
I’ve re-learned this lesson a lot of times. I’ll probably keep re-learning it.
I truly feel this way, and a wonderful human/leader I worked with (shout out to Jeff Gallimore at Excella!) felt that way too, and taught it to me. His ability to receive feedback in all forms really set him apart for me (and still does).
When someone wants me or my team to succeed enough to offer their critical feedback, I want to honor that. I love for as many people to move toward this as possible, but that’s a personal journey and doesn’t happen overnight.
I am very much inspired by the “leader/leader” model espoused in L. David Marquet’s book, “Turn the Ship Around” (again, big credit to Excella there). There’s a lot to unpack in a whole book but I’ll sum it up by saying I want everyone to feel like they can be a leader at any time, and I want our team to operate as an empowered group of leaders with a common goal.
Try to figure something out for 30 min before asking for help. You’ll learn stuff and become more confident in your problem solving ability.
Don’t wait more than 30 minutes to ask for help when you’re stuck. Sometimes it just takes another person, and that’s fine! We will all get to learn something.
I’m a big fan of Scrum in many cases and have a background in it, having been a certified trainer for the CSD certification.
However, I believe Scrum is optimized for predictability. This is great, especially in environments where a lack of predictability is harmful. However, predictability can sometimes hamper effectiveness (as we see in the backlash articles against Scrum, which often make good points about its effectiveness).
In many environments – high performing teams or small companies where communication paths and feedback loops are small – Scrum is not the right choice.
If you’re already effective without it, optimize for effectiveness. In my current context, that means Kanban and the continuous pull of work (with enough slack in the system, of course)
This one is huge for me. Work “in public”. Start pull requests early. Share your thinking along the way. Always be “journaling” – posting updates on tickets, adding to wikis, sharing what you learn with colleagues.
Sure, I stole this directly from the concept of Generative Culture, but it resonates enough that I try to put it directly into my approach.
Things will go wrong. We will learn as a team and as individuals. It should be OK to say you messed something up, and it shouldn’t come with consequences. It should be on us to build our systems such that the blast radius for those things is small.
Less meetings. More chats and wikis and empowering people to make decisions. Leave messages and don’t expect immediate responses.
Don’t share office file copies etc. Make them live collaborative docs and share links. Something magical happens.
A recent example of this: rather than downloading some analysis in an Excel sheet, we started making it a link. Now I can add questions as comments using the review tool, and even assign those to someone, and we see the whole history right in the document.
It may seem counter-intuitive because people (understandably) don’t like to context switch. But unblocking each other (and collectively sharing what we learn) is often more valuable.
I try to be clear that this extends to me, too. If I’m doing something, I need people to ask for the help they need, and I need to stop what I’m doing to unblock and empower them.
Up front: this doesn’t mean “always do extra hours”, which is how a lot of the industry likes to weaponize it. Nor do I expect everyone at a job to be trying to do the best work of their life.
But, this means if I’m getting close to something that could help someone, I finish it. It means if taking a little extra time makes something much better, I do it. I optimize for being as impactful as possible. That also means that some days I’m less effective, and I have to accept that and focus on less impactful work those days.
Balance doesn’t mean 50/50. I’ve been putting in just enough more time to be really effective, and it feels great. And I know I can take downtime when I need it. If my team trusts in that, I want them to be able to opt into it too. But that trust and opt-in is extremely important so that this one doesn’t backfire.
It’s an important tool in the toolbox. Where it helps us move faster and with confidence, we should do it. That is probably more places than we think. I love TDD and the way it forces me to break problems down. But mandating the practice of TDD across all code or automation for its own sake isn’t helpful.
Favor small work that flows more quickly toward production. Try to deliver many small chunks of work. Use things like feature flags to ensure work can go out the door without being activated, so that work doesn’t have to be held up.
The Prime Directive is important enough that I’ll repeat it directly here too:
“Regardless of what we discover, we understand and truly believe that everyone did the best job they could, given what they knew at the time, their skills and abilities, the resources available, and the situation at hand.”
At least slightly. Improving our approach to the work is compound interest – it builds up over time and affects all future work. Thus, we should do it sooner rather than later.
Some of these principles are in natural tension with each other. It’s bound to happen.
When I hit a conflict between these things, I try to think: What is best for the people on my team who are involved? What’s best for the people in our organization? Usually that helps clarify the right choice/action. People make up a company; we have to be people and look out for each other first & foremost.
I may update this post soon as I inevitably think of something I left off, but: what are some things you expected to see but didn’t? Sound off in the comments!
]]>You’re not alone. I think this, too – as do many hiring managers. We fix it where we can. Some of these tips are silly – the result of bad systems and outdated practices, and I wish many of them weren’t necessary.
I am rooting for every candidate to succeed. I hope all candidates know that hiring managers want to find a fit. These tips are just that – tips to navigate a difficult system, from my perspective as a hiring manager in my current context. Should you have to do them? No. Will they help? I hope so.
[FirstName] [LastName].pdf
than it was to find Resume (5).pdf
. Naming this well from the start tells me you’re thinking about my experience as an audience. It’s a minor detail but it stands out because it tells me something.Tech hiring is awful in that there are now whole systems designed around surfacing keyword matches, and gaming these systems has become unfortunately necessary for applicants. I abhor this. With that said, if you’re a candidate who has a resume like this, it’s important to know that it works against you when submitting to companies who don’t subscribe to this philosophy. Have a an authentic resume at hand, too, and choose which one to use based on your best information. You will stand out.
Your resume should have bullet points for your roles. The organization and title are not enough, because they don’t tell me enough about whether an interview makes sense, and with so many applicants, I can’t give the benefit of the doubt except in very rare circumstances. I also use the resume to help formulate interview questions based on claims you make; if there’s no content, it makes my job harder there too.
I suggest taking all the data points you have for your roles, and adding them in priority order of:
Once you get to enough bullet points for that role, move on.
Don’t pad your resume with typical or daily activities (e.g. “attended daily stand-ups” “wrote code”). If you feel the need to point these things out, condense them into one bullet or make them part of a position description above the bullets.
Understand if you’re submitting to a human, and don’t submit 1,000s of bullets that are clearly SEO. If you break one concept into 3 bullet points, it only gives me the impression that you may not understand that concept.
If those much more basic things are considered accomplishments, how can I expect the impact that I’ll need someone to have on the team?
Claiming results is good; claiming outlandish results backfires. Really? You increased client satisfaction 90% by switching a software library? Be prepared to answer questions about how these things were measured and how you traced your actions to that outcome.
You don’t have to claim amazing results; the fact that you care about value and how to measure it when possible is a big point in your favor already.
Despite this being a relatively small role, I received at least 3 resumes that looked almost exactly the same. Not just the same format, and the same many bullet points but when I looked closer, the content was almost exactly the same. This blew my mind.
Now, maybe these people were just scammers, but it honestly didn’t seem that way. So I’ll just say: beware of templates, especially any that contain helpful language. Because if you’re submitting it without major modifications, chances are someone else is too. It immediately disqualifies you both; how do I know what else isn’t plagiarized? It tells me something about your work ethic and respect for the work.
If you have a GitHub profile or a web site, I strongly suggest listing it. It doesn’t have to be brilliant and you don’t have to be active. I don’t judge the content or the code there, but it sends some signals. It tells me you care about community and sharing/gaining knowledge.
If you don’t have a blog or GitHub, I recommend taking a little time and getting started with one. You don’t have to self-host a blog; content on places like dev.to works great, too!
Take 2 minutes to write actual bullet point responses if you want the job. Don’t use Chat GPT for this. It sets you up for a bigger letdown from me when I say “ooh, someone took the time to do this!” and end up with “…nevermind, they think I’m too stupid to notice this was written by AI and doesn’t actually say anything.”
The hiring process is hard enough on everyone without more enshittification.
Find your local & global communities on Twitter, Mastodon, Slack, LinkedIn, Discord, etc. – many have jobs channels where things will pop up. A candidate coming from a community is seen as a sort of implicit reference in terms of places you may participate. And there’s usually little downside as you learn things, participate in discussions, and build relationships there that are nice either way.
I wish you the best of luck finding your next opportunity! Let me know your thoughts in the comments.
]]>I’ve worked with some great recruiters (shout out to Excella!) but I had no infrastructure in place and we weren’t hiring enough people to warrant investing in a separate product.
However, we did have Jira.
So, here’s what I did:
Applicant
created by the project (you could create your own if not using the project)has_testautomation
, has_devops
, has_industry_experience
)standout_resume
, has_referral
, via_email
for those who did a nice e-mail intro)down_selected
as a label too.feedback_requested
label so that I didn’t ask more than once.Now for some sweet stuff – I added Jira automation.
Acknowledged
column, it sent an e-mail to the candidate and CC’d me. The e-mail was a friendly intro:We’re excited that you’re interested in our .NET Developer role! We wanted to acknowledge that we’ve received your application and let you know that we’ll be in touch about it as soon as we’re able. We ask for your patience as we give each application our attention.
If you have any questions about the organization, role, or process, reply all to this e-mail at any time and we’ll be happy to answer.
Thank you!
Interview Planning
column, an e-mail is sent with the Calendly link:Hello,
We’re excited that you’re interested in our .NET Developer role!
As a next step, please schedule a time for the interview at (Link)
We look forward to speaking with you!
Hello,
Thanks for your interest in the Mid-Senior .NET Developer position at SCT Software. Unfortunately, we will not be moving forward with your application but we appreciate your time and interest in SCT Software.
While things may not be a fit right now, we hope you’ll keep us in mind for future opportunities. We wish you the absolute best in your next career move.
(if public feedback was provided) The hiring manager provided the following feedback: “(the feedback)”
If you have any questions or follow-up, don’t hesitate to reply to this e-mail. Again, we thank you for your time.
Thank you for going through the SCT interview process and making the time to speak with us.
We know your time is valuable, and we’d appreciate it if you’d be willing to anonymously share some thoughts on your experience with us. This feedback will be seen directly by the hiring manager who conducted the interview.
(Link)
NOTE: If you are still in the interview process, this is not an indicator that the process is finished; we just don’t want to wait too long to collect feedback.
Thank you for considering!
So, my overall process went something like this:
Screening
column and look at their resumeInterview Scheduling
column. This sends the scheduling e-mail.Interviewing
column.Interview Debrief
This process was pretty effective for us, which is why I’m willing to write it up in the hopes that it benefits others. We had over 60 applicants for the two roles we had open. I was able to make an offer to two fantastic candidates that I think will really move our organization forward. I also had to reject several great candidates would have also been a really good fit (a best-case scenario for us as an org, even though that stinks).
But, more importantly: 100% of our anonymous interview feedback respondents rated their experience a 5 out of 5, and we received a ton of positive comments about the process. And, I felt like most of my time was spent where it mattered: on thinking about and connecting with candidates.
I hope this provides you with a place to start if you’re looking to improve your interview process!
Questions? Thoughts? I’d love to hear from you in the comments!
]]>