Title: The Moment of Change: Rethinking Long-Term Planning in UI Development
Modern UI development thrives on rapid iteration, but this agility often comes at the cost of long-term sustainability. Teams find themselves trapped in a cycle of rewriting code as frameworks evolve, implementation details shift, and abstractions leak. The root of this fragility lies in our over-reliance on concrete frameworks rather than architectural principles—a problem that demands a fundamental rethinking of how we plan, design, and build.
This article explores why traditional long-term planning fails in today’s UI ecosystem, proposes solutions to decouple code from volatile implementation details, and envisions a future where UI development is driven by conceptual clarity rather than framework churn.
Modern UI development is tightly coupled to frameworks like React, Angular, or Vue. While these tools accelerate initial development, they bind teams to their implementation specifics:
- Frameworks evolve: What’s cutting-edge today becomes legacy tomorrow.
- Leaky abstractions: Components often depend on framework-specific lifecycle methods or state management.
- Rigid mental models: Developers equate architecture with framework patterns (e.g., Angular’s MVVM), limiting adaptability.
TypeScript offers temporary relief by catching errors early and enabling AI-assisted refactoring, but it’s not enough. To future-proof code, we need architectural insulation—a way to abstract logic from frameworks while retaining flexibility.
True architecture isn’t about frameworks—it’s about designing systems that isolate concerns and postpone decisions. Let’s rethink the classic React TicTacToe tutorial to illustrate:
Key Principles
- Component-as-Entity: Treat components like domain entities (e.g.,
Game
,Board
,Square
) with clear responsibilities. - ViewModel as Props: Instead of framework-specific state, pass a
props
object encapsulating logic (e.g.,mapStateToBoardProps
). - Dependency Injection: Decouple I/O (e.g., fetch requests) from components for easier testing and decision postponing.
Example
// Game component manages state but delegates rendering to Board
export default function App() {
const [state, setState] = useState<TState>(...);
return <Game boardProps={mapStateToBoardProps(state, setState)} ... />;
}
// Board renders squares without knowing state management details
export function Board({ squareProps, status }: TBoardProps) {
return (
<>
<div className="status">{status}</div>
{squareProps.map(row => <div className="board-row">...</div>)}
</>
);
}
export const mapStateToBoardProps = getMapStateToProps(dependencies as TOutsideWorldDependencies);
Here, mapStateToBoardProps
acts as a lightweight ViewModel, translating state into framework-agnostic props. This pattern works with React today but could adapt to Svelte or Angular tomorrow.
The rise of AI and declarative programming demands a shift from coding to conceptualizing. Domain-Driven Design (DDD) attempted this with "ubiquitous language," but its abstractions often leak (it jumps to OOP development directly, whereas OOP development is a detail, a true ubiquitous language can happen even without development team in a company) A better approach:
Top-Down Ontology Design
- Start with mocks: Define UI flows and interactions first.
- Derive entities: Let components (e.g.,
Square
,Move
) emerge from user needs. - Automate relationships: Use tools like the Owl ontology language to formalize concepts (e.g.,
:Square :parent :Entity
).
Example
:Game :parent :Entity .
:Move :parent :Action .
:Board :parent :Entity .
This ontology becomes the system’s backbone, enabling AI-driven refactoring (e.g., merging duplicate concepts) and propagating changes across designs, UI, and backend.
Even though we started with development with designs, it doesn't mean that ontology is secondary. It just means that we can't start with ontology directly because we will most likely create unecessary entities that will not scale well.
As Henric Altschuller famously said that there is a law of technical systems increasing the degree of their idealism over time, this tred is really going to continue, software will keep getting more and more declarative
The UI developer of tomorrow will resemble an applied philosopher-devops hybrid:
- Ontology-Driven Tools: Systems will auto-generate code from declarative ontologies.
- AI as Collaborator: AI will refactor ontologies, suggest simplifications, and update dependent code.
- Framework-Agnostic Layers: UI code will depend on designs, designs on ontologies, and backends on contracts—not frameworks.
Imagine a workflow where:
- A designer updates a Figma mock.
- The ontology updates, triggering AI to refactor component interfaces.
- The backend adjusts its API schema automatically.
Long-term planning in UI development isn’t about predicting the future—it’s about building systems that embrace change. By decoupling logic into architectural layers and grounding work in formalized ontologies, teams can escape the framework upgrade treadmill.
The future belongs to those who treat code as a byproduct of clear thinking, not the endpoint. Let’s stop writing for today’s React or Angular and start designing for the systems of tomorrow.
For code examples and ontology details, refer to the TicTacToe implementation and OWL ontology discussed in this article.