Frequently Asked Questions About Dimma Front-End Design Patterns Framework

22 answers covering everything from basics to advanced usage.

// Basics

What is a fat client vs. a thin client in front-end architecture?

A fat client is a front-end application with significant business logic running on the client side — validation rules, state machines, calculations, and domain logic. A thin client mostly displays data fetched from a server with minimal client-side logic. This distinction matters because Dependency Inversion, abstraction layers, and IoC containers add real value in fat clients but create unnecessary complexity in thin clients.

What is the god component antipattern?

A god component is a single component or hook that handles too many unrelated responsibilities — fetching data, validating forms, managing state, formatting output — all in one place. It violates the Single Responsibility Principle because it has multiple independent reasons to change. Modifying one behavior risks breaking others. The fix is splitting into separate components or hooks, each with one reason to change.

What does high cohesion and low coupling mean in front-end code?

High cohesion means things that change together live together — all logic for one feature is in one hook, component, or module. Low coupling means separated modules are truly independent — removing module B doesn't break module A. The target state is high cohesion within a module and low coupling between modules. Vertical slice architecture (organizing by feature, not by layer) is a project-level expression of this principle.

What's the difference between design patterns and architectural patterns in front-end?

Design patterns operate at the code level — how to structure individual components, hooks, functions, and types (SRP for a hook, OCP for a function). Architectural patterns operate at the system level — how parts of the application connect and communicate (MVC, Feature Slice Design, Layered Architecture). The Dimma Framework explicitly warns against conflating them. A well-structured hook (design) can exist inside a poorly organized project (architecture), and vice versa.

// How To

How do I apply Dependency Inversion in React?

Separate business logic from infrastructure. Make your business logic a pure function or hook that receives data as parameters — it never directly imports fetch calls or API functions. Create a separate connector hook that fetches data and passes it into the business logic hook. For shared services like loggers or analytics, use React Context as an Inversion of Control container so the service can be swapped without editing consumers.

How do I refactor a hook that does too many things?

List every reason the hook could change independently — API contract changes, validation rule changes, formatting changes, state shape changes. Each independent reason becomes its own hook. Wire them together in a parent component or a thin orchestration hook. Test each hook in isolation. If you find only one reason to change, the hook is fine as-is — don't over-split just for the sake of smaller files.

How do I apply Open/Closed to a function with many if/else branches?

Extract the shared logic into a base function or hook. Each variant (each branch of the original if/else) becomes its own function implementing the variant-specific behavior. Pass the variant function as a callback parameter to the base. Adding a new variant now means writing a new function — the base is never modified. However, if a branch is just a small variation (not a fundamentally different scenario), a simple if/else is fine — don't over-extract.

How do I write better AI prompts for front-end code using the Dimma Framework?

Replace vague instructions with pattern-specific language. Instead of 'write clean code,' say 'create a hook with a single responsibility: managing form validation for email and password fields. It should not handle API calls or state management for submission.' Include the principle name and an example of what to avoid. This specificity gives AI models clear constraints that produce more consistent, maintainable output.

How do I use the Dimma Framework during code reviews?

Replace vague feedback with pattern-named observations. Instead of 'this doesn't look right,' say 'this hook violates SRP — it has three reasons to change, split into separate hooks.' Instead of 'this is too complex,' say 'this violates KISS — useState is sufficient here, useReducer adds complexity without a current need.' Pattern-named feedback is faster to act on for the author and produces better learning outcomes across the team.

Can I use the Dimma Framework to review AI-generated front-end code?

Yes, and it's one of the framework's explicit use cases. Run AI-generated code through the 10-step workflow: check SRP (does the generated hook have multiple reasons to change?), check YAGNI (did the AI add configuration options nobody asked for?), check KISS (did it use useReducer when useState would work?). AI models frequently over-engineer solutions — the framework gives you a structured checklist to catch exactly those issues.

// Troubleshooting

My refactored code has too many small files — did I over-apply SRP?

Probably yes. Every new module has a cost: more files, more navigation, harder to trace data flow. SRP says split by reason to change, not 'make everything as small as possible.' If two pieces of logic always change together for the same reason, they belong in the same file. Re-merge modules that don't have genuinely independent reasons to change. The goal is high cohesion, not maximum file count.

I extracted a shared utility but it keeps getting more complex — what went wrong?

You likely hit the wrong abstraction antipattern. The code you merged looked similar but serves different purposes for different consumers. Each consumer now needs conditional logic inside the shared utility, making it fragile. The fix is to split the utility back into separate functions per consumer. Duplication across domain boundaries is often correct — apply DRY only to genuinely shared knowledge, not coincidentally similar code.

When should I use useReducer instead of useState?

Apply KISS: use useState until the problem actually requires useReducer. If your state transitions are simple (toggle a boolean, set a string), useState is correct. Switch to useReducer when you have complex state with multiple interdependent transitions, or when the next state depends on the previous state in non-trivial ways. Don't use useReducer preemptively 'for scalability' — that's a YAGNI violation.

Should I apply DRY to my test files?

No. Tests should NOT be DRY — they must remain readable and self-contained. A test is verified by reading it, not by other tests. If you hide setup behind multiple helper layers, the test's purpose becomes unclear. Use helpers only to remove pure boilerplate (like creating mock objects), never to hide the logic being tested. Every test should be understandable without jumping to other files.

// Comparisons

How does the Dimma Framework compare to Feature Slice Design?

They operate at different levels. The Dimma Framework provides design patterns — how to structure individual components, hooks, functions, and types using SOLID, DRY, KISS, and YAGNI. Feature Slice Design is an architectural pattern — how parts of the application connect and how folders/modules are organized at the project level. The Dimma Framework explicitly warns against conflating design patterns with architectural patterns. You can use both together.

How is the Dimma Framework different from just following SOLID principles?

Standard SOLID principles are described in OOP and backend terms — classes, interfaces, inheritance hierarchies. The Dimma Framework adapts each principle specifically to front-end entities: React hooks, components, TypeScript types, and client-side architecture. It adds front-end-specific calibration (fat vs. thin clients, project scale), a concrete 10-step workflow, and pattern vocabulary designed for AI prompting and code reviews.

Is the Dimma Framework only for React developers?

No, the principles apply to any front-end framework. SRP applies to Vue composables and Angular services the same way it applies to React hooks. Dependency Inversion uses React Context, Angular's Injectable system, or Vue's provide/inject as IoC containers. The specific examples reference React hooks, but the concepts — split by reason to change, depend on abstractions, don't build what you don't need — are framework-agnostic.

// Advanced

How does the Dimma Framework handle TypeScript interfaces?

Through Interface Segregation: don't force a component or class to depend on properties it doesn't use. If you have one broad interface with 20 fields and different consumers only need subsets, split it into focused interfaces. A red flag is using TypeScript's Partial<T> everywhere to paper over fields that never exist for a given entity. This principle is most relevant in larger codebases with shared types — rarely needed in small projects.

When is it okay to violate YAGNI and build for the future?

When the roadmap explicitly plans for a use case in the near term. If multi-language support is confirmed for next quarter, don't hardcode user-facing strings — that's reasonable preparation, not premature abstraction. YAGNI targets hypothetical features nobody has asked for: generic components with many unused props, HTTP clients with interceptors nobody needs, or multiple interface implementations when only one exists. YAGNI is also never an excuse to skip error handling, tests, or reasonable project structure.

How do I apply Liskov Substitution in front-end components?

If a component extends a base component, the extended version must support all props and behavior of the original. A violation looks like: a child component renames or removes props the parent defines, or a subclass throws errors on inherited methods. If a class can't support all methods of the interface it extends, the fix is to split the interface — which is also an ISP fix. LSP ensures that swapping an extended component for the base never breaks the app.

Should I apply Dependency Inversion in a small project?

Only apply full DIP with abstraction layers and IoC containers in fat clients — applications with significant business logic on the client. In thin clients or small projects that mostly display data, full Dependency Inversion adds complexity without benefit. A simple hook that directly calls fetch is fine when there are no domain rules to protect. Scale your architectural investment to your actual problem complexity — that's KISS applied to architecture.

How do I decide if duplicated code is shared knowledge or coincidental similarity?

Ask: if the business rule behind this code changes, should both copies change identically? If yes, it's shared knowledge — extract to a single source of truth. If no — if each copy could evolve differently for different business reasons — it's coincidental similarity and should stay duplicated. The email validation example is shared knowledge; two modules with similar-looking but domain-specific data transformations are often coincidental similarity.