Writing Is a Developer Skill

Every programming language has a syntax, a set of rules for how tokens combine into valid statements. English does too — and the words developers write in tickets, comments, pull requests, and client emails follow the same principle: clear structure produces clear meaning. Treating everyday writing with the same care as code is not a soft skill; it is a practical way to reduce friction in collaboration, reviews, and debugging.

Developers already spend a substantial share of their day communicating. A 2021 survey of more than 4,000 developers by the Git client Tower found nearly half spend between 3 and 6 hours a day writing code. That leaves plenty of time for demoing features, documenting them, updating work tickets, and reviewing others' work. All of those tasks are exercises in technical writing, and they only get easier with attention to grammar, voice, and audience.

Bar chart showing actual programming time per day.

The payoff is concrete. A well-structured bug report gets fixed faster. A precise PR title saves reviewers time. A comment that explains why prevents future developers from "fixing" unidiomatic code and breaking it. Writing is how developers coordinate; improving it improves the codebase.

Venn diagram showing the overlap between technical writing and coding.

The Building Blocks of Clear Prose

English, like a programming language, has its own components. Words fall into categories that function like modular UI components — you assemble only the pieces you need to convey the intended meaning.

Color coded sentence showing the English syntax.

The essential parts of speech:

  • Nouns name people, places, concepts, and objects. Example: "CSS is one of the core languages of front-end development."
  • Verbs convey action. Example: "Marcia codes in the morning and answers emails in the afternoon."
  • Adjectives describe nouns. Example: "The Box Model is important to understanding CSS."
  • Prepositions relate a noun to other words in time, space, or direction. Example: "Did you commit your work to the repo?"
  • Adverbs specify how an action happens. Example: "The team worked diligently on the project."
  • Conjunctions connect clauses. Example: "CSS is for styling while HTML is for markup."
  • Transitions bridge sentences within a paragraph. Example: "First, clone the directory."
  • Pronouns replace repeated nouns. Example: "CSS is a stylesheet language. We use it to style websites."

Assembling sentences from these pieces works like composing an interface: use only what is needed for the job.

Voice and Tone Are Different Levers

Vocabulary, punctuation, and sentence structure set the "sound" of a message — a single exclamation point can flip its emotional register. Voice is the consistent character of your word choice, tied to context: a beginner tutorial may be casual and friendly, while API documentation is formal and direct. The same message can carry different voices:

  • Fun: "Expand your social network and stay updated on what's trending now."
  • Serious: "Find jobs on one of the largest social networking apps and online jobs market."

Tone is situational — how you respond in a given interaction, not a permanent trait. Reading messages aloud and experimenting with sentence structure is a practical way to avoid coming across as condescending or unprofessional.

Favor the Active Voice, But Not Always

English sentences contain an actor, a verb, and a target. In the active voice, the actor comes first: "CSS paints the background." In the passive voice, it comes last: "The background is painted by CSS."

The active voice is shorter, clearer, and requires less mental parsing — readers often convert passive sentences to active in their heads, which adds processing time. Tech writing generally prefers active constructions, with exceptions like research citations ("It has been suggested that…"). That said, switching between the two deliberately can improve sentence flow when used sparingly.

Proofreading Catches What Linters Miss

Grammar tools are the writer's equivalent of linters. Spelling mistakes and semantic errors in prose create the same noise as syntax errors in code. Grammarly is widely used for this, a one-stop tool for spotting problems before a document goes out. Built-in spell checkers and editor plugins offer a baseline; a dedicated checker adds another layer of review.

Code Comments Should Add What the Code Cannot

Programming languages provide comment syntax for a reason — but it is easy to misuse it. Vague comments like "this function adds the numbers" restate what any developer can read in the code. The goal is context the code does not carry.

red *= 1.2 // Multiply `red` by 1.2 and re-assign it

Useful comments provide deeper information:

red *= 1.2 // Apply a 'reddish' effect to the image

The distinction comes down to answering: "What kind of program am I building?" — and what a reader needs to understand the "why" behind the code.

Don't Just Restate What Code Does

Lazy comments merely translate code back into English, adding no value. If a comment can't tell a reader something they couldn't infer from reading the code itself, it should not exist.

const age = 32 // Initialize `age` to 32
filter: blur(32px); /* Create a blur effect with a 32px radius */

Redundant comments are noise. They force a reader to verify the comment matches the code instead of moving forward — a small but real tax on every future maintainer.

Keep Comments in Sync With Code

Out-of-date comments are a leading source of confusion in any sizable codebase. Consider a JavaScript function that sorts a list of strings alphabetically:

cities = sortWords(cities) // sort cities from A to Z

A developer discovers the function actually sorts from Z to A and reverse the output — while forgetting to update the original comment:

cities = sortWords(cities) // sort cities from A to Z
cities = reverse(cities)

Now a reader sees a comment claiming sortsWords() sorts "A to Z," followed by code that reverses the result. A comment and code that disagree waste everyone's time — and stale comments compound into technical debt.

Good Comments Explain the Unexpected

When code deliberately takes a non-obvious route — breaking a "standard" pattern — a comment explaining the rationale prevents reviewers from "correcting" it back into a broken state. Such comments document the decision and the reasoning behind it.

 function addSetEntry(set, value) {    
  /* Don't return `set.add` because it's not chainable in IE 11. */  
  set.add(value);
  return set;
}

Comments can also flag known limitations and future work, using TODO markers to keep focus on the current task while acknowledging what is incomplete.

// TODO: use a more efficient algorithm
linearSort(ids)

And when code is copy-pasted from an external source (say, StackOverflow), linking back to the origin is valuable. Solutions change, and a reference makes it possible to understand why the code was written that way down the road.

Screenshot of copying a link at StackOverflow.
// Adds handling for legacy browsers
// https://stackoverflow.com/a/XXXXXXX

Write Pull Requests for Your Reviewers

Pull requests (PRs) sit at the heart of code review, and poorly worded ones become bottlenecks. A good PR description summarizes what changes and why — not the how, which the code diff shows. Many large projects enforce this with a PR template.

## Proposed changes
Describe the big picture of your changes here to communicate to the maintainers why we should accept this pull request.

## Types of changes
What types of changes does your code introduce to Appium?
 - [ ] Bugfix (non-breaking change which fixes an issue)
 - [ ] New feature (non-breaking change which adds functionality)
 - ...

## Checklist
 - [ ] I have read the CONTRIBUTING doc
 - [ ] I have signed the CLA
 - [ ] Lint and unit tests pass locally with my changes

## Further comments
If this is a relatively large or complex change, kick off the discussion by explaining why you chose the solution you did and what alternatives you considered, etc…
  • Why is the PR being done?
  • Why is this the best approach?
  • Any known shortcomings, and ideas to address them later.
  • Related bug or ticket numbers, benchmark results, etc.

Make Titles Descriptive and Imperative

A title like "Fix build" or "Add patch" tells a reviewer nothing. A useful PR title is a one-line imperative summary that states what the PR does:

  • Support custom srcset attributes in NgOptimizedImage
  • Default image config to 75% image quality
  • Add explicit selectors for all built-in ControlValueAccessors

Keep PRs Small or Split Them Up

Huge PRs mean huge reviews — nobody wants to review hundreds or thousands of lines of code, especially if much of it is unrelated to the core change. Instead, communicate through project Issues, make a plan, and break large problems into smaller pieces that can each land in its own PR.

Write Bug Reports That Lead to Fixes

Users find bugs that testing misses, so issue reports are a critical loop in any project. A well-written report makes it easy for a developer to reproduce and fix the problem. Projects often provide templates to standardize the basics.

 <!-- Modified from angular-translate/angular-translate -->
 ### Subject of the issue
 Describe your issue here.

 ### Your environment
 * version of angular-translate
 * version of angular
 * which browser and its version

 ### Steps to reproduce
 Tell us how to reproduce this issue.

 ### Expected behavior
 Tell us what should happen.

 ### Actual behavior
 Tell us what happens instead.

Include what a developer needs to get unstuck quickly:

  • Screenshots or GIFs. Capture the issue visually. For a CLI, make sure text is readable. For a UI, capture the state and elements in question. For dynamic behavior, a screen-recorded GIF can demonstrate the problem far better than a paragraph.
  • Exact reproduction steps. A developer can only fix a bug they can see. Detail the precise sequence that triggers the issue.
Update: you can actually reproduce this error with objects:

 ```html
 <div *ngFor="let value of objs; let i = index">
   <input [ngModel]="objs[i].v" (ngModelChange)="setObj(i, $event)" />
 </div>
 ```

 ```js
 export class OneComponent {
   obj = {v: '0'};
   objs = [this.obj, this.obj, this.obj, this.obj];
 ​
  setObj(i: number, value: string) {
     this.objs[i] = {v: value};
  }
 }
 ```

 The bug is reproducible as long as the trackBy function returns the same value for any two entries in the array. So weird behavior can occur with any duplicate values.

Finally, if you have a hypothesis about the cause — perhaps it only happens on certain devices or after a specific event — suggest it. Even a quick look through the codebase can accelerate the fix and get you assigned to the resulting PR.

Communicating With Clients Without the Jargon

Programmers have a stereotype for poor client communication: too much jargon, too little listening, and a defensive posture when questions come. The mitigation is straightforward — ask better questions instead of making counter-claims:

  • "Are you OK with that even if it comes with an additional performance cost?"
  • "Does moving the component help us better accomplish our objective?"
  • "Great, who is responsible for maintaining that after launch?"
  • "Do you know offhand if the contrast between those two colors passes WCAG AA standards?"

Questions shift the dynamic from opposition to investigation, forcing the other side to reason through the tradeoffs themselves.

Winning freelance or contract work also depends on written communication. A pitch should state who you are, what you do, why you fit the job, and link relevant work. Post-sale, contracts filled with legalese are intimidating; inviting documents like the Contract Killer for design projects demonstrate a friendlier baseline for terms. Clients often hire developers they think they will enjoy working with over the most technically credentialed candidate.

Microcopy: Error Messages Should Help, Not Hurt

Microcopy — the brief UI messages users encounter at form fields, buttons, and especially errors — often gets deferred until launch pressure forces its creation. The result is messages like this:

Error: Unexpected input (Code 693)

On-screen errors are a user's last resort interactions, so they deserve care:

  • Avoid jargon. The word "server" is clear to every developer and opaque to most users. A good error message does not explain why something went wrong if the explanation demands technical terms — it tells users what to do next.
  • Never blame the user. "Your email/password is incorrect" reads as an accusation. Mailchimp's adaptation — "Sorry, that email-password combination isn't right. We can help you recover your account" — takes ownership of the friction.
  • Don't overwhelm the user. Humor can ease frustration, but used poorly it reads as condescension. Mailchimp's guidance holds: don't go out of your way to be funny. If you're unsure, keep a straight face.

Accessible Markup Is a Form of Clarity

Accessibility best practices intersect with technical writing in concrete ways, and they round out any content style guide — Microsoft and Mailchimp both include such sections. A few fundamentals stretch further than most others:

  • Use semantic HTML elements (<nav>, <header>, <article>) where they exist.
  • Follow a logical heading structure that communicates the document hierarchy.
  • Write meaningful alt text for images.
  • Pay attention to inline semantics and how elements combine to communicate meaning.

Readability improvements for content on the web — better contrast, clearer headings, and descriptive text — don't just help users with disabilities; they make content more understandable for everyone.

Writing Better Is Part of Being a Better Developer

Technical writing and development are not separate tracks. Clear prose in comments, PRs, issues, and client emails reduces the cost of every collaborative task. Sharpening sentence structure, adopting a consistent voice, and editing for audience are habits that reinforce themselves — and make developers more effective counterparts to both machines and people.