Table of Contents
Organizing various blog entries by common themes
![]()
Introduction
I began this blog in earnest as a retirement project in the fall of 2023. The blog’s home page lists the entries chronologically from newest to oldest. Blog entries are often part of a series focused upon a theme. The first blog entry of a series is usually an introduction to the series and acts as a landing page to the other blogs in the series. There are crossover reference links to other blog entries as well.
Beyond chronology and series structure, there is a deeper organizing principle at work. Just as a library organizes books to make this accessible, as seen in the Trinity College Library above, this meta-blog entry organizes the themes of my blog entries making them more accessible.
This page is a curated collection of essays, examples, and experiments on software design, testing, and architecture, written from the perspective of a retired software engineer with decades of industry experience.
The focus here is on durable ideas: design patterns, abstractions, tradeoffs, and mental models that hold up across languages, frameworks, and architectural fashions. Many entries are intentionally long and exploratory. They are meant to be read slowly, revisited, and occasionally argued with.
This is not a framework tutorial site, and it is not a stream of short-form commentary. Most articles aim to answer questions like Why does this pattern exist?, What problem is it actually solving?, and Where do people get confused when applying it in real systems?
Think of this site less as a blog and more as a living technical notebook—one that continues to evolve as ideas are tested, refined, and sometimes reconsidered.
NOTE: This page will be updated as new blog entries are added to existing themes and new themes are introduced.
How to Use This Page
This page serves as an index and entry point into the material on the site. You do not need to read it from top to bottom.
Ways to Navigate
- Browse by topic if you are exploring or refreshing a concept
- Jump directly to an article if you arrived here from search
- Return to specific entries as reference material while working
Many articles are designed to support non-linear reading. If a post includes a table of contents or reader’s guide, it is intentional—use it.
What to Expect from Articles
- Explanations favor conceptual clarity over brevity
- Code examples are illustrative, not copy-paste recipes
- Some posts revisit the same idea from different angles
This repetition is deliberate. Important ideas tend to reappear as systems grow more complex.
Interactive Notebooks
Some articles link to Interactive AI Notebooks that expand on the written material. These are optional, but they often explore edge cases, alternate implementations, or “what if?” scenarios that don’t fit cleanly into a static article.
A Note on Depth
Not every section will be relevant to every reader. Skipping ahead, skimming, or reading selectively is expected. The goal is not to finish pages, but to build understanding over time.
- New readers: Start with Design Pattern Foundations or Abstraction.
- Practicing engineers: Jump directly to Essential Design Patterns, Automated Testing, or Hexagonal Architecture.
- Advanced readers: Explore Composable Design Patterns, Interpreter, or Working Effectively with Legacy Code.
- Readers looking for wisdom, inspiration and a few laughs: Try Bumper Sticker Computer Science and Software Engineering and Cautionary Tales and Principle of Least Astonishment
Table of Contents
- Core Concepts
- Design Patterns and Architecture
- Quality and Testing
- AI and Emerging Topics
- Experience and Reflection
- Miscellaneous
- Reference
Core Concepts
Software Engineering
A degree in Computer Science has been the initial exposure to software for many developers; however, Computer Science is not the same as Software Engineering.
SE Miscellaneous
- Bumper Sticker Computer Science and Software Engineering - This is my favorite entry.
- My Design Process - Everyone has their own way to approach design problems. This entry describes mine.
Abstraction
Abstraction is a core software engineering concept, and it’s more challenging to describe abstraction concretely than I originally thought.
- What is Abstraction? - An introduction to Abstraction
- Cohesion and Coupling - My first attempt to describe Cohesion and Coupling
- Cohesion and Coupling - Take 2 - My second attempt to describe Cohesion and Coupling
- What is Cohesive Construction? - How to configure cohesive abstractions consistently
- Getting the Right Abstraction is Hard - How I adjusted the abstraction in a design I inherited
See: Abstraction Interactive Interactive AI Notebook
Design Pattern Foundations
Design Patterns changed how I approach software. This section argues that every Software Engineer would benefit from having some degree of competence and comfort with design patterns.
Design Patterns are not technically challenging, but they do require a slight paradigm shift in thinking. These blog entries lay some foundations toward that shift in thinking.
- Are you a cook or a chef? - Are you following the recipe or creating something new?
- Rules of the Game - Do you know more than just the rules of the game? Do you know strategy and tactics to win the game?
- Problem Solvers - We solve problems, usually in the form of code
- Design Patterns are Everywhere - Design Patterns are not limited to Software Engineering. They are ubiquitous in most domains.
- Toolbox - Design Patterns are tools in your toolbox. Like most tools, we have mastered them when we not only know when to use them, but when not to use them.
- Parts is Parts - Most Object-Oriented Design Patterns are different combinations of the same set of OO constructs
- Design Pattern Principles - There are only two Design Pattern Principles. Understanding them will help in understanding the underlying structures that reappear in Design Patterns.
See: Design Pattern Foundations Interactive AI Notebook
Design Patterns and Architecture
Patterns are grouped in cohesive groups, often as a series where the next pattern builds upon the previous one. They are not grouped by a rigid taxonomy. Some patterns naturally belong in more than one category, since the cohesive groups don’t have strict boundaries, and there’s some degree of overlap.
Essential Design Patterns
The Seven Essential Design Patterns are the design patterns that will be used repeatedly in designs. They are the hammer and screwdriver of a software developers design pattern toolbox.
- Command - Objectify a function so that it becomes a first-class citizen in an Object-Oriented paradigm
- Strategy - A variant of Command with multiple implementations for an interface
- Template Method - Similar to Strategy, except the interface is replaced with an abstract base class, which houses the implementation for common behavior that applies in all cases.
- Adapter - A translation helper class that allows other classes to interact indirectly when they cannot interact directly due to different protocols and/or method signatures.
- Façade - Similar to Adapter in concept, but rather than performing basic translation, it shields the client application of its dependency upon a particularly nasty or complex class or set of classes
- Factory - Allows an application to acquire an object reference without knowing class type and without having to call a
new()constructor directly - Dependency Injection - Removes all dependency resolution from an application by transferring that responsibility to another entity whose sole responsibility is to configure and resolve object references for the application
See: Essential Design Patterns Interactive AI Notebook
Creational Design Patterns
The Creational Design Patterns define techniques to acquire objects while encapsulating the object’s concrete class type. They also provide object management techniques when a new object is not always needed.
- Factory – Allows an application to acquire an object reference without knowing class type and without having to call a
new()constructor directly - Abstract Factory – Applications often have multiple dependencies often resolved via a Factory. It’s critical for these factory dependencies to be consistent within their environment. For example, resolving dependencies with some factories producing production references while other factories produce test references could lead to disaster. Abstract Factory helps ensure that a set of factories return consistent dependency references.
- Builder – Creates, assembles and returns a set of cohesive objects based upon a plan much like a blueprint. Builder is often used with Composable Design Patterns to create and assemble the objects in the composition. The Builder pattern supports abstraction as well since different concrete Builders can resolve the abstraction within the same design allowing them to create and assemble different concrete instances of the same structure.
- Singleton – Ensures that only one object is created for a class type
- Flyweight (Also Known As Multiton) – Ensures that only one instance of an object will be created for a given set of intrinsic attributes
- Object Pool – Objects are created at start up and lent to the caller when requested, much like borrowing books from a public library
- Prototype – Acquires a new object instance from an existing object instance
- Dependency Injection – Removes all dependency resolution from an application by transferring that responsibility to another entity whose sole responsibility is to configure and resolve object references for the application
See: Creational Design Patterns Interactive AI Notebook
Composable Design Patterns
The Composable Design Patterns focus upon behavior emerging from the composition of objects and their interaction in a structured formation rather than implemented within an individual class.
- Proxy - Place administrative wrapper objects around objects often to help manage their complexity or resources
- Decorator - Layer additional behaviors upon a core feature via a list of linked wrapper objects
- Chain of Responsibility - Delegate a request through a linked chain of handlers until one of the handlers can complete the request
- Composite - Configure behavior emerging from a group of snippet behavior objects organized in a tree structure
- Specification – Allow a Client to select or filter objects with specific attribute property values as specified by the Client
- Interpreter – Given a language, define a representation for its grammar along with an interpreter that uses the representation to interpret sentences in the language. This pattern will require several blog entries.
See: Composable Design Patterns Interactive AI Notebook
Interpreter Design Pattern
The Interpreter required its own series. It moves from language theory to production through a single evolving example.
Interpreter allows software developers to design and implement their own Domain-Specific Languages (DSLs). Interpreter is not just the pinnacle of Composable Design Patterns, but it shares the top spot of all design patterns along with the Visitor Design Pattern.
Interpreter is not a difficult pattern to design or implement, but it’s a difficult pattern to comprehend. Interpreter required multiple blog entries to do it justice.
- Interpreter - Introduction and overview
- Domain-Specific Languages - Domain-Specific Languages solve domain-specific problems succinctly
- Programming Language Grammars - Grammars define the structure rules for natural and programming languages, including Domain-Specific Languages
- Grammars to Design - The Interpreter Design emerges from the Grammar
- Design to Implementation - Implementing the Interpreter Design Pattern based upon a Design.
- Scanners and Parsers, Theory and Practice - The basics of Scanner and Parser theory and practice
- Scanners and Parsers, Implementation: Rational Expression Implementation Example Completed - Implementing the Scanner and Parser for the Rational Expression Evaluator DSL Use Case
- Interpreter Design Pattern – Production Example: My Experience Using Interpreter on a Work Project - My Experience Using Interpreter on a Work Project
See: Interpreter Design Pattern Interactive AI Notebook
Hexagonal Architecture
The Hexagonal Architecture (AKA Ports and Adapters) is a design that all software developers should know. It showcases how different Essential Design Patterns can work as a cohesive design.
- Hexagonal Architecture Introduction - Introduces Hexagonal Architecture
- Hexagonal Architecture - Structure - This describes the structure of the Hexagonal Architecture design, and how it’s really a pattern of design patterns
- Hexagonal Architecture - Why it works - This describes why I feel that the Hexagonal Architecture design works so well. It’s based upon dependency and knowledge management. Dependency and knowledge management applies to all OO based designs, and not just within the context of Hexagonal Architecture.
- Hexagonal Architecture - How it compares and contrasts with Clean Architecture - The two designs are mostly the same, but there are some differences worth pointing out
- Hexagonal Architecture - Adapter Flexibility - We have quite a bit of flexibility with this design in the Adapter layer
See: Hexagonal Architecture Interactive AI Notebook
Quality and Testing
Automated Testing
I didn’t appreciate automated testing until late in my career. My automated testing series begins with my Conversion from automated testing non-believer to almost a zealot. The series grew larger than I originally imagined. I ended up writing a short book on the topic.
Here is the complete Automated Test series:
- The Conversion of a Unit Test Denier or … How I Learned to Stop Worrying and Love Unit Testing - This is a summary of my journey from avoidance to introduction to acceptance and advocate of automated testing
- Attributes of Effective Unit Tests - Unit Test properties that make them more useful than not
- Basic Elements of Automated Unit Tests - Elevating automated tests to first-class citizen status
- Test Doubles - Emulate dependencies without depending upon dependencies
- Suril, the Semaphore and Me - When the theory became practice for me
- Test-Driven Development - Writing Tests Before the Implementation - I know it sounds completely backwards, but please give it some consideration
- Yuri, the Programming Assignment and Me - My evening introducing Test-Driven Development to a young Computer Science student
- Be On Your Best Behavior - Test-Driven Development: How to create tests. Behavior-Driven Development: What tests to create.
- What is Behavior in Behavior-Driven Development - More details about the nature of behavior
- Testing Benefits - Spoiler Alert – It’s not really about testing the code
- Testing Concerns - Test concerns may be a result of previous bad test experiences; there are ways to accommodate them
- A House Divided Against Itself Will Not Stand - Resolving the conflict between My Design Process and Test-Driven Development blog entries
- Working Effectively with Legacy Code - How to leverage automated test techniques when working with Legacy Code
- How do you know if your test code is really testing your code? - How Mutation Testing can help test your test suite
- Approval Testing - A Test Strategy for those who are reluctant to try Test-Driven Development - A testing strategy that’s in the intersection of Unit Testing and Characterization Testing
- Mastering Time in Software Testing - Strategies for Temporal Behavior Verification - Become a Time Lord and control time in your tests
- Humble Objects - Designing Code You Don’t Hate Testing - A pattern to help test code that’s difficult to test
- Test Layers: From Unit to System - Building Confidence with the Right Tests at the Right Level - There’s more to testing than Unit Tests
- Consumer-Driven Contract Testing - Giving the consumer exactly what they asked for - When the Consumer supplies the Test Specifications to its Provider
See: Automated Testing Interactive AI Notebook
AI and Emerging Topics
Large Language Models and Generative AI
AI has become a major topic since late 2022 with the introduction of ChatGPT among others. I learn a bit more about how to use them almost daily.
See: Large Language Models and Generative Interactive AI Notebook
LLM/GenAI Introduction
LLM/GenAI Introduction - Like it or not, the AI Genie is out of the bottle
Prompt Engineering Patterns
Prompt Engineering Patterns are the key to getting the best results from Generative AI. These blogs present a few patterns I learned via online courses.
Interactive AI Notebooks (Google NotebookLM)
I have created interactive AI notebooks for several of my blog series. Each provides an AI interactive experience with some of my central themes. There are several artifacts including an AI generated two-host podcast formatted summary. You can also interact with the generated AI hosts to some degree.
NOTE: A Google account may be required to access Google NotebookLM.
Interactive AI Notebooks:
- Abstraction
- Design Pattern Foundations
- Creational Design Patterns
- Essential Design Patterns
- Composable Design Patterns
- Interpreter Design Pattern
- Hexagonal Architecture
- Automated Testing
- Large Language Models and Generative AI
Experience and Reflection
True Stories
The following blog entries feature a few True Stories, or maybe they should be called: True Confessions. I try to include personal experiences where I can in my blog entries. Sometimes story is the entire blog entry. Sometimes it’s just a part of the blog entry.
I keep my previous employers and others anonymous. If I do mention someone by name, I only use their first name, and I get their permission, or I use a pseudonym.
- What is UML and why you may want to care - When I realized, in an Aha! moment, that OMT, the predecessor of UML, is more than just a design tool. It’s a way to model the problem that based upon the domain elements and their relationships
- It’s Your Move - When I realized that software engineering was more than just knowing the rules of a programming language
- Getting the Right Abstraction is Hard - Where I had one of my first experiences of working with someone else’s code and realizing that it could be designed better
- Façade Design Pattern - Where I encapsulated a really nasty API away from the rest of my codebase
- Dependency Injection - Where tightly coupled code limited my team’s testing abilities
- Hexagonal Architecture – Adapter Flexibility - Where adopting Hexagonal Architecture and an Adapter Dispatcher provided the flexibility we needed to solve a rather challenging design problem
- Chain of Responsibility Design Pattern - Where a Chain of Responsibility design solved a problem of different configurations of Address Books.
- Interpreter Design Pattern - Domain-Specific Languages (DSLs) - Where I briefly summarize a few DSL experiences in my career.
- Interpreter Design Pattern - Parser and Scanner Theory and Practice - Where I describe my experience of taking Automata Theory and Compiler Design and Implementation in the same semester at college. I was exposed to the same problem, first as theory and then as practice in two separate courses, literally on the same day.
- Interpreter Design Pattern – Production Example - Where I created a Domain-Specific Language, even when that was not my original intent
- My Design Process - How I evolve my designs
- The Conversion of a Unit Test Denier … or How I Learned to Stop Worrying and Love Unit Testing
- Suril, the Semaphore and Me - How I learned the true meaning of Software Under Test
- Yuri, the Programming Assignment and Me - When I indoctrinated a young mind with TDD
- Losing Your Job Stinks - Where I describe my unemployment experience during a down market after the dot-com bubble burst in the early 2000s
- Testing Concerns - Where I list the lessons I learned when I was on the QA team
- Abstraction - Where I describe the conversation, I had with a mentee at my college alma mater, which inspired this blog
- What Is Cohesive Abstraction? - Where I describe my experience with Safety Critial Code
- A House Divided Against Itself Will Not Stand - Where I resolve the conflict between My Design Process and Test-Driven Development blog entries
- Prepping for a demo - Where I describe how I stumbled onto Mutation Testing by accident.
- Heartbeat or Heart Attack? - Where I describe a bug that took 42 days of continuous execution before it manifested itself in Mastering Time in Software Testing - Strategies for Temporal Behavior Verification.
Cautionary Tales and Principle of Least Astonishment
Cautionary Tales may help others avoid some poor choices I encountered, some of my own making. This section will also contain a few examples of violations of the Principle of Least Astonishment (POLA):
- What Is Cohesive Abstraction? - Where I describe a A Cautionary Tale, which darn near cost me my job
- Working Effectively with Legacy Code - Where an obvious error lurked in the code for months due to the lack of testing in Hey. This doesn’t look right.
- Consumer-Driven Contract Testing - Where I describe in Why Bother? that an external provider changed their contract, and we didn’t realize it until our customers started to complain.
- Singleton Design Pattern - Where I describe a Singleton in You Did What? Why? that allowed anyone with a reference to it to change its intrinsic state.
Miscellaneous
This is for blog entries that were one-offs, and weren’t part of series:
- Job Loss - Software Engineering has been a great career for me, but it wasn’t without a few bumps in the road. I wrote this blog when others I knew in the industry were running into the same bumpy road in their careers.
Reference
Complete Code Demos
Many blogs have complete code examples to demo the principles. They are in Java and collected into one file, even if the file contains many interfaces and classes. All examples are self contained within Java. There are not external dependencies to import.
Copy the demo into a Java environment and run it. If you don’t have Java, try this Online Java Environment.
Play with the implementation. Add tests. Refactor the demo. Copy the demo into Generative AI platform for analysis and comments.
NOTE: While developing this section, it became obvious to me that I had not provided as many complete code demos as I should have. I will slowly add them retroactively and provide references here when provided. I may also reorganize the list once it gets more content.
- Command Design Pattern, which includes an example using Runnable and ExecutorService.
- Strategy Design Pattern, even if ChatGPT thinks it’s a better example for Command.
- Template Method Design Pattern, which includes the Hot Drink Template Method to create Coffee, Tea and Hot Cocoa.
- Adapter Design Pattern, which includes code examples for both Object Adapter and Class Adapter variants.
- Factory Design Pattern, which includes a simple static class Factory.
- Dependency Injection Design Pattern, which expands upon the Factory example by injecting the Factory acquired interface reference into the application, which allows us to easily test the application.
- My Design Process, which includes a Circuit Design implementation for the design featured in the blog.
- Test Doubles, which includes several hand-crafted Test Doubles.
- I featured a Rational Expression Evaluator as a use case example in the Interpreter Design Pattern series. I developed the evaluator across several Interpreter blogs:
- Rational Expression Evaluator Grammar Rules, which define the grammar for my rational expression evaluator example.
- Rational Expression Evaluator Grammar to Design, which defines an OO design that emerges directly from the grammar.
- Rational Expression Evaluator, which is a complete Rational Expression Evaluator implementation, but it does not have a reasonable interface with the user.
- Interactive Rational Expression Evaluator, which defines a Scanner and Parser that evaluates the Rational Expression DSL and executes it via a Read-Eval-Print Loop.
- Yuri, the Programming Assignment and Me, which features a recursive implementation for an arithmetic expression evaluator.
- Working Effectively with Legacy Code, which features a small example of iterating through all possible arguments for a legacy method so it can be refactored safely.
- Mastering Time in Software Testing - Strategies for Temporal Behavior Verification, which features an injected
Clockto take control of time. - Abstract Factory Design Pattern, which features a weapon system consistent with launcher/project pairs, such as rifle/bullet, bow/arrow, etc.
- The Build Design Pattern required several blogs with several complete phases showing its evolution:
- Builder Design Pattern - Basic Implementation, which features building a Pizza using several techniques.
- Builder Design Pattern - Complete Implementation, which completes the Pizza Builder example.
- Director, which champions the Director component of the Builder Pattern as its own pattern featuring a Coffee Shop Drink example.
- Singleton Design Pattern, which features several versions of Singleton demonstrating incorrect use, correct use, state injection, etc.
- Flyweight Design Pattern, which features a cloud DVR example.
- Object Pool Design Pattern, which features several versions of an Object Pool.
- Prototype Design Pattern required a couple blogs, each with its own code example:
- Prototype Basics, which featured a Prototype implementation.
- Prototype Shape Rendering Use Case, which featured a Shape Rendering example demonstrating how Prototype and Composite can work together.
Statistics
This started as a retirement project. It quietly became something else.
| Year | Blogs | Words | Countries Reached | Most Views | Comments |
|---|---|---|---|---|---|
| 2021 | 1 | 1,278 | N/A | What is UML and why you may want to care | First prototype blog about UML to set up the environment on GitHub. |
| 2022 | 0 | 0 | N/A | N/A | Still employed; did not start blogging yet. |
| 2023 | 21 | 38,229 | 46 | Hexagonal Architecture – An Introduction | Topics covered were Design Pattern Introduction, Essential Design Patterns and Hexagonal Architecture. |
| 2024 | 35 | 109,944 | 73 | Interpreter Design Pattern – Domain-Specific Languages | Topics covered were Composable Design Patterns, Interpreter Design Pattern, Automated Testing, LLMs/GenAIs and Abstraction. |
| 2025 | 21 | 71,033 | 98 | Specification Design Pattern – Allow a Client to select or filter objects with specific attribute property values as specified by the Client. | Specification is from early 2024, but it was by far the most viewed page. It's in first page results of a few search engines. |
| Totals | 78 | 220,484 |