Posts (page 2)

Meet Michael Carducci...

A poster for the Derek DelGaudio's special event documentary, In and Of Itself

A.k.a Michael Cary - and all the other identities and aliases I have held in my life (fun fact, this might be the first time ever those two names have appeared side by side in public!). They’re all masks I’ve worn, idealized versions of myself that I want to present to the world and, ultimately, lies I’ve told myself (and possibly you).

“I’m not defined by what you see, I’m also all of the things you’ll never see.”

-Derek DelGuadio, In and Of Itself

I wrote something today, and felt moved to publish it somewhere. If you are one of the vanishingly few people who actually read my blog, it’s entirely possible you’re interested in getting to know not just my thoughts on tech, but perhaps also interested in getting to know me a little deeper as well.

Read on if you want to see some of the parts of me you have likely never seen. I’m exposing myself for a moment, “warts and all.” If not, no worries, more tech opinions and knowlege are already in the works.

Continue reading...

Third-Way Web Development Part I - History

a timeline of the simplicity of web development in 2014, the complexity in 2019, and HTMX introducing a new simplicity in 2021

When I look back on my career in technology, I’ve been seduced, over and over again, by this idea that best practices exist and that I can consider my work “good” so long as I follow those best practices. In some ways it would be wonderful to work in a field where there are absolute “right” and “wrong” answers but I no longer believe software engineering is one of those fields. Every single decision we make has consequences and whether these consequences are positive, negative, or mixed will depend on the context. It’s all just a set of trade-offs, and the key to making good decisions lies in understanding what matters most and evaluating the trade-offs in this context.

There are no best practices, only trade-offs.

-First law of Software Architecture

We’ve somehow gotten into this weird place in web development where the consensus seems to be that an absolute set of best practices exist; where the only meaningful decisions surround which framework to use and how to find the optimal implementation details within that chosen framework. Unfortunately the web development space has become so myopically focused on frameworks, tooling, and Single-Page Applications (SPAs) as the de-facto “best practices” that the trade-offs of these approaches are rarely discussed–or even well-understood up front–and, in many cases, the result is an ocean of bloat and accidental complexity that often could have been avoided entirely.

Continue reading...

Reflection an a Decade and a Half on Dvorak

old black & white picture of an original underwood typewriter

I have now been typing using the Dvorak keyboard layout longer than I have used QWERTY. It’s been over 15 years since I first switched and probably a decade since I moved to the even more niche Programmer Dvorak Layout. As the year winds down (and I am in currently in quarantine) I figure I’d take some of this idle time to write a little bit, and this is where my head is at today. Who knows, there may be some interesting take-aways from this. On the other hand, it may just be 1000-or-so words of “brain droppings” as George Carlin would say.

Continue reading...

Abstract Style: Space-Based Architecture

Drawn/blueprint-style illustration of the space-based architecture pattern.

Many developers strive for elegance efficiency in their code. Imagine a hypothetical developer who takes this too far. Perhaps this developer looks back in shame at the sloppy, inefficient implementations their much less experienced self had written. They were, undoubtedly and objectively, “bad.” Over time, their code grew cleaner and more efficient. They could measure progress in wall-clock time, algorithmic complexity, or other quality metrics. Somewhere, however, the pendulum swung too far. If their “bad” code was slow, and their “better” code is faster, it stands to reason that even faster is even better. They reached a point where they would squeeze out every spare microsecond at all costs. The result was difficult to read, change, and understand; perhaps “the juice was not worth the squeeze.”

Performance can be a valuable system capability, but only in context. Remember the “Mad Potter’s” wisdom on the difference between “a lot” and “enough.” Architecture trade-offs must be considered in many dimensional contexts. Never trade an excess of one capability for a deficit of a more important capability. That said, sometimes performance is among that short-list of business-critical capabilities–perhaps at the very top. What constraints induce high-performance at the architectural level? Read on to learn about the Space-Based Architecture.

Continue reading...

Abstract Style: Service-Based (a.k.a. 'miniservices')

Drawn/blueprint-style illustration of the service-based architecture pattern.

In our previous post we looked at a technically partitioned, coarse-grained, distributed architecture. Although that pattern balances capabilities like scalability and elasticity with low cost and simplicity, a domain-partitioned architecture may offer many advantages. For an organization with well-defined domains and domain-aligned teams, this next pattern offers a very balanced and pragmatic distributed architecture that offers comparable capabilities to an architecture like microservices at a fraction of the cost and complexity. In short, a Service-Based architecture offers a highly viable “middle-ground” between monoliths/n-tier architecture and microservices. This architecture can act as a stepping stone between monoliths and more complex topologies although often it will represent an acceptable and desirable end-state for green-field and legacy systems alike. Read on to learn about the Service-Based Architecture

Continue reading...

Abstract Style: N-Tier

Drawn/blueprint-style illustration of the n-tier architecture pattern.

So far in this series on abstract styles we have only looked at monolithic abstract styles and a handful of defining constraints. In reality, however, much–in not most–of the systems we will design as architects will involve some kind of network component. Although many implementations of the layered monolith or modular monolith may be extended through the addition of the client-server constraint (and, typically, some type of API constraint) the next several posts will focus on abstract styles that are, at their core, natively distributed. We will start by examining the N-tier architecture.

Continue reading...

Abstract Style: Microkernel

Drawn/blueprint-style illustration of the microkernel architecture pattern.

Agility is a term that is typically poorly-defined–and often overloaded–in many business circles. Yet the underlying capability remains highly sought-after. Agility can be broadly defined as the ability of the business to adapt and respond to change. Agility is desirable because change is inevitable, and comes in a number of forms. With the progression of technology, from digital computers to personal computers, to the internet, to the web, to the mobile web, and beyond; the rate of change is only increasing. Businesses unable to keep pace will be disrupted, and we see this almost daily. We also cannot escape the fact that software runs almost every business. While there is a near infinite number of ways to write code to ship a set of features, software systems that are rigid and difficult to change will continue to constrain business agility. In short, if our software is not agile, the businesses it powers won’t be either.

As we have discussed in previous posts in this series, conventional wisdom is that monolithic architectures might offer low cost and high simplicity, but aren’t capable of meaningful agility. Through careful combination of key architectural constraints, however, architecture can yield monolithic systems that balance agility and simplicity. The goal of architecture is not to provide “a lot” (undefinable) of a given capability, but a minimum of “enough” (driven by business needs). To this end, we introduce another abstract architectural style, the Microkernel Architecture Pattern.

Continue reading...

Abstract Style: Modular Monolith (a.k.a. 'Vertical Slice Architecture')

Drawn/blueprint-style illustration of the modular monolith architecture pattern.

When many developers these days are asked “Which is better: Monolith or Microservices?” The answer is often a resounding ‘Microservices!’ The term monolith has become a pejorative; a veritable four-letter word in some software architecture circles. The folk-wisdom criticisms are not entirely undeserved, after all there are a lot of bad monoliths out there; unmaintainable, untestable, brittle to the point of personifying a Jenga tower of code. Yes, the microservices pattern offers many strengths. Yes, the layered monolith carries many weaknesses. However, that’s not the end of the story. As we have learned so far in this series, capabilities like testability, maintainability, evolvability, etc. don’t originate from deployment granularity but instead emerge from architectural constraints.

What might the humble monolith look like if an architect applied some of the constraints that give microservices their magic? Meet the Modular Monolith.

Continue reading...

Abstract Style: Layered Monolith

Drawn/blueprint-style illustration of the layered monolith architecture pattern.

Patterns have become indispensable tools in software development.. Patterns can provide a high-bandwidth mechanism for communicating ideas, however as our industry has noted (and we explored in-depth in our previous post) application of architecture patterns rarely yield a consistent set of outcomes for any given project. A powerful solution is to apply the idea of design-by-constraint. This resolves the prevalent semantic ambiguities of our current architecture pattern set and enables a more reliable and deterministic means of inducing architectural capabilities in systems.

In the dynamic world of software architecture, be it for buildings or software, two dominant philosophies emerge. The first imagines a designer starting from scratch–a void on a whiteboard–and begins meticulously crafting an architecture, piece by piece, with familiar components until it embodies the system’s aspirations. The alternative perspective envisions a designer commencing with an all-encompassing view of the system’s requirements, unshackled by constraints. As the design evolves, constraints are strategically imposed on system elements, fine-tuning the design canvas and allowing the forces that mold system behavior to move fluidly, in perfect sync with the system’s essence. While the former accentuates unbridled creativity, the latter champions understanding and discernment within the system’s milieu. It’s this latter philosophy that the Tailor-Made Software Architecture reveres, focusing on constraints as composable design elements to both precisely define our architectures and also enable fine-grained control of the capabilities and characteristics the architecture elicits. Architectural constraints possess a high-degree of reusability and they can typically be applied to almost any pattern or candidate architecture. For the next several posts, we will define the eight common patterns in terms of their core constraints, potential optional constraints, and highlight how the composition of these constraints results in a predictable set of architectural capabilities. We begin with the humble layered monolith.

Continue reading...

Architectural Styles - The Tailor-Made Pattern Language

interior of a complex glass building with the caption 'Architectural Styles'

In our previous post, we discussed how the business problems we tackle through software architecture seldom align perfectly with just eight sizes (the conventional architecture patterns). More often than not, any system’s architecture that adheres to a specific pattern tweaks it significantly. This deviation brings forth two critical challenges that the Tailor-Made approach seeks to resolve:

Firstly, the prevalent tendency to oversimplify diverse and distinct systems filled with numerous modifications leads to miscommunication and ambiguity in portraying the architecture’s intricacies. Secondly, relying on a pattern-based language holds value only if there’s a unanimous consensus regarding the pattern’s definition.

We have already shown that an architecture can essentially be defined by its constraints it is, consequently, imperative to embrace Dr. Roy Fielding’s notion of the “architectural style.” Such an adaptation ensures clearer pattern definitions and more transparent architectural communication. Moreover, it unlocks a vast spectrum of architectural styles, moving beyond the confines of the standard eight patterns.

Continue reading...