Developers follow different approaches to software development. Some stick to established philosophies, while others come up with their own.
My philosophical influences come from Lean Domain-Driven Design **(DDD)**, Test-Driven Development **(TDD)**, The Agile Software Development Life Cycle **(SDLC)**, Developer Operations **(DevOps)**, and more.
Here's my software development philosophy. What's yours?
## People First
I create software that benefits others and strives for a positive work environment. Your needs come first.
{{< socialpost src="images/people-first.png" alt="People First" >}}
## Invest Lightly
Technology constantly changes; I limit my keystrokes and produce thoughtful, low-maintenance software architectures.
{{< socialpost src="images/invest-lightly.png" alt="Invest Lightly" >}}
## Stay Liquid
I avoid technical debt like COVID. It's frighteningly common to witness multi-million-dollar software projects scrapped and rebuilt for millions again.
A mountain of technical debt is no laughing matter; it threatens the longevity of your business. I recommend paying your technical debt **now**. Rewriting software is often more expensive than paying technical debt.
{{< socialpost src="images/stay-liquid.png" alt="Invest Lightly" >}}
## Everything Changes
When building code, change will occur sooner than expected. Therefore, I craft flexible solutions that economically fulfill new business requirements.
I build modular code ready for replacement.
I use API Gateways, Service Facades, The Adapter Pattern (Anti-Corruption Layer), The Strategy Pattern, Proxies, and other patterns at the right time to prepare.
{{< socialpost src="images/everything-changes.png" alt="Everything Changes" >}}
## Simple Security
Simple security is often an oxymoron, but there are solutions.
I create layers to protect data for access rule clarity rather than using software configuration files.
I require clients to identify themselves before calling my services. [Legacy deprecation] is hard enough without introducing a game of whack-a-mole or resorting to [scream tests] during migration activities.
I often remind myself that the only secure computer is a dead computer, and you better be sure it's demolished, in the ocean, encased in cement, and buried.
{{< youtube "Q5v-bOUWppM" >}}
## Use the Right Tool
Languages are [programming tools] that help us craft solutions. I consider the appropriate tool for a job and am acutely aware of [The Law of Instrument].
In software development, many people use one tool and master it. Specialization is lucrative; some developers will profit from this approach. However, I prefer to follow the 80-20 rule. I learn several tools to unlock [full-stack development] proficiency.
I'm pragmatic, yet I apply principles contextually.
{{< socialpost src="images/be-pragmatic.png" alt="Be Pragmatic" >}}
## The Mythical Man-Month
Many believe adding more people will speed up a project. I don't blame them; it is a logical outcome. However, this is never true on a short timeline.
I'm acutely aware of [Brook's Law]. Adding new people to a team will initially slow it down.
I simplify onboarding activities to lower the impact of adding new team members.
{{< socialpost src="images/the-mythical-man-month.png" alt="Be Pragmatic" >}}
## Cut With The Grain
I build solutions with an eye for opportunity. If hosting software is cheap with the cloud, do it; otherwise, seek other less expensive solutions.
I skip dogma when allocating resources and address inefficient resource allocations.
{{< socialpost src="images/cut-with-the-grain.png" alt="Build With The Grain Of Opportunity" >}}
## Measure Then Commit
When building software, I focus on critical decisions, then fire [tracer bullets] to determine options.
I pass proposals by my team to eliminate blind spots.
I measure twice and then commit.
{{< socialpost src="images/quality-matters.png" alt="Quality Matters" >}}
## All The Logs In The Forest
I collect all log sources as I never know what they might reveal when debugging a problem.
While information is essential, too much information drives me crazy. I appropriately classify logs with {{< font style="color:#71F149;font-weight:bold;" text="DEBUG" >}}, {{< font style="color:#71F149;font-weight:bold;" text="INFO" >}}, {{< font style="color:#F8E86A;font-weight:bold;" text="WARN" >}}, {{< font style="color:#DD3F36;font-weight:bold;" text="ERROR" >}}, and {{< font style="color:#4300b6;font-weight:bold;" text="FATAL" >}}.
I implement general-purpose logging with aspect-oriented programming and control planes, keeping most logging concerns out of applications.
{{< socialpost src="images/all-the-logs-in-the-forest.png" alt="All The Logs In The Forest" >}}
## Start Fresh
When I dust off a software development tool, I approach it as a newbie. I search for a modern tool and remind myself that my tools may soon be obsolete.
I embrace a beginner's mind and avoid the sunk cost fallacy.
I use principles to guide me rather than knowledge of a tool.
{{< socialpost src="images/start-fresh.png" alt="Start Fresh" >}}
## Solutions Looking For a Problem
I ask myself a few simple questions before building anything.
* _Is this feature valuable?_
* _Does this feature solve a significant user or business problem?_
* _Does this feature increase or preserve revenue?_
If a feature isn't valuable, I postpone its development.
{{< socialpost src="images/a-solution-looking-for-a-problem.png" alt="A Solution Looking For A Problem" >}}
## Reframe The Problem
I can't eat a garden with one bite.
When I solve a complex problem, I break it into bite-sized bits. I work methodically to create discrete solutions to simple problems.
I reframe complex problems into economical and educational solutions. Depending on the impact of failure, I apply bronze, silver, or gold-plated solutions.
{{< socialpost src="images/reframe-the-problem.png" alt="Reframe The Problem" >}}
## Use Cases
It's vital to limit software use cases. A command-line utility's use cases are easy to restrict, while user interfaces are not. I limit use cases to reduce bugs.
A clear definition of use cases defines a contract between myself and users. I document a use case when people use my software in novel ways.
I create extendable features when developing general-purpose software.
{{< socialpost src="images/use-cases.png" alt="Use Cases" >}}
## Constraints Are Good
If it's flapping around, I nail it down. I identify and document constraints before writing any code. Defining constraints simplifies and improves decision-making.
I obsess over resource constraints and costs. Before deploying a software architecture, I review technical limitations and business rules to discover absolute blockers or quality impediments.
I regularly validate previously defined constraints. If something changes in my favor, I'll forge an optimized path.
{{< socialpost src="images/constraints-are-good.png" alt="Constraints Are Good" >}}
## Versioning Most Things
I version most things. I version software, hardware, and workflows.
I pin package versions and apply the principle: if it's not broken, don't fix it.
I update insecure packages proactively.
I like [comver] but use namespaces to avert potentially breaking changes.
e.g.
```python
# Services
from .v1.coffee import CoffeeMaker as CoffeeMakerV1
from .v2.coffee import CoffeeMaker as CoffeeMakerV2
from .v1.api import app as coffee_app_v1
from .v2.api import app as coffee_app_v2
__all__ = [
"CoffeeMakerV1",
"CoffeeMakerV2",
"coffee_app_v1",
"coffee_app_v2"
]
__version__ = "2.0.0" # COMPAT = 2, MINOR = 0, PATCH = 0
```
{{< socialpost src="images/version-most-things.png" alt="Version Most Things" >}}
## Name Things With Purpose
When naming variables, I name them in ways that make them easy to rename. I call things exactly and avoid overloading or overusing the same variable name.
{{< socialpost src="images/name-things-with-purpose.png" alt="Name Things With Purpose" >}}
## Fire Tracer Bullets
I use tracer bullets to punch a hole in the walls between myself and a solution. I use scattershot shotgun methods to prove use cases, theories, and the viability of a solution before investing time and money in building robust solutions. I pick a requirement far from the final solution and meet it head-on.
{{< socialpost src="images/fire-tracer-bullets.png" alt="Fire Tracer Bullets" >}}
## Loosely Held Inverted Ideas
I hold my ideas loosely, inverting them to validate them. I value processing ideas more than the ideas themselves.
To invalidate ideas, I invert my goals. I ask myself, _"What would I do if I wanted to fail?"_ This optimizes idea invalidation.
{{< socialpost src="images/loosely-held-inverted-ideas.png" alt="Loosely Held Inverted Ideas" >}}
<!--
https://tidyfirst.substack.com/p/thinkie-invert-the-goal?utm_source=post-email-title
https://www.youtube.com/watch?v=dSCBCk4xVa0
-->
## There Are No Big Problems
As Henry Ford once said, there are just a lot of minor problems. Breaking down what looks like big problems into manageable problems makes software developers look like wizards. ๐งโโ๏ธ
If I face a complex problem, I solve a minor problem and work from there.
I like to say, _"You can't eat a garden with one bite!"_
{{< socialpost src="images/there-are-no-big-problems.png" alt="No Big Problems" >}}
## Drive Human Value
I prioritize end-user needs and simplicity over complexity. I consider the human-centric value of features before building anything.
{{< socialpost src="images/drive-human-value.png" alt="Drive Human Value" >}}
## Single Responsibility
I isolate software components to reduce complexity and create user interfaces with a single responsibility. I divide tools logically between users and software developers and follow the SOLID principles when creating object-oriented software solutions. Failure to follow these principles causes many software problems.
{{< socialpost src="images/solid-principles.png" alt="SOLID Principles" >}}
## Take Responsibility
[Development Operations] (DevOps) has transformed software development, greatly benefiting modern practices.
DevOps requires software development teams to take full responsibility for their creations. The DevOps maturity model increases the quality of products and increases the speed of delivery to the market.
I guide team members towards continuously improving build pipelines, testing methodologies, and other DevOps best practices.
{{< socialpost src="images/devops-maturity-model.png" alt="DevOps Maturity Model" >}}
## There's Always A Design
It is paramount to design a maintainable, malleable, and easy-to-understand system. A design always exists. An unplanned design is terrible, but it is still a design. A poor design becomes a massive liability for a company and will slow a development team to a crawl.
I insist on a good design upfront. My primary goals include making a system sufficiently flexible, understandable, and affordable.
{{< socialpost src="images/the-big-ball-of-mud.png" alt="The Big Ball Of Mud" >}}
## Be Empathetic
Empathy for people is a cornerstone of a robust software development philosophy.
I work diligently to understand what people need. I ask why five times to understand the real problems while considering the big picture.
I write code anyone can understand by eliminating questions collected through solicited feedback.
When communicating with team members, I use tools like my [Emoji Search Tool] to ensure my messages are clear and engaging. Clear communication is key to building great software.
{{< socialpost src="images/be-empathetic.png" alt="Be Empathetic" >}}
## Step Slowly
When solving complex problems, I step slowly through code and make manageable changes. This helps me isolate errors and correct them individually.
I don't cut corners when a path is clear. Quality is more important than speed; speed emerges through grade.
> _Slow is smooth, smooth is fast_.
> โ Bob Martin
{{< socialpost src="images/step-slowly.png" alt="Step slowly" >}}
## Automate Almost Everything
I automate tasks religiously. I consider a different approach if it's expensive to automate a solution.
If automation causes fear, uncertainty, and doubt (FUD), I refuse to support or code it.
{{< socialpost src="images/automate-almost-everything.png" alt="Automate Almost Everything" >}}
## Test For Life
I like focusing on solving problems. Without robust integration tests, unit tests, and other tests, we spend time creating problems for ourselves.
I write tests because manually running an app after every change is tedious.
An automated test suite helps me sleep at night. Coding without testing increases the time spent working on bugs, investigating production issues, and troubleshooting broken builds. Testing prevents future pain; therefore, I test for life.
{{< socialpost src="images/test-for-life.png" alt="Test For Life" >}}
## Exceptions Are The Exception
I write code to avoid mistakes. Instead of throwing exceptions in the name of defensive programming, I change software designs to prevent thrown exceptions. After all, users depend on software to work and simplify their lives; let's keep it simple.
However, I bubble up exceptions with maximum traceability when required.
I implement messaging patterns, isolate control of resources, and identify other creative ways to avoid errors before throwing exceptions.
{{< socialpost src="images/exceptions-are-the-exception.png" alt="Exceptions Are The Exception" >}}
## Decouple Everything
I refactor tightly coupled code to reduce complexity and prepare it for change. When tight couplings exist for no good reason, I decouple them.
I summarily dismiss software libraries that aren't dependency injection-ready.
I ask myself five times why I'm coupling code before committing to tight coupling.
{{< socialpost src="images/decouple-everything.png" alt="Decouple Everything" >}}
## No Perfect Solutions
Picking the best solution, at the moment, with all the facts laid out, is the way to avoid [analysis paralysis].
I don't believe in the [Nirvana fallacy] and make the best decision possible at [The Last Responsible Moment], yet at the same time, I take big architectural choices very seriously.
Solutions can't simultaneously be fast, cheap, and good, yet I strive for the right balance based on functional requirements.
{{< socialpost src="images/cheap-fast-good.png" alt="Cheap, Fast, Good" >}}
## Conway's Law Is True
[Conway's Law] states that the organization's communication structure influences a system design.
> Any organization that designs a system (defined broadly) will produce a design whose structure is a copy
> of the organization's communication structure.
>
> โ Melvin E. Conway
**If communication flows are complex, so are systems.**
I inspect organizational information flow to understand its procedures. If the flow could be more efficient, I propose a better solution.
{{< socialpost src="images/conways-law-is-true.png" alt="Conway's Law Is True" >}}
## Open Source is Life
I use Open Source software whenever possible. I ensure the Open Source software I use is well maintained and make safe bets on a project's longevity. If it aligns with my development needs, I'll contribute to a project and enjoy the benefits that Open Source software development models provide to businesses and developers.
I promote [InnerSource] first culture that leads to Open Source contributions.
{{< socialpost src="images/open-source-is-life.png" alt="Open Source" >}}
## Can != Should
The software development world has many tools, methods, design patterns, and best practices. Frequently, choice overload leads software developers to believe one tool can rule them all. ๐
Choosing the wrong tools to solve a problem can lead to technical debt and wasted time. Before tackling a problem, I research the standard methods and choose the best tools.
{{< socialpost src="images/can-not-equal-to-should.png" alt="Can Not Equal To Should" >}}
## Confusion Is Painful
Software development is overly complicated as-is. I follow [the principle of least astonishment].
If I forge an unconventional path, I prepare [a steelman argument], keep it simple, and document why.
Code is language. My code speaks succinctly to people first, followed by a compiler.
I keep my variables consistent, methods clear, and configuration files clean, and I make sound choices to eliminate inconsistencies.
Inconsistency is an enemy of excellent software design.
{{< socialpost src="images/confusion-is-painful.png" alt="Confusion Is Painful" >}}
## Pair Programming FTW
I enjoy a productive pair programming session and love sharing my hard-earned wisdom. Programming in the modern age is a self-induced chaos test meant to push my ability to understand everything to the limit. When I help someone avoid the pain I've experienced, it brings me joy.
Another pair of eyes will make code easier to maintain and lower the total cost of ownership. When done right, Pair programming will level up your team while turning it into a high-performing powerhouse.
{{< socialpost src="images/pair-programming-ftw.png" alt="Pair Programming FTW" >}}
## Perfection Is A Myth
Perfect is the enemy of good enough. It's the phantom of the software delivery opera.
A software solution can act like a pain pill, but a packaged pill helps no one.
I ship software when it's good enough, then [continuously improve]({{< ref "1000-life-giving-potions-1-continuous-improvement" >}}) it.
{{< socialpost src="images/perfection-is-a-myth.png" alt="Perfection Is A Myth" >}}
## A Software Development Philosophy Evolves
My software development philosophy is evergreen. It changes after learning new things. This list contains a small fraction of my overall development philosophy. As always, a great magician only reveals some of their tricks.
{{< figure src="images/gandalf.png" alt="Gandalf" align="center" >}}
I refine my software development philosophy regularly in the spirit of [continuous improvement]({{< ref "1000-life-giving-potions-1-continuous-improvement" >}}).
## Develop your philosophy
Here are a few books to help you develop your software development philosophy.
* [The Pragmatic Programmer]
* [Clean Code]
* [Clean Architecture]
* [Solution Architect's Handbook]
* [The Elements of Programming Style]
## Related Content
* [List of software development philosophies - Wikipedia]
* [A Philosophy of Software Design | John Ousterhout | Talks at Google]
* **Product**
* [Seven Product Management Principles]
* [10 Customer Service Principles Every Employee Must Know]
* [Principles of Marketing]
* **Software**
* [SOLID - Wikipedia]
* [Summary of 'Clean code' by Robert C. Martin - gists ยท GitHub]
* [Principles of Security - Cornell Computer Science]
* [Seven basic principles of software engineering]
* [10 Crucial Software Development Principles]
* [Software Architecture Principles That Every Programmer Should Follow]
* [Software engineering principles to live by]
* [The 10 Principles of Observability]
* [Principles behind the Agile Manifesto]
* **Software Architecture**
* [Enterprise Architecture Principles]
* [Principles of Distributed Computing]
* [Follow these 10 fundamental microservices design principles]
* [Principles Of Microservices - Sam Newman]
* **Graphics Design**
* [Principles of Graphic Design]
* **Operations**
* [Principles of Decision Making - 6 Things You Need to Know]
* [7 Key Principles for a Successful DevOps Culture]
* [16 Essential Change Management Principles You Should Know About]
* **Soft Skills**
* [10 Essential Principles of Communication]
* [27 Key Principles of Leadership Communication]
[legacy deprecation]: /blog/2022/09/05/what-is-legacy-deprecation/
[scream tests]: https://www.urbandictionary.com/define.php?term=scream+test
[programming tools]: https://en.wikipedia.org/wiki/Programming_tool
[the law of instrument]: https://en.wikipedia.org/wiki/Law_of_the_instrument
[full-stack development]: /blog/2020/05/08/full-stack-developer-vs-specialized-software-developer
[brook's law]: https://en.wikipedia.org/wiki/Brooks%27s_law
[tracer bullets]: /blog/2020/12/19/a-pragmatic-programmer-book-review/
[development operations]: https://en.wikipedia.org/wiki/DevOps
[analysis paralysis]: https://en.wikipedia.org/wiki/Analysis_paralysis
[nirvana fallacy]: https://en.wikipedia.org/wiki/Nirvana_fallacy
[the last responsible moment]: https://blog.codinghorror.com/the-last-responsible-moment/
[conway's law]: https://en.wikipedia.org/wiki/Conway%27s_law
[the principle of least astonishment]: https://en.wikipedia.org/wiki/Principle_of_least_astonishment
[a steelman argument]: https://en.wikipedia.org/wiki/Straw_man#Steelmanning
[the pragmatic programmer]: https://www.amazon.com/Pragmatic-Programmer-Anniversary-Journey-Mastery/dp/B0833FBNHV/ref=sr_1_1
[clean code]: https://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882/ref=sr_1_2?dchild=1&keywords=clean+code&qid=1596815043&sr=8-2
[clean architecture]: https://www.amazon.com/Clean-Architecture-Craftsmans-Software-Structure/dp/0134494164/ref=sr_1_1?dchild=1&keywords=clean+architecture&qid=1610575399&sr=8-1
[solution architect's handbook]: https://www.amazon.com/Solutions-Architects-Handbook-Kick-start-architecture-ebook/dp/B0855XQZ44/ref=sr_1_1
[the elements of programming style]: https://www.amazon.com/Elements-Programming-Style-2nd/dp/0070342075/ref=sr_1_1
[list of software development philosophies - wikipedia]: https://en.wikipedia.org/wiki/List_of_software_development_philosophies
[a philosophy of software design | john ousterhout | talks at google]: https://youtu.be/bmSAYlu0NcY
[seven product management principles]: https://jefago.medium.com/seven-product-management-principles-55f4909cd9a2
[principles of marketing]: https://open.lib.umn.edu/principlesmarketing/
[solid - wikipedia]: https://en.wikipedia.org/wiki/SOLID
[summary of 'clean code' by robert c. martin - gists ยท github]: https://gist.github.com/jeffabailey/1e47567598e60878a07dc7e0b511c62e
[principles of security - cornell computer science]: https://www.cs.cornell.edu/courses/cs5430/2015sp/notes/principles.php
[seven basic principles of software engineering]: https://www.sciencedirect.com/science/article/abs/pii/0164121283900031
[10 crucial software development principles]: https://www.laneways.agency/software-development-principles/
[software architecture principles that every programmer should follow]: https://simpleprogrammer.com/software-architecture-principles/
[software engineering principles to live by]: https://www.callicoder.com/software-development-principles/
[the 10 principles of observability]: https://newrelic.com/blog/best-practices/principles-of-observability-modern-software-development
[principles behind the agile manifesto]: https://agilemanifesto.org/principles.html
[enterprise architecture principles]: https://www.luc.edu/its/aboutus/itsgovernance/enterprisearchitectureprinciples/
[principles of distributed computing]: https://disco.ethz.ch/courses/podc_allstars/#:~:text=All%20Chapters-,Principles%20of%20Distributed%20Computing,-PDF%201%3A1
[follow these 10 fundamental microservices design principles]: https://searchapparchitecture.techtarget.com/tip/Follow-these-10-fundamental-microservices-design-principles
[principles of microservices - sam newman]: https://samnewman.io/talks/principles-of-microservices/
[principles of graphic design]: https://www.designyup.com/principles-of-graphic-design/
[principles of decision making - 6 things you need to know]: https://coachingauthority.net/blog/2017/11/8/six-key-principles-of-decision-making
[7 key principles for a successful devops culture]: https://www.cmswire.com/information-management/7-key-principles-for-a-successful-devops-culture/
[16 essential change management principles you should know about]: https://status.net/articles/change-management-principles/
[10 essential principles of communication]: https://virtualspeech.com/blog/principles-of-communication
[27 key principles of leadership communication]: https://virtualspeech.com/blog/key-principles-of-leadership-communication
[comver]: https://gitlab.com/staltz/comver
[InnerSource]: https://en.wikipedia.org/wiki/Inner_source
[Emoji Search Tool]: /emoji-search