Skip to main content

9 posts tagged with "architecture"

software architecture

View All Tags

Introducing Hexagonal React: Architecture Enforced by ESLint

· 7 min read
Fabio Fognani
random nerd

I'm excited to announce @dxbox/hexagonal-react, a monorepo template that brings hexagonal architecture (also known as ports and adapters pattern) to React applications with a game-changing twist: architectural rules are enforced at compile-time via ESLint.

The core principle is simple yet powerful: "If it compiles, it's architecturally correct."

CQRS Complete: exploring the potential of use-less-react's new QueryBus

· 6 min read
Fabio Fognani
random nerd

We've reached a significant milestone. With the foundational work on the CommandBus and the recent completion of our QueryBus, we now have the full architectural toolkit to explore Command Query Responsibility Segregation (CQRS) in our complex frontend applications.

While keeping alive the experimental spirit of use-less-react, we are adopting the well-known CQRS pattern. Although our implementation is new, this widely battle-tested best practice promises to consolidate our work, guaranteeing enhanced performance and superior complexity management across the board.

Command and Conquer: mastering application flow with the Hybrid Command Bus

· 8 min read
Fabio Fognani
random nerd

Building modern, scalable applications requires more than just calling functions. It requires a clear, deliberate pattern for initiating and executing changes to your system's state. Enter the Command Bus — an architectural pattern borrowed from Domain-Driven Design (DDD) that provides structure, traceability, and decoupled execution.

In this post, we’ll explore what a Command Bus is, how it differs from its cousin the Event Bus, the architectural problems it solves, and how you can seamlessly integrate use-less-react's Hybrid Command Bus into your application.

How the use-less-react Hybrid Event Bus will improve your Front-End architecture

· 7 min read
Fabio Fognani
random nerd

If you develop complex React applications, you know how hard it is to make distant components communicate without tightly coupling them. Often, the result is a horrible "state monolith" (a single, massive Store or Context) that becomes impossible to understand and - therefore - to maintain. Also, this makes the components difficult to test, because of the abovesaid dependency on a big Store/Context that must be mocked. When this happens, you will dread changes and you won't sleep well.

The fun fact is 99% of the times you don't even really need global state. In such cases, an elegant weapon for more civilized times is an Event Bus, an abstraction that implements the Mediator pattern, bringing Event-Driven Architecture (EDA) directly into your browser.

Using an Event Bus is kinda like getting state updates via the Pub/Sub pattern, but without creating a complex, tangled mess of dependencies across your application. The Event Bus acts purely as a Mediator, decoupling the logic of different application parts. Their only "contract" is the event: more specifically its type and its small, focused payload.

The Half-Truth of React: MVVM Contaminated

· 6 min read
Fabio Fognani
random nerd

React is often categorized as an MVVM (Model-View-ViewModel) framework. This classification is based on two core principles it perfectly enforces:

  1. Unidirectional Data Flow: State flows strictly from Model to View (M → VM → V). The View does not directly mutate the Model; it sends commands back to the ViewModel/Component.
  2. Conceptual Separation: The code conceptually separates the Logic (VM) from the Presentation (V).

However, this is only half the truth. The full truth is that React's design, particularly with Hooks, enforces a critical architectural fusion that undermines the pattern's primary benefit—pure testability:

  • View (V): Your JSX output.
  • ViewModel (VM): The logic that exposes state and actions.

The fundamental issue is that Hooks mandate the fusion of the VM into the V. Your functional component contains the JSX, but it also becomes the seat of the ViewModel (via useState, useEffect, etc.). This fusion is the root of contamination: it forces business logic to become dependent on React's rendering APIs, effectively getting in the way of testability and killing separation of concerns.

Hooks Kill Architecture: The Price Of Sacrificing Classes

· 7 min read
Fabio Fognani
random nerd

The introduction of Hooks in React was presented as a revolution, freeing us from the complexity of classes and their lifecycle methods. We willingly accepted the trade-off: cleaner code, less boilerplate.

But in this process, we imposed a set of rules upon ourselves — often not fully grasped — that have effectively rendered entire categories of Design Patterns unused, and in some cases impossible.

We accepted the price of sacrificing classes, a core feature of the language we're using, and this is something I must admit I overlooked, back in the day. Now I'm asking myself how could that happen. The paradox is clear: the world's most popular UI library abruptly failed to support a core language feature, thereby crippling the expressive potential available to engineers. How could the front-end community think this was a good idea, from an architectural standpoint?

By the way, this is not a debate about "classes vs functions": it is a warning about what we lost at a structural level.

Architectural Guardrails: How Clean Separation of Concerns Dramatically Simplifies PR Reviews

· 8 min read
Fabio Fognani
random nerd

Introduction: The High Cost of Unconstrained Complexity​

In software development, the true cost of a feature is measured not just by the time it takes to write, but by the time it takes to debug, change, and — last but not least — review. When logic is unconstrained, a simple feature often turns into a complex pull request (PR) that demands deep, time-consuming investigation.

This post contrasts two architectural approaches to demonstrate how Separation of Concerns, enforced by a class-based Domain Model (like in use-less-react), dramatically simplifies the PR review process.


Scenario 1: Hooks-based implementation​

Imagine a PR submitted by a junior developer for a new feature. The core logic is housed in a single component file, putting together data and logics from different hooks.

The Component-Centric Trap: Why Domain Logic Needs Its Own Lifecycle

· 5 min read
Fabio Fognani
random nerd

Introduction​

The prevalence of React Hooks has anchored application state and logic firmly within the concept of Component. While this simplifies local UI state, it creates a fundamental architectural problem for complex applications: the subordination of core business logic to the React Component Lifecycle.

Logic packaged in a custom hook is intrinsically tied to where it is executed — it only "lives" as long as the component that uses it is mounted, and its execution is dependent on the component's render cycle.

This is the core argument for elevating state and logic into independent, vanilla Domain Entities.


1. Subordination to the Component Lifecycle​

A custom hook, by definition, must adhere to the Rules of Hooks. This dependency means that the lifecycle of the data and the logic it contains is entirely governed by the useEffect and useLayoutEffect calls within its composition.

The Boilerplate Tax 💸

· 6 min read
Fabio Fognani
random nerd

How use-less-react finally fixes React's boilerplate tax and makes clean architecture practical.​

You're a good developer. You believe in clean architecture. You've heard about separating your app into two "worlds":

  1. the World of Presentation (the UI): Your React components. The "Primary Adapter" that translates user clicks and keyboard tapping into application events.
  2. the World of Logic (the Core): Your business rules and application state. The pure TypeScript functions and classes that don't know or care about UI details.

You start building a new feature. Let's say, a simple dropdown menu.

"This is just UI state," you think. "It's simple. I'll just use useState."

function MyMenu() {
const [isOpen, setIsOpen] = useState(false); // Local. Easy.

return (
<div>
<button onClick={() => setIsOpen(o => !o)}>Toggle</button>
{isOpen && <div>Menu Content</div>}
</div>
);
}

This is clean & pragmatic. You're keeping state as local as possible until a different necessity arises.

Then, a new requirement lands on your desk.

"We're building a tutorial wizard, and it needs to be able to open that menu automatically to show the user where to click."

...and suddenly, you're not so sure about what's "local" and what's not.