Drew's Software Learnings

By Drew LeSueur @drewlesueur repository

This site is for documenting the things I've learned as a computer programmer working on teams to create software for people.
Below is a list of concepts or technologies and my thoughts on them.
Much of this is my personal opinion and I value ideas that are different than these.


End-User Value

The best software is used by people and it helps them.
It works!
It's extremely satisfying to create something useful.
I enjoy working with the end-user to create software.
What's the essence of what you are making? Does your software do that well?


Teams

I love working with a team when creating software.
I love helping and learning from a team.
I have learned so much from my teammates.
I value diversity and inclusion.
I try to be sensitive and understanding to others.

Personality differences are totally overcomable with a unified cause or purpose.
—Ryan LeSueur

Problem Solving

Software development is all about problem solving.
A good software developer is a good problem solver.
I think skill in a specific language or technology is not as important as general problem-solving skills.
Languages and technologies can be learned if it's required to solve a problem.
I like when there is a simple solution to a problem and many times there is.


Simplicity

Simplicity is one of the most important considerations when writing code and designing systems.
Simple code and systems have fewer bugs, are more secure, are easier to change later.
Simple code is easy to read and understand.
Simple systems can fit in your head.
Not everything can be simple, and there are tradeoffs that require more complex code, but as much as reasonable, I prefer simple code.
If something is out of the norm or confusing, make sure to add clear comments to explain what's going on.
In general, I think of simple code and systems as having few levels of indirection, few nodes in a diagram, and generally linear.
What can I remove?

Less is better. And if it's not better, at least there's not as much of it.
—Unknown

Releasing

Web-based software has the benefit (and drawback) of being able to be changed frequently.
It allows software developers to release software in small increments.
Users can get incremental benefit along the way.
Without the drive to release, I've seen software projects spin too long in development mode.
What's the most important thing we can work on in order to release quickly?


Overhead

It's natural for me to love coding and releasing software,
and not spend as much time on other important things related to software.
Make time for other tasks like Cleanup, Testing, Documentation, and Monitoring
If these are neglected, you'll feel burdened by technical debt.


Cleanup

Code and systems develop organically over time.
Things are added, changed, removed.
After time, artifacts of change exist that are unintended, but natural.
Code will have left-over parts that aren't used.
Or systems will be too complex.
It's important to take time to analyze code and systems, and identify ways to clean and simplify them.
It's much easier to do this when there are tests, especially integration-style tests.


Testing

I have benefitted hugely from having automated tests that prevent bugs.
I generally prefer integration-style tests over unit tests, but I still see value in unit tests.
Integration-style tests allow me to test a system as a whole, and allow me to refactor without changing too many tests.
I generally prefer not to mock in tests, except for mocking third-party services if necessary.
I'd rather spin up a dependent test database or internal service instead of adding mocks.
I think it's easy for things to break at the seams and integration-style tests test the seams too.
I think integration-style tests can be made to run in all environments—development, test, and even in production.


Documentation

Tests help with documentation, but they don't always answer, "Why?"
Add documentation for users, other developers, or yourself later.
It takes time.


Monitoring

Software is more than just code, it's a living system.
It's important to monitor the health of the system.
Track things like latency, throughput, request lifecycles, error rates.


Bugs

It's frustrating but also somewhat reassuring that there will always be bugs.
Plan on bugs existing (because they will), and write code that is easy to debug (because you will have to).
Add tests and review code to limit bugs, but know that even with tests, code review, QA, bugs will exist.
I like to be empathetic to customers who report bugs—I feel the same frustration when I encounter bugs—
and I feel bad about all the bugs that aren't reported.
I've learned to not argue over what's a bug and what's not. If it doesn't work the way the user expects, I consider it a bug.
A quick bug checklist:


Abstraction

Code is read much more that it is written.
Code should be able to be removed and edited easily.
There is beauty and simplicity in abstraction in general,
but sometimes the cost of learning or remembering the abstraction is not worth the duplication that the abstraction removes.
I will sometimes duplicate code if I think it will make it clearer and easier to understand and change later.
When a heavy abstraction is beneficial, I like providing an "abstraction escape-hatch" so you can break out of the abstraction when needed.

duplication is far cheaper than the wrong abstraction
—Sandi Metz
A little copying is better than a little dependency.

Tradeoffs

I love the idea of tradeoffs. Two opposing decisions might both be right, as long as the deciders are happy with the tradeoffs involved.
Many decisions come down to personal preference. I don't believe that there is always one universal, correct way to solve a problem.
I've really enjoyed seeing "best practices" change over the years.
It reminds me that I should have confidence in the tradeoff decisions I have made,
but also respect others for their decisions.
If you are making software, and you have a simple solution that works, don't feel bad if it seems to go against current "best practices."


Automation

I like automating tasks.
When automating, it's important to allow for "manual overrides" so a human can do what a computer can't.


Pair Programming

I really enjoy pair programming.
I enjoy the knowledge transfer and focus that pair programming provides.
I think that there doesn't need to be a formal way of doing pair programming.
It should be natural.
Both people in the pair provide value even if one isn't touching the keyboard.


Learning

I love learning technologies and practices. I love experimenting with things.
Even if I don't need it yet, one day I might.
When I am with other developers, I think it's better to ask, "What can I learn?" instead of, "How do I prove how smart I am?"


Optimization

I enjoy thinking through and working on optimization problems.
Sometimes optimization means changing the way the system works rather than optimizing existing code.


Finding Code

It's frustrating to not be able to find code.
I value things like onclick= in html.
And 'greppable' identifiers in code.
If a specific feature spans multiple files in code,
I like to be able to grep for a single word or tag and find all places in code that relate to that feature.


Drive

Sometimes solving problems (like fixing bugs) takes a lot of effort and repetition.
Keep trying.


Focus

Focus is a form of simplicity and minimalism.
You can only do so much, what is the most important thing?


Flow

Creating software requires a good flow.


Negotiation

There is always an implicit request when software is asked for—it needs to be done quickly.
It is sometimes valuable to negotiate scope in order to satisfy the request for speed.


Tools

I value tools with a simple interface—like command-line-based tools.
Sometimes it's great to use existing tools to solve a problem,
and sometimes you need to write your own tools.
I also value "dumb" tools.
Many times a tool will try to be "smart" (like adding “smart quotes”, spell-check),
but it ends up not being what I want.


Git

Git is a very useful tool for developing software.
I like that I can be in the middle of something, but revert back to do hotfixes.
I like that it helps teams work together on the same codebase.


Redis

I love the simplicity of Redis.
The conceptual interface is extremely simple—commands with arguments that set state of data structures shared over a network
The simplicity exists in the underlying RESP protocol too.
Even the configuration file is simple—no JSON, no YAML, no TOML—just key value and # comments
Its simplicity is so refreshing.


Go

I really enjoy writing Go—especially for networked services.
It's clunkier to write than more dynamic languages, but it really pays off when going back to read Go code.
I like that Go intentionally leaves out features like inheritance and exceptions.
Some things are harder to abstract in Go, but this can lead to clearer code.
I also value the idea that Go doesn't meet all needs and that other languages can be more appropriate or preferred.


Bash/Shell

The more I use bash/shell, the more I like it.
I think of it as the glue of operating system features.
And I like glueing together text streams for quickly automating tasks.
I also like how easy it is to do multi-threaded scripts in shell if needed.


JavaScript

I gravitate toward simple uses of JavaScript like using <script src="app.js"></script> with hand-written JavaScript.
Lately I've used the Preact library for more complex user interfaces.
I like Preact because it's small and I can use it with plain html and JavaScript—I don't need a compile step.
I used to use JavaScript on the backend with Node.js, but I now use Go.


Development Environment

I use Vim as my text editor.
I usually use it with no plugins and a small .vimrc.
I enjoy programming with syntax highlighting turned off.
I usually program while ssh'd into a remote machine.
I like that I can be productive on any computer with an internet connection.
I only use one monitor.
I'd love to see more software creating tools done for mobile.
In high school I loved programming on my TI-83 Plus graphing calculator.


Links

Here are links to other thoughts on software (or things that can apply to software) that I value:
A Philosophy of Software Design
Ten Principles for Good Design
Zen of Python
Agile Maxims
Redis Manifesto
The Rise of ``Worse is Better''
Rob Pike's 5 Rules of Programming
Amazon's Leadership Principles