Pluralsight is different from most engineering organizations (I say without any real data). We are structured differently, from what makes up a team to how we deploy code. Let’s jump in and walk through a typical day in the life of a developer at Pluralsight.
For the sake of simplicity, I will go through the day according to developers in the same time zone as our headquarters: MT (Mountain Time).
Disclaimer: Some teams’ individual practices and day may vary a little. We value team autonomy a lot at Pluralsight, so teams have a lot of flexibility in how they choose to work.
For most developers, the day starts with stand up.
Three days a week, we have an engineering org stand up at 9:00 am. This is typically run by our CTO who gives updates that pertain to the whole (or majority) group. This includes company updates from our executive team, welcoming new team members, etc. Stand up (rare exception aside) ends by 9:15, oftentimes sooner.
Shortly after the engineering org stand up, each team has their own stand up - usually around 9:20 or 9:30.
### What is a team?
Now, it’s important to note here what constitutes a team. We work in cross-functional teams. A typical team consists of 4-6 developers, a product manager, and a UX designer. Additionally, a devops engineer is assigned to a team, but is usually not dedicated. (I could go into devops culture - what is ideal and where we stand, but that’s outside the scope of this post.)
During stand up, a team does a number of things:
* Give an update on the previous day’s work. These updates are meant to be kept at a fairly high level, diving into details where it makes sense. What was released? What is still in flight? What is blocking us?
* Make sure the Leankit kanban board reflects reality, particularly the status of cards.
* Make sure everyone is assigned and working on the right thing (this would usually be only one card for a mob).
* Each person should only be assigned to one thing. I don’t know about you, but I haven’t figured out how to code two things at once. Don’t get smart - reusable code doesn’t count. The only exception to the one-card rule is if something is blocked.
At the end of stand up, everyone should have a good sense of what the team is doing and what the shorter term goals are.
After stand up, it’s time to dive in!
We are big proponents of TDD and having tests to guide our development. They are also valuable when it comes to continuous integration (see below).
When it comes to writing production code, we have one explicit, unquestionable rule: two people must see and approve code before it goes to production. Most teams use pair programming, a couple use mobbing, and a few primarily use pull requests.
Let’s look more closely at mobbing and pairing.
In both mobbing and pairing, there is a driver and a navigator. The driver is the one at the keyboard, actively writing code. Somtimes a driver is referred to as a “smart keyboard,” meaning they shouldn’t be trying to dictate what the code should do, but rather writing the code that the navigator tells them to write. Rather than just being a “keyboard”, they are a “smart keyboard” because their navigator can give higher level instructions than you can give to an actual keyboard, such as, “Let’s make this test pass by writing the method called RollDie and always return a 1.” The navigator’s responsibility is to tell the driver what to do. Because they aren’t typing, they are better able to think about things at a higher level and help guide the pair/mob.
Each person and each group will find their own balance of how strictly you prefer to assign and use these roles. I explain what these roles mean with both mobbing and pairing below.
Imagine a spectrum of collaborative coding where individual coding is on one end. I believe mobbing would be on the other end. Mobbing is where the whole team is working on the same thing at the same time. Oftentimes for us, it is just our developers in the mob. But the product manager and other members of the team are always welcome to participate, and sometimes explicitly requested to join.
Our mobs each have two very large tvs behind one desk. The desk has one (sometimes more depending on team members’ style preferences) keyboard and one mouse.
Our teams use a mob timer that was written internally at Pluralsight (found here). The length of the timer is configurable; our teams usually rotate the driver every 8-10 minutes.
Sometimes a mob will have a set navigator. In this case, I’ve seen the navigator defined as the person about to become the driver, or the person who just finished driving. With a strict navigator, the rest of the mob is primarily silent until the navigator asks for group input. Other times, a mob will have a more loose approach to navigating where basically everyone except the driver is a navigator. Each approach has its merits and ideal contexts.
You can read more about mobbing in another post.
On the spectrum I mentioned in the mobbing section, pairing would be in the middle. Pairing is where two developers work on the same code at the same time.
There is a lot of variation in how teams pair.
Most teams have 4 monitors per pairing station: 2 per person (great math!), each pair of monitors mirroring the other. With this set up, each person has their own keyboard, mouse, and desk. Some teams pair across the table, meaning there are two desks back-to-back with one person on either side. Other teams pair side-by-side, meaning the two desks and each member of pair are sitting next to the other.
In my experience, pairing tends to be less formal than mobbing. That said, it can be implemented however you choose. I’ve been part of a pair where we naturally and fluidly switch between the roles without ever creating any explicit rules. I’ve also been part of a pair where we strcitly have a driver and navigator role and switch on a set cadence, whether it’s time-based or ping-pong pairing.
What language do we use? Well, this is another thing that varies across teams. An aspect of autonomy we value is allowing teams to choose which tools they use, within reason. Each team is able to choose from a list of preferred or acceptable languages, tools, and platforms according to their preference and the task at hand. When it comes to development-only concerns such as an IDE, the team has complete autonomy. You can read more about team autonomy and responsibility here.
Now that we’ve written some code, let’s get a feature to production!
A word about continuous integration (CI)
After code has been written and pushed to source control (we use github), we have an automated build that runs (we use TeamCity). Each code base has a suite of unit and integration tests that are run. When those all pass, a build artifact is created and in most cases automatically deployed to stage. Then we have acceptance and/or UI tests that run against that build that is now on stage.
Once the build is green (all tests passing) and on stage, we do a bit of manual testing - mostly a sanity check. If everything looks good, it’s time to ship it!
Not every release is created equal, meaning some may require some DB changes first and each team’s setup can be unique. But most of the time we simply push a button to deploy to prod. It’s as simple as authenticating on whatever tool/process your team uses, and deploying the correct build. There’s no middle-man in this process - no build engineer, no manager approval required. With the push of a button we’ve deployed our code we wrote this morning (or a half hour ago) to production!
I don’t want to go into too much detail here, but I just want to mention: Each team is responsible for their own logging, monitoring, and alerting. We have system level tools in place, but the configuration of those tools falls to each individual team. It is up to them to make sure their part of the system is available and performant.
Lather, rinse, repeat
That’s really it for the day-to-day work of a developer at Pluralsight. On occasion there are one-off meetings, but who wants to read (or write) about those? The other variation from the stuff discussed above is recurring meetings. I’ll cover a couple below.
Most teams have a weekly retrospective, but some opt for bi-monthly or continuous retrospectives. A retrospective is deserving of its own post, but the 10,000 foot view is that it provides a chance for the team to look back on the past and talk about what went well and what didn’t. It’s an opportunity to identify ways to improve or grease the wheels. It’s not a blame game, rather a time to retrospect as a team.
Retrospectives can also be a great tool in other scenarios. For example, a team might hold one after the end of a specific project (which may span a longer amount of time like a month or two and even across multiple teams), or possibly focused on a particular topic such as delivery or team member feedback.
Some teams have a weekly planning meeting. Unlike a typical planning meeting, there is no formal sizing or estimating here. It’s merely a time for the entire team to sync up. Here are some goals/exit criteria for a planning meeting:
* Make sure everyone is on the same page about what the team’s priorities are.
* Discuss what is coming down the pipeline.
* Make sure cards on the kanban board are ordered by priority - highest priority at the top.
* Make sure developers understand everything they need to in order to be able to pick up the card and start working on it.
* Talk about things that have come up since last planning meeting and decide on their priority.
* Bugs: if bugs have come up that weren’t urgent enough to fix right away, planning meeting is a great time to discuss them. Generally, we decide to fix them very soon or not at all. If a bug is worth fixing, fix it now.
* We don’t really do backlogs here. Certainly not at the level where we have to groom them. If something has come up that another team needs from us, we discuss it in planning. It usually gets prioritized to be worked on in the next week or so.
The way we work at Pluralsight has largely been shaped and decided by our developers. We value shipping quality software to our customers, and align our processes and practices around that. Rather than optimizing for individuals, we optimize for the system. For more insight into how we work and the ideas behind them, check out other posts on the blog and watch for new ones!