DEV Community

Cover image for On the Criteria To Be Used in Decomposing Interfaces into Components and Modules
Gurigraphics
Gurigraphics

Posted on

On the Criteria To Be Used in Decomposing Interfaces into Components and Modules

--> Portuguese version


Resume

This article contains the FUNDAMENTALS for developing less confusing interfaces. Nothing here is an "absolute truth." But I consider it required reading for anyone who wants to start thinking about User Interfaces.


Starting Point

In a 2D interface, everything you see exists within a hierarchy. Each level contains the next, like nested boxes.


Level 0: Window — The Observer

What it is: The browser viewport. Your screen's viewing frame.

Critical distinction: Window is not part of the interface structure. Window is the medium through which you observe the interface.

Analogy: Book vs Eye
- Complete book = Page (may have 100 pages of content)
- Your field of vision = Window (sees 2 pages at a time)
- Turning page = scroll
Enter fullscreen mode Exit fullscreen mode

The relationship:

  • Page has 3000px height
  • Window has 800px height
  • You see ~27% of Page at once
  • Scroll reveals Page \ Window (the unseen part)

Remember: Window ≠ Page


Level 1: Page — The Universe

What it is: The largest indivisible unit. The total content space.

Key property: A Page is indivisible as an entity. You don't "split a Page into two Pages". You organize a Page using Regions.

<div class="page-home">
  <!-- Everything here is THE Page -->
  <!-- Not "two pages", but ONE page with divisions -->
</div>
Enter fullscreen mode Exit fullscreen mode

Important distinctions:

Structural (HTML delimited):

<div class="page-home">
  <!-- Explicit structure in markup -->
</div>
Enter fullscreen mode Exit fullscreen mode

Conceptual (CSS delimited):

.page-home {
  display: grid;
  grid-template-columns: 1fr 1fr; /* left/right division exists only in CSS */
}
Enter fullscreen mode Exit fullscreen mode

Both are valid. One is explicit (structural), the other is implicit (conceptual).

Z-index layers:

Page (z-index: 0)  ← Base layer
Page (z-index: 1)  ← Overlay (modal, dropdown)
Page (z-index: -1) ← Background layer
Enter fullscreen mode Exit fullscreen mode

A Page can have multiple Layers.
Think of them as transparent sheets stacked on top of each other.
Page is the combination of these layers when there is more than one.


Level 2: Region — Spatial Divisions

What it is: A Page contains Regions. Regions organize space, not replace the Page.

The divisibility principle:

Wrong thinking:

"Page splits into left and right, creating two new Pages"

Correct thinking:

"Page contains left Region and right Region"

Example:

<div class="page-home">
  <div class="region-top"></div>    <!-- Region 1 -->
  <div class="region-bottom"></div> <!-- Region 2 -->
</div>
Enter fullscreen mode Exit fullscreen mode

Structural vs Conceptual:

Structural:

<div class="region-left">
  <!-- Explicit HTML element -->
</div>
Enter fullscreen mode Exit fullscreen mode

Conceptual:

.page-home {
  display: flex;
  /* Left "region" is first 300px, right "region" is remaining space */
  /* No explicit HTML elements, but regions conceptually exist */
}
Enter fullscreen mode Exit fullscreen mode

Space between Regions:

<div class="page">
  <div class="region-top"></div>
  <div class="region-bottom" style="margin-top: 30px"></div>
  <!-- 30px gap is PART OF THE PAGE, not a third region -->
</div>
Enter fullscreen mode Exit fullscreen mode

The available space is not a region. It can be occupied by a region.


Level 3: Section — Functional Divisions

What it is: A Region contains Sections. Sections organize by purpose/function.

Difference from Region:

  • Region = spatial organization ("where on screen": top, left, right, bottom)
  • Section = functional organization ("what it does": header, nav, content)

Example:

<div class="page-home">
  <div class="region-top"> 
    <div class="section-header">Header content</div> 
  </div>

  <div class="region-bottom">
    <div class="section-left">Sidebar navigation</div>
    <div class="section-right">Main content</div>
  </div>
</div>
Enter fullscreen mode Exit fullscreen mode

Structural vs Conceptual:

Structural:

<div class="section-navigation">
  <!-- Explicit element -->
</div>
Enter fullscreen mode Exit fullscreen mode

Conceptual:

.region-sidebar {
  display: flex;
  flex-direction: column;
  /* Top 100px is conceptually "nav section" */
  /* Remaining space is conceptually "content section" */
  /* No explicit HTML, but sections exist conceptually */
}
Enter fullscreen mode Exit fullscreen mode

Level 4: Component — The Complex Part

What it is: A Section displays Components. Components are operational units that can have state and behavior.

<div class="section-header"> 
  <app-header>Header component</app-header> 
</div>
Enter fullscreen mode Exit fullscreen mode

Component Types

Here's where it gets interesting. There are multiple ways to classify Components:

Classification 1: By Space Division

Simple Component:

<div class="card">
  <img />      <!-- Element -->
  <h3></h3>    <!-- Element -->
  <p></p>      <!-- Element -->
</div>
Enter fullscreen mode Exit fullscreen mode

No spatial divisions. Just a set of Elements.

Formal Component (Micro Pages/ Fractal Pages):

<div class="card-complex">
  <div class="region-header">    <!-- Has Regions -->
    <div class="section-title">  <!-- Has Sections -->
      <h3></h3>                   <!-- Has Elements -->
    </div>
  </div>
  <div class="region-content">
    <!-- ... -->
  </div>
</div>
Enter fullscreen mode Exit fullscreen mode

Contains full structure: Regions → Sections → Elements (instead of Components).

The classification is contextual and dynamics, not fixed.

Classification 2: By Composition

Composite Component:

<div class="user-profile">
  <app-avatar />     <!-- Sub-component -->
  <app-user-info />  <!-- Sub-component -->
  <app-actions />    <!-- Sub-component -->
</div>
Enter fullscreen mode Exit fullscreen mode

Made of other Components (Sub-components).

Sub-component: Any Component displayed inside another Component.

Classification 3: By Use

Composite Component (componente composto):

<div class="sidebar">
  <app-button name="home" /> <!-- Subcomponente -->
</div>
<div class="menu">
  <app-button name="options" /> <!-- Subcomponente -->
</div>
<app-button name="start" /> <!-- Element -->
Enter fullscreen mode Exit fullscreen mode

When an element is used in multiple components, it can be considered an Element. And it can belong to an element library, not a component library.

Classification 4: By Complexity

Complex Component:

<div class="data-table">
  <app-table-header />   <!-- Sub-component -->
  <app-table-body />     <!-- Sub-component -->
  <app-pagination />     <!-- Sub-component -->
  <!-- Each sub-component is also a complex component -->
</div>
Enter fullscreen mode Exit fullscreen mode

Formed by multiple Sub-components that work together.


Level 5: Element — The Atom

What it is: The smallest functional unit.

Examples:

  • <button> — one button
  • <input> — one input field
  • <a> — one link
  • <img> — one image

Important: Elements can also be Simple or Formal.

Simple Element

<button>Click me</button>
Enter fullscreen mode Exit fullscreen mode

Just text. No internal structure.

Formal Element

<button class="complex-button">
  <div class="region-left">
    <svg class="icon"></svg>         <!-- Section: icon -->
  </div>
  <div class="region-center">
    <span class="text">Click</span>  <!-- Section: text -->
  </div>
  <div class="region-right">
    <svg class="dropdown"></svg>     <!-- Section: dropdown icon -->
  </div>
</button>
Enter fullscreen mode Exit fullscreen mode

It has structural or conceptual Regions and Sections.

The classification shift:

When a item stop being an Element and become a Subelement or Component?

Context determines it:

<button>Click here</button> <!-- Element -->
Enter fullscreen mode Exit fullscreen mode
<button class="icon-button"> <!-- Element -->
  <span>Text</span> <!-- Subelement -->
</button>
Enter fullscreen mode Exit fullscreen mode

This is an Element (atomic interaction unit).

When it shows a menu:

<button class="dropdown-button" @click="showMenu">
  <svg></svg>
  <span>Text</span>
  <svg class="arrow"></svg>
</button>
<div class="dropdown-menu" v-if="menuVisible">
  <!-- Menu items -->
</div>
Enter fullscreen mode Exit fullscreen mode

Now it's a Component (has state, behavior, manages sub-elements).

When used inside another component:

<div class="toolbar"> <!-- Component -->
  <icon-button />  <!-- Now it's a Sub-component -->
  <icon-button />
  <icon-button />
</div>
Enter fullscreen mode Exit fullscreen mode

Now it's a Sub-component (Component inside Component).


The Dynamic Nature of Classification

Example: Icon Button Evolution

Stage 1 - Simple Element:

<button>
  <svg></svg>
</button>
Enter fullscreen mode Exit fullscreen mode

Classification: Element

Reason: Atomic unit, no internal divisions

Stage 2 - Formal Element:

<button>
  <div class="section-left"><svg></svg></div>
  <div class="section-center"><span>Text</span></div>
  <div class="section-right"><svg></svg></div>
</button>
Enter fullscreen mode Exit fullscreen mode

Classification: Element (still) or Component (depends on context)

Reason: Has internal structure, but still one functional unit

Stage 3 - Simple Component:

<icon-button icon="search" input-text="Search" />
Enter fullscreen mode Exit fullscreen mode

Classification: Component

Reason: Can be broken down into more than one functionality

Stage 4 - Sub-component:

<div class="search-bar">
  <icon-button icon="search" />  <!-- This one -->
  <input />
  <icon-button icon="clear" />
</div>
Enter fullscreen mode Exit fullscreen mode

Classification: Sub-component

Reason: Component used inside another Component

Stage 5 - Complex Component:

<icon-button-with-dropdown 
  icon="more" 
  @click="toggleMenu"
>
  <dropdown-menu v-if="open">
    <menu-item />
    <menu-item />
  </dropdown-menu>
</icon-button-with-dropdown>
Enter fullscreen mode Exit fullscreen mode

Classification: Complex Component

Reason: Manages state, has Sub-components, complex behavior


Visibility Control

Any level can show/hide:

// Hide Region
page.regions.top.hide()

// Hide Section
page.regions.main.sections.sidebar.hide()

// Hide Component
page.regions.main.sections.content.components.userCard.hide()

// Hide Element
page.regions.header.sections.nav.components.menu.elements.loginButton.hide()
Enter fullscreen mode Exit fullscreen mode

Example:

<div class="page">
  <div class="region-top" v-if="showHeader">     <!-- Can hide entire Region -->
    <div class="section-nav" v-if="showNav">     <!-- Can hide Section -->
      <app-menu v-if="isLoggedIn">               <!-- Can hide Component -->
        <button v-if="canEdit">Edit</button>     <!-- Can hide Element -->
      </app-menu>
    </div>
  </div>
</div>
Enter fullscreen mode Exit fullscreen mode

Complete Hierarchy with Examples

Window (browser viewport: 1920×1080)
  ↓ observes
Page (total content: 1920×3000)
  ↓ contains
Region (top: 1920×100, main: 1920×2800, footer: 1920×100)
  ↓ contains
Section (in main region: sidebar-left: 300×2800, content: 1620×2800)
  ↓ contains
Component (in sidebar: navigation-menu component)
  ↓ contains (if Simple Component)
Element or Subcomponents (menu-item button)
Enter fullscreen mode Exit fullscreen mode

Modules and Sub-modules — Functional Grouping Across Structure

What it is: A different classification axis. While hierarchy is about spatial containment (what's inside what), Modules are about functional cohesion (what works together).

Key insight: Components can be spatially separated but functionally united.

The Cross-Cutting Nature

Hierarchy says: "This Component is inside this Section"

Module says: "These Components, wherever they are, belong to the same feature"

Example: Code Editor Module

<div class="page">
  <div class="region-left">
    <div class="section-sidebar">
      <file-tree />              <!-- Part of Editor Module -->
      <search-panel />           <!-- Part of Editor Module -->
    </div>
  </div>

  <div class="region-right">
    <div class="section-main">
      <code-editor />            <!-- Part of Editor Module -->
      <status-bar />             <!-- Part of Editor Module -->
    </div>
  </div>

  <div class="region-bottom">
    <div class="section-terminal">
      <terminal-panel />         <!-- Part of Editor Module -->
    </div>
  </div>
</div>
Enter fullscreen mode Exit fullscreen mode

All these Components are spatially separated (different Regions/Sections) but functionally united (Editor Module).

Module Definition

A Module is:

  • A collection of Components that work together
  • Can span multiple Regions/Sections
  • Shares state, data, or behavior
  • Implements one complete feature/functionality

Sub-modules

What it is: Modules can contain Sub-modules for finer functional granularity.

Example: Editor Module with Sub-modules

Editor Module
├─ File Management Sub-module
│  ├─ file-tree (in left sidebar)
│  ├─ file-tabs (in top bar)
│  └─ file-actions (in context menu)
│
├─ Code Editing Sub-module
│  ├─ code-editor (in main area)
│  ├─ syntax-highlighter (inside editor)
│  └─ autocomplete (overlay)
│
└─ Debugging Sub-module
   ├─ breakpoint-gutter (in editor margin)
   ├─ debug-toolbar (in top bar)
   └─ variables-panel (in right sidebar)
Enter fullscreen mode Exit fullscreen mode

All components in "File Management Sub-module" share state:

  • Opening a file in file-tree updates file-tabs
  • Closing a tab in file-tabs updates file-tree selection
  • file-actions operates on state from both

Distinction from Other Classifications

Component vs Module:

Component Module
Single UI piece Multiple UI pieces
One place in hierarchy Can spans multiple places
Contained in Section Cuts across Sections
Example: <button> Example: "Authentication" feature

Example: Authentication Module

<!-- Spatially: different locations -->

<!-- In top-right Region -->
<user-avatar />          <!-- Auth Module Component -->

<!-- In dropdown overlay -->
<login-form />           <!-- Auth Module Component -->

<!-- In settings Section -->
<account-settings />     <!-- Auth Module Component -->

<!-- In modal -->
<change-password />      <!-- Auth Module Component -->
Enter fullscreen mode Exit fullscreen mode

All these Components belong to Authentication Module despite being in completely different parts of the interface.

Module Communication

Modules can:

  • Share global state
  • Communicate via events
  • Access shared services
  • Coordinate behaviors

Example:

// Editor Module components communicate
fileTree.onSelect(file => {
  codeEditor.open(file)        // Different Component, same Module
  statusBar.update(file.path)  // Different Component, same Module
  terminal.setContext(file.dir) // Different Component, same Module
})
Enter fullscreen mode Exit fullscreen mode

Module vs Component Hierarchy

They're orthogonal concepts:

Spatial Hierarchy:
Page → Region → Section → Component

Functional Grouping:
Module → Sub-module → Component
Enter fullscreen mode Exit fullscreen mode

A Component exists in BOTH:

<file-tree />

Spatial location:
Page → region-left → section-sidebar → file-tree

Functional membership:
Editor Module → File Management Sub-module → file-tree
Enter fullscreen mode Exit fullscreen mode

Practical Example: Dashboard

Spatial structure:

<div class="page-dashboard">
  <div class="region-header">
    <notification-bell />
    <user-menu />
  </div>

  <div class="region-main">
    <div class="section-widgets">
      <sales-chart />
      <revenue-card />
      <activity-feed />
    </div>
  </div>

  <div class="region-sidebar">
    <date-filter />
    <export-button />
  </div>
</div>
Enter fullscreen mode Exit fullscreen mode

Functional modules:

Analytics Module:
├─ sales-chart (in main section)
├─ revenue-card (in main section)
├─ date-filter (in sidebar)
└─ export-button (in sidebar)

Notifications Module:
├─ notification-bell (in header)
└─ activity-feed (in main section)

User Module:
└─ user-menu (in header)
Enter fullscreen mode Exit fullscreen mode

Notice:

  • date-filter and export-button are in same Section (sidebar) but could be in different Modules
  • sales-chart and activity-feed are in same Section (main) but different Modules
  • notification-bell and activity-feed are in different Sections but same Module

When to Use Modules

Use Module classification when:

  • Components need to share state across Regions/Sections
  • You're organizing by feature, not by layout
  • Multiple Components implement one user-facing functionality
  • You need to enable/disable entire features

Example: Feature toggles

if (user.hasFeature('advanced-editor')) {
  enableModule('Editor')  // Activates all Components in Editor Module
  // This could span: file-tree, editor, terminal, debugger, etc.
}
Enter fullscreen mode Exit fullscreen mode

Module Size

Modules can be:

Large (Application-level):

E-commerce Module
├─ Product Catalog Sub-module
├─ Shopping Cart Sub-module
├─ Checkout Sub-module
└─ Order History Sub-module
Enter fullscreen mode Exit fullscreen mode

Medium (Feature-level):

Shopping Cart Module
├─ Cart List Component
├─ Cart Summary Component
└─ Cart Actions Component
Enter fullscreen mode Exit fullscreen mode

Small (Workflow-level):

Checkout Module
├─ Shipping Form Component
├─ Payment Form Component
└─ Confirmation Component
Enter fullscreen mode Exit fullscreen mode

Key Differences Summary

Hierarchy (Spatial):

"Where is it located?"
Page → Region → Section → Component → Element
Enter fullscreen mode Exit fullscreen mode

Module (Functional):

"What feature does it belong to?"
Module → Sub-module → Component
Enter fullscreen mode Exit fullscreen mode

Component Classification (Structural):

"How is it built?"
Simple / Formal / Composite / Sub-component
Enter fullscreen mode Exit fullscreen mode

All three classifications apply to the same Component simultaneously:

<file-tree />

Spatial: Page → region-left → section-sidebar → file-tree
Functional: Editor Module → File Management Sub-module → file-tree
Structural: Composite Component (contains tree-item Sub-components)
Enter fullscreen mode Exit fullscreen mode

Why This Matters

Without Module thinking:

// Components tightly coupled to their spatial location
sidebar.fileTree.onSelect(file => {
  mainArea.editor.open(file)  // Hardcoded locations
})
Enter fullscreen mode Exit fullscreen mode

With Module thinking:

// Components loosely coupled via Module
Modules.FileManagement.onFileSelect(file => {
  Modules.CodeEditing.open(file)  // Location-independent
})
Enter fullscreen mode Exit fullscreen mode

Benefits:

  • Easier to reorganize UI (move Components between Sections)
  • Clearer feature ownership
  • Simpler enable/disable of features
  • Better code organization

Practical Rules

  1. Modules are invisible to users

    Users see Components, not Modules. Modules are a developer concept.

  2. Modules can overlap

    One Component can belong to multiple Modules if needed.

  3. Modules don't have visual representation

    Unlike Regions/Sections, Modules have no HTML container.

  4. Modules follow features, not layout

    If you reorganize the UI, Modules stay the same.

  5. Sub-modules create functional hierarchy

    Like folders organize files, Sub-modules organize related Components.


Remember:

  • Hierarchy = spatial structure (where things are)
  • Modules = functional grouping (what works together)
  • Component types = structural classification (how it's built)

All three perspectives describe the same interface from different angles.


Practical Decision Guide

When building an interface, ask:

Is it a Component or Element?

It's an Element if:

  • Single interaction point
  • Cannot be meaningfully split
  • No internal state management
  • Example: <button>, <input>, <a>

It's a Component if:

  • Has internal structure
  • Manages state or behavior
  • Example: <search-bar>, <user-card>, <data-table>

Is it a Region or Section?

It's a Region if:

  • Primarily spatial division
  • Answers "where?" (top, left, right, bottom)
  • Layout-focused

It's a Section if:

  • Primarily functional division
  • Answers "what?" (navigation, content, header)
  • Purpose-focused

Is it Structural or Conceptual?

Structural:

<div class="region-sidebar">
  <!-- Explicit in HTML -->
</div>
Enter fullscreen mode Exit fullscreen mode

Conceptual:

.page { 
  display: grid;
  grid-template-columns: 300px 1fr;
  /* Left area is conceptually "region-sidebar" */
  /* No explicit HTML element needed */
}
Enter fullscreen mode Exit fullscreen mode

Key Principles

  1. The window defines the space, not the content

    Window ≠ Page. Window shows Page.

  2. Indivisibility means entity integrity

    Page doesn't split into two Pages. Page contains Regions.

  3. Classification is contextual

    Same UI can be Element, Component, or Sub-component depending on usage.

  4. Structure can be explicit or implicit

    HTML structure or CSS layout both create valid divisions.

  5. Fractality exists

    Components can contain full Page-like structure (Regions → Sections → Elements).

  6. Visibility is hierarchical

    Hide a Region → all its Sections/Components/Elements hide too.


Common Mistakes

"My page has two pages: left and right"

✅ "My page has two regions: left and right"

"Window is the page container"

✅ "Window is the viewport that observes the page"

"This button is always an element"

✅ "This button is an element in this context, component in another"

"All divisions must be in HTML"

✅ "Divisions can be structural (HTML) or conceptual (CSS)"

"Components can't contain regions"

✅ "Formal components are micro-pages with full structure"


Final Checklist

Building an interface? Verify:

  • [ ] Window: What viewport sizes do I support?
  • [ ] Page: Does content fit? Need scroll? Multiple z-index layers?
  • [ ] Region: How do I divide space? (Structural or conceptual?)
  • [ ] Section: What functional areas exist in each region?
  • [ ] Component: What's reusable? Simple or formal? Composite?
  • [ ] Element: What are the atomic interaction points?
  • [ ] Classification: Is my naming contextually accurate?

End. You now understand the complete structure of an interface 2D, from viewport to atom.

References:

PARNAS, David L. On the Criteria To Be Used in Decomposing Systems into Modules. Communications of the ACM, Vol. 15, No. 12, pp. 1053 – 1058, 1972.

DESCARTES, René. Discourse on method. 2. ed. São Paulo: Martins Fontes, 2001. 102 p.
(“Divide each of the difficulties I examined into as many parts as possible and as necessary to better resolve them.”)

Top comments (0)