Meetings for Developers

As a developer advances in their career, they attend many, many meetings. "Too many meetings," most developers would say. Paul Graham talks about the "maker schedule" which is a model that rings true for me. A single meeting, especially a poorly run meeting, in the middle of a morning or afternoon, ruins half a day.

boring meeting

Thank you Ville Säävuori

Yet, meetings are valuable. A good meeting can help a team reach consensus, or pitch a new idea to management or create that elusive "synergy" between coworkers.

Part of the trouble for developers is that they are often not the meeting maker. Many people don't know how to run a good meeting.

Understanding Different Types of Meetings

Sometimes, meeting discontent comes from a lack of clarity about the purpose of the meeting. There are only a handful of constructive meeting types. Getting stuck in a meeting that doesn't match one of the following patterns is generally unpleasant and unproductive.

Meeting Types, Arranged by Purpose

  • Inform
  • This type of meeting is easy to set up and often easy to attend. These are just presentations to a group of people
  • Consult
  • Decision makers hold these meetings to gather input. What they do with the input is not part of the meeting, but these meetings offer the chance to speak up
  • Discuss
  • Discussion meetings bridge the gap between a consultation meeting and a collaboration meeting. There is back and forth, but a decision is not necessarily the product of the meeting. These aim to create something like a 'meeting of the minds'
  • Collaborate
  • This type of meeting is tough to run. The goal is to have the participants discuss and collectively decide something.

Be the Change You Want in the World

empty meeting room

Thank you Thoroughly Reviewed

Somewhere around mid-career, developers start hosting their own meetings. Make the world a better place by only hosting meetings that you would want to attend.

The key to hosting a good, productive meeting is to understand what the intent of the meeting is before meeting. The developer should decide what kind of meeting they are hosting before they host the meeting. Once the goal is realized, plan the meeting so that everything bends toward that goal.

Write an agenda - there is no such thing as a good meeting without an agenda. The act of writing the agenda, and assigning time estimates to each section of the meeting will make it clear if the meeting can be short or if the meeting will be too long.

Do not take notes at a meeting you host.

Do not take notes at a meeting you most.

Do not take notes at a meeting you host.

Get someone (not you) to take notes during the meeting. A designated note taker will leave you free to lead the meeting, present your material and guide discussion. Note takers can also provide feedback on your meeting performance afterwards. A record of what happened during the meeting is extremely useful to send to meeting participants.

Encouraging meeting makers to behave

If you are invited to a meeting without an agenda, ask the meeting organizer when they will send out the agenda. Be sure to ask far enough in advance for them to write the agenda.

If no one is taking notes for the meeting, offer to take notes. This will help ensure everyone ends up on the same page. You also have the option to frame the discussion.

If the meeting scheduled is lengthy, request to break it into smaller meetings, or that you get invited only to the part relevant to you. This doesn't always work - sometimes a person must develop an iron butt.


large meeting

Thank you Ricter Frank-Jurgen

Meetings are inescapable. As with all things that can't be changed, embrace them and make them your own to lessen your pain. Meetings don't have to suck - run your meetings so they don't suck, and gently encourage others to improve their meetings.

Remember, a meeting is a communication tool, just like email, Slack or JIRA. Use meetings well and lots of good can happen. Use them poorly, and suffer.

Tags: meetings personal-development business soft-skills leadership

Get great articles about development every month here ⬇️

Java 8 Functional Interface Cheatsheet

O'Reilly has a great in-depth article on the functional interface in Java 8. Here's a quick cheat sheet to keep track of the main types, what they do and common use cases.


A Predicate returns true or false. These are used for filters or replacing big chains of if/else logic.


A Function transforms data. These are used for maps, and other transformations. It is important to not mutate the original data that is passed in.


A Supplier takes no arguments and returns a value of a known type. Fetching, reading or creating resources to be used by other functions are common use cases. Suppliers get things started.


A Consumer accepts a single argument, but does not return any results. Consumers are where mutating functions, things with side-effects, should go. Consumers finish things.

Tags: cheatsheet how-to guide tutorial functional-programming java8

Get great articles about development every month here ⬇️

How to Write a Multiline Lambda in Java 8

For the most part, single line lambda functions are all you need.

This is a single line lambda:

Predicate<String> isBig = str -> str.length() > 10;

Sometimes one line is not enough to express the complexity of the lambda. How do you make a multiline lambda?

This is how:

//set up - elsewhere in the pseudo code:
public Sound getSound() throws MuteAnimalException {...}
Predicate<Sound> barks = sound -> Sound.valueOf("bark").equals(sound);

//payoff, a multiline lambda
Predicate<Animal> isDog = animal -> {
    try {
        return barks.test(animal.getSound());
    } catch (MuteAnimalException e){
        return false;
Tags: how-to tutorial guide functional-programming java8

Get great articles about development every month here ⬇️

How to Execute Python Files in Windows CMD

A question I get from new devs fairly frequently is "After installing Python, I can't run Python scripts with 'python'. What is going wrong?"

The most common thing going wrong is that the Python executable is not on the path.

Add Python Executable to the Path

Let's assume your Python executable is C:\Python37\python.exe. Open up cmd.exe and type setx path "%path$;c:\Python37;c:\Python37\Scripts". This will add both python.exe and the helper scripts included with Python (like pip and easy_install) to the path.

After modifying your path, open a new command prompt (this is important - Windows won't refresh the path in an open command prompt) and then try it out by navigating to your script directory and typing python You should see your script run!

Tags: basics tutorial how-to command prompt

Get great articles about development every month here ⬇️

Disable Atom.js Startup Welcome Guide

I've been test driving Atom.js and I like it pretty well. Something I don't like about it, is that the startup welcome guide keeps coming back. After several days of using it, I finally noticed how to turn it off.

In the left hand pane, at the bottom of the text there is a checkbox that disables the Welcome Guide. I think it's pretty hard to see, at least with the dark theme, but just uncheck it and you are good to go.

Tags: til ide development how-to guide tutorial programming

Get great articles about development every month here ⬇️

Managing By Whiteboard

Team lead is a different job than developer and requires a slightly different skillset.

While developers need to get along with others and coordinate their work, a team lead needs to coordinate lots of people's work - developers, stakeholders, users and their own. A team lead also needs to encourage and enable others to coordinate amongst themselves.

One simple technique is using the whiteboard as a tool to provoke discussion, make sure everyone is on the same page and to teach without appearing to teach.

The short explanation is that when a team member is explaining something complicated, asking a question or is making a decision as part of a group, stand up a start drawing what they say. Any mistakes will quickly be pointed out and everyone is working off the same information.

Whiteboarding to Learn

Credit jemimus @ Flickr

Often one of my teammates will have an idea that I don't understand. Or we'll want to do something neither of us understands.

To the whiteboard!

The process I typically follow is a teammate begins explaining something complex in a meeting. As soon as they summarize the concept that I don't understand, or suspect others don't understand, I'll politely ask if I can draw what I think they meant. I make it clear that I want to check my understanding. I then make my best attempt to draw what they just described.

Typically during drawing the team will have suggestions about naming things, or where to put lines. I listen to them all and draw what the collective will wants.

Whiteboarding to Teach

Teaching with a whiteboard

Credit juhansonin @ Flickr

Everyone has had to explain a concept to their team or a member of their team. You can try email, or talking, but for fast, quality results:

To the whiteboard!

This technique works best with advanced preparation, or at least a deep understanding of the topic. Starting with an overall block and arrow drawing to discuss and the drawing concepts as it becomes clear more explanation is needed is the basic outline of what to do.

A key technique, when teaching with the whiteboard, is to not monopolize drawing. The teacher should draw the initial concepts, but after that is done they should pass the marker to the student and encourage them to draw what they understand.

This has the added benefit that the teacher can see what they are not explaining well.

Whiteboarding to Communicate

Communicating with a whiteboard

Credit jm3 @ Flickr

Meetings are a vital part of a team lead's role. Meetings with stakeholders, meetings with supervisors, meetings with peers, meetings with team members, meetings with executives, even meetings with the public.


In many cases, Powerpoint is overkill or actively harmful.

To the whiteboard!

Whiteboards are light, adaptable and can be pre-prepared for your presentation. They also encourage audience participation, which enhances retention of information.

Whiteboards Everywhere

Use whiteboards as a tool to learn, to teach and to communicate. Don't just draw on them. Actively using a whiteboard and passing it around between participants ticks off two different learning style boxes - auditory and kinesthetic. The more learning styles you use, the more likely information is retained.

And remember - whiteboards can be transitory, but if you need to retain what you've drawn, take a picture.

Whiteboard everyday!

Tags: tips management programming best-practices skills team-lead leadership

Get great articles about development every month here ⬇️

Problem Behavior Correction Flowchart

A few months back I took the Coast Guard Senior Leadership Principles and Skills class, which combines The Leadership Challenge with some Coast Guard specifics. I enjoyed the class a great deal - the instructors (Charlie Coiro and Cdr Scott Jones) were outstanding.

One resource they provided is the technique the Coast Guard uses to address problem behavior with its staff. This was something of a revelation for me, because while I had some vague sense of how to encourage people having problems, I lacked a structured way of intervening.

The technique the Coast Guard uses provides a structure that I like, because it separates the problem behavior from the employee themself. The trainers say that problems are seldom intentional and usually result from a misunderstanding or shortcoming of ability.

This matches my experience - essentially everybody I work with is a dedicated professional working toward the same goal, and problems arise not because of willingness but out of confusion.

Behavior Correction Flowchart, click for bigger

This chart is supposed to guide how a leader responds to a problem with one of their charges. The leader is supposed to correct problem behaviors by stating the standard vs the behavior, listening and then diagnosing why there is problem behavior. Depending on the underlying reason for the problem behavior, different approaches are advised.

The intent of this methodology is to emphasize that most problem behaviors are the result of misunderstanding, circumstance or under training and not any hostile intention. It further emphasizes not applying the flow chart beyond the point where the problem behavior ceases. It separates the behavior from the employee.

The example they gave at the training is a chronically late employee.

Example Dialog

Supervisor: I see you came in at 9:30 today. Our doors open at 9, and we expect staff to be here by then.

Role Clarity Example

Employee: I thought we had core hours between 10:00 and 2:00 and that if I were here during them and work the full 8 hours my starting/stopping time didn't matter?

Supervisor: That's an option at some offices, but we haven't started that program here. The customer service component of our job requires that we're all here to answer the phone at 9 promptly.


Supervisor: You're right, my mistake

Ability Example

Employee: I know, but I have such a hard time getting up. I've tried alarms, light timers and I just don't know what to do.

Supervisor: -Brainstorm ways to wake up here-

Supervisor: Try some new methods of getting up on time. It's important to be here at 9, so let's check in again in a month and see how things are working out

Willingness Example

Employee: I get in when I get in. You know I bust my ass all the time.

Supervisor: -Stop when argument gets through to employee-

Supervisor: I know you work really hard, and I appreciate that, but part of your job is providing customer service. If our customers are here at 9 and you aren't here to help them, it puts them in a tough spot. Your co-workers have to cover for you, and it isn't fair to them to double up their duties just for your convenience. I get rated on this unit's customer service performance and I like to be able to say that we are not just meeting all our guidelines and helping as best we can, but exceeding them. If this continues, we'll have to put you on a performance improvement plan, and that's one foot out the door.

Emergent Problem Example

Employee: -in tears- My car keeps breaking down and I don't have any money to fix it because my daughter has cancer and the chemo takes every extra cent I have*

Tags: management leadership how-to tutorial flowchart resource

Get great articles about development every month here ⬇️

TIL CSS has a 'Calculate' Function

I don't like to specify layouts in pixels, because display sizes are all over the place. I dislike sniffing the display size and adjusting parameters through javascript, because I feel like the document should take care of all of that for me.

Something that has been bothering me is I find myself specifying heights, widths, margin, etc in em, while I typically specify border in px. Maybe this is bad practice, but it's what I've been doing.

The trouble is when trying to figure out how big something is, I can add up the em, and I can add up the pixels, but I didn't know how to combine them.

Today I learned that you can combine them with the calc() function. calc( 10em + 5px ); will spit out the number.

It's only supported in bleeding edge browsers, but it's a nice feature.

The big gotcha is that you must have a space surrounding the mathematical operator, or it won't get parsed.

Happy Calculating!

Tags: til css html web development web dev web

Get great articles about development every month here ⬇️

How to Move Mercurial Changesets to a New Branch

This is me when I realize I've been committing in the wrong branch all day:


Fortunately, there is a way to move changesets between branches, provided you haven't pushed your changes out to any other repositories. If you have pushed your changes out to the mothership repository, or your coworkers, the only way to pick up the pieces is to get all the users of the repo together and coordinate. That is beyond to scope of this article, and too hard for all but the smallest or dictatorial teams.

Problem Setup

Here at we make recipes and sell advertising. I've been hard at work writing up new recipes. Here's what I start with:

$ hg history
changeset:  1:b1c330d2ac79
user:       Gunnar Gissel <>
date:       Sat Feb 04 05:15:00 2017 -0900
summary:    Added quesadilla recipe

changeset:  0:6f5ef8f77a9f
user:       Gunnar Gissel <>
date:       Sat Jan 28 11:30:00 2017 -0900
summary:    Added taco recipe

I want to add drink recipes, but they aren't ready to show to our valuable users, so I want to add them in a development branch. Unfortunately, I've been out all night sampling drink recipes and I forget to create the new branch!


This is what I end up with:

$ hg history    
changeset:  3:398dfc004270
user:       Gunnar Gissel <>
date:       Sat Feb 04 05:15:00 2017 -0900
summary:    Added michela recipe

changeset:  2:852364587134
user:       Gunnar Gissel <>
date:       Sat Feb 04 05:15:00 2017 -0900
summary:    Added mojito recipe

changeset:  1:b1c330d2ac79
user:       Gunnar Gissel <>
date:       Sat Feb 04 05:15:00 2017 -0900
summary:    Added quesadilla recipe

changeset:  0:6f5ef8f77a9f
user:       Gunnar Gissel <>
date:       Sat Jan 28 11:30:00 2017 -0900
summary:    Added taco recipe

Fortunately, before I push all my code to the mothership repo, I notice I've been working in the wrong branch.

Move My Code to a Different Branch

The approach to fixing this problem is to create the missing branch, then create a patch from my new changesets, apply the patch to the new branch, then strip off the changesets from the incorrect branch.

Working in the same repository as above:

$ hg export -o patch.diff 3 2

I create a patch, which shows up as a file called patch.diff.

Create a branch off the newest changeset before I started adding new stuff:

$ hg update 1
$ hg branch drinks
$ hg commit

Patch the new branch I just made:

$ hg import patch.diff

This is dangerous, so make sure you are targeting the correct changeset. You can't easily undo this. You also need to have the strip extension enabled

Remove the changes off the original branch, so we can avoid mixing drink and food recipes:

$ hg strip 3

Phew, my repository is fixed. Now when look at the history I can see that I've got everything in the correct branch:

$ hg history -l 4
changeset:  4:8afca56c4940
branch:     drinks
tag:        tip
user:       Gunnar Gissel <>
date:       Sat Feb 04 05:15:00 2017 -0900
summary:    Added michela recipe

changeset:  3:357ff9545db
branch:     drinks
user:       Gunnar Gissel <>
date:       Sat Feb 04 05:15:00 2017 -0900
summary:    Added mojito recipe

changeset:  2:357ff9545db
branch:     drinks
user:       Gunnar Gissel <>
date:       Sat Feb 04 05:15:00 2017 -0900
summary:    drinks branch

changeset:  1:b1c330d2ac79
user:       Gunnar Gissel <>
date:       Sat Feb 04 05:15:00 2017 -0900
summary:    Added quesadilla recipe

Now I'm safe to push and I won't accidentally pollute our recipes with drink mixing recipes


Tags: mercurial hg dvcs version control vcs problem fix til

Get great articles about development every month here ⬇️

Organic Artisanal Small Batch vs Impersonal Factory

There are a couple approaches a shop can take to coding. There is the "Organic, artisanal, small batch" programming and "Impersonal Factory" programming.

My transition from a small batch artisanal shop to an impersonal factory is recent. The change is still fresh in my mind, while distant enough to have some perspective. This is what the change from an artisanal shop to impersonal factory style coding is like:

Small shops and new devs take the organic route. This is out of necessity. You have to move fast, get code out the door and put food on the table and money in your pocket.

Infrastructure is the other reason. Small shops and new devs often have little infrastructure. There may not be a build server and a staging server. There may only be a laptop and production.

Organic, artisanal, small batch programming gets things done. If nobody sat down and banged out the first version of something we'd still be using slipsticks and filing cabinets. Moreover, while teams are small and have low turnover, the cost to artisanal coding is minimal. If the author is there and can personally explain where the bodies are buried to a small group, style differences are barely a hiccup.

As shops grow, the merits of factory style programming becomes clear. I don't mean the factory pattern. You GOF people can see yourselves out :)

At some point, around 5 developers, the overhead from introducing new developers begins to drag on the team's productivity. Different project formats and project that need leads to be responsible for building applications

The Solution

Stand up some shared infrastructure and standards. Pairing shared infrastructure and standards together is absolutely necessary. Without standards, shared infrastructure turns into a shared nightmare. Without shared infrastructure, you're left with standardized coding wizards mumbling into their own private grimoires. No chance of telling whether or not the standards have been adopted.

The bare minimum for effective shared infrastructure is:

  • A shared code repository

  • A shared build server

  • A place to put artifacts created by builds

  • A staging server for testing deploys before they make it to production

What each of these elements mean is different depending on the stack your shop uses. I'm in the boring enterprise world, so the stack I'm going to talk about is Oracle, Java and Javascript.

Shared Code Repository

The specific tool your team uses doesn't matter, so long as it uses a tool and you are all storing code in the same place. According to Zero Turnaround's 2016 tech survey Git (and presumably Github) is the clear winner for version contro, followed by Subversion. My shop uses Mercurial - we made the switch from CVS before it was clear that Git would win and haven't felt a strong need to switch just for the sake of switching.

I won't go into why you should use source control in 2017(!), but I want to emphasize that having a shared place where every developer gets and puts code is extremely valuable.

If you aren't using source control, get with the program.

Shared Build Server

In 2017, developers should not be deploying artifacts to production that they create on their workstation. Partly this is because it can be difficult to recreate the state of a dev's workstation at a point in time well enough to recreate the artifact. Partly because manual processes like these have a poor bus factor and are difficult to pass on to new devs. Mostly because computer time is cheap, dev time is expensive, and automation is easy.

A build server provides a place to define the build and deploy process. A place to record past builds. A place to store artifacts. One of the great benefits of a shared build server is that any developer can run a build by pressing a button. It's a powerful advantage when a new hire can do a build on the first day they walk into the office.

Keeping deployed artifacts around another great benefit. If you need to roll back, you can get the exact thing that was deployed last. No manual copying out to a network file share, no wiki notes about where to find the backups. Everything in one place!

Another benefit to a shared build server is that they can act like a friendly interface to cron. Devs can easily script a repetitive task and then pass off the scheduling to Jenkins. Jenkins keeps track of the scripts success and can email devs when there are problems. It sounds small, but this is a huge productivity booster.

Artifact Repository

A build server can hold all your artifacts, up to a point.

Build servers are good at holding artifacts that get deployed to production servers. Build servers are not good at holding intermediate artifacts, like library jars.

Jenkins can move jars between builds, but keeping track of which jar belongs to a build is difficult. Like spaghetti code, spaghetti dependencies end in tears.

Developers need access to intermediate artifacts, but build servers do not give easy access. Sane Java development uses Maven, which can go get jars, but it needs to get them from a repository, not a build server.

Nexus is the artifact repository my shop uses. It's an artifact repository that works with Maven and is self-hostable. Thanks to Nexus, new projects can use existing libraries and tools without really trying.

Staging Server

A staging server is a server where code is deployed before it is deployed to the production server. The simplest way to use a staging server is as a simple smoke test - deploy your code, boot the server. If it boots, A-OK.

A staging server can also be a test server. Deploy code to the staging server, then run functional and user-acceptance tests. The staging environment is designed to be just like production.

If you aren't using a staging server, you're staging/testing in production, which is dangerous.

Reflections on the Change from Small Batch to Factory


The change from a small batch shop to a factory shop has been positive. The speed of code development increased and the rate of recurrent bugs decreased. The straightjacket of Maven, and the Nexus repository encourage modularity and code sharing, which allows us to build more complex systems quickly.

On the negative side, the speed of creating a new project with new infrastructure decreased. More infrastructure for testing is required, which naturally increases the burden of rolling out new projects.

Increased automation has offset the infrastructure burden, but more automation remains to be done.

I wouldn't go back.

Tags: programming culture method methodology mindset growth style

Get great articles about development every month here ⬇️

« Page 2 / 4 »