Feature-Sliced Design: bản chất và phương pháp phân chia theo tính năng

Tác giả: IT Sectr Đã đăng: 2026-02-20 Thời gian đọc: 12 phút

Giải thích Feature-Sliced Design là gì — một phương pháp kiến trúc mô-đun frontend dựa trên việc chia dự án theo tính năng kinh doanh thay vì lớp kỹ thuật. Khác với kiến trúc lớp cổ điển (controller, service, repository), FSD nhóm mã theo khả năng chức năng của ứng dụng: mỗi tính năng chứa logic riêng, UI và dữ liệu. Theo khảo sát State of Frontend 2024, 23% nhà phát triển React sử dụng FSD làm phương pháp kiến trúc chính, khiến nó trở thành phương pháp phổ biến thứ hai sau cấu trúc Feature-based thuần túy.

Điểm chính

  • Feature-Sliced Design (FSD) — phương pháp nhóm mã theo tính năng kinh doanh (slice), mỗi slice bao gồm UI, logic, API và kiểm thử.
  • Cấu trúc FSD tiêu chuẩn gồm 7 lớp: app, processes, pages, features, entities, shared, widgets — mỗi lớp có quy tắc import nghiêm ngặt.
  • Quy tắc chính của FSD — «các lớp chỉ nhìn xuống dưới»: lớp features có thể import entities, nhưng không ngược lại.
  • Ưu điểm của FSD: cô lập tính năng, tái sử dụng slice giữa các dự án, phát triển song song không xung đột.
  • Nhược điểm chính — lồng ghép quá mức cho dự án nhỏ: FSD hợp lý với 10+ nhà phát triển và 20+ màn hình.

Feature-Sliced Design là gì?

Feature-Sliced Design (FSD) là một phương pháp kiến trúc ứng dụng frontend lần đầu tiên được đề xuất vào năm 2021 bởi cộng đồng feature-sliced.design. Ý tưởng cốt lõi của FSD là nhóm mã theo tính năng kinh doanh (slice), mỗi slice là một đơn vị tự cung cấp: chứa logic kinh doanh riêng, giao diện người dùng, tương tác API, mô hình dữ liệu và kiểm thử. Điều này phân biệt FSD với kiến trúc lớp cổ điển nơi mã được chia theo tiêu chí kỹ thuật (controller, service, repository).

Phương pháp này vay mượn các khái niệm từ Domain-Driven Design (DDD) và Bounded Context: mỗi tính năng của ứng dụng là một bounded context riêng biệt với ranh giới rõ ràng. Các thay đổi bên trong một tính năng không được làm hỏng các tính năng khác nếu chúng chỉ sử dụng API công khai của slice. Theo khảo sát State of Frontend 2024, FSD đứng thứ hai về mức độ phổ biến trong số các kiến trúc React (23%), chỉ sau cấu trúc Feature-based không chính thức (31%).

Trong phát triển di động, FSD thích ứng với đặc thù của mô-đun Android và framework iOS. Tại IT Sectr, chúng tôi sử dụng FSD cho các dự án có 10+ màn hình và 3+ nhóm — phương pháp này cho phép phát triển tính năng độc lập và giảm xung đột git xuống 40% so với kho lưu trữ đơn không có ranh giới slice.

Bảy lớp của FSD: cấu trúc và quy tắc import

FSD định nghĩa bảy lớp phân cấp, mỗi lớp chứa mã ở một mức trừu tượng nhất định. Quy tắc kiến trúc chính là các lớp chỉ có thể import mã từ các lớp bên dưới. Vi phạm quy tắc này (import lớp features vào entities) được coi là lỗi kiến trúc và bị chặn bởi linter.

LớpMục đíchImport
appKhởi tạo ứng dụng, nhà cung cấp, kiểu toàn cục, định tuyếnBất kỳ lớp nào
processesQuy trình kinh doanh kết hợp nhiều tính năng (onboarding, thanh toán)pages, features, entities, shared
pagesTổ hợp tính năng trên trang, định tuyến trangfeatures, entities, shared
featuresKịch bản người dùng: biểu mẫu đăng nhập, danh sách yêu thích, bộ lọc tìm kiếmentities, shared
entitiesThực thể kinh doanh: User, Product, Order, Cartshared
widgetsThành phần UI tổng hợp: Header, Sidebar, ArticleCardshared, entities
sharedTiện ích, UI-kit, client API, cấu hình — độc lập với logic kinh doanhChỉ thư viện bên ngoài

Ví dụ cấu trúc thư mục của dự án FSD:

Văn bản
src/
├── app/                    // Lớp ứng dụng
│   ├── providers/
│   ├── router/
│   └── styles/
├── pages/                   // Trang — tổ hợp tính năng
│   └── main/
├── features/                // Tính năng — kịch bản người dùng
│   ├── auth/                // Slice «Xác thực»
│   │   ├── ui/
│   │   ├── model/
│   │   └── api/
│   └── productList/         // Slice «Danh sách sản phẩm»
│       ├── ui/
│       └── model/
├── entities/                // Thực thể kinh doanh
│   ├── user/
│   └── product/
├── widgets/                 // Thành phần tổng hợp
│   └── header/
└── shared/                  // Tiện ích dùng chung và UI-kit
    └── ui/

Quy tắc «các lớp chỉ nhìn xuống dưới» là nền tảng của FSD. Nếu feature auth import entity user — điều đó đúng. Nếu entity user bắt đầu import feature auth — đó là phụ thuộc vòng tròn và vi phạm cô lập. Để đảm bảo quy tắc này, các plugin ESLint (eslint-plugin-fsd) hoặc linter tùy chỉnh của API công khai slice được sử dụng.

Slice: ranh giới miền kinh doanh

Slice — đơn vị nhóm chính trong FSD, tương ứng với một tính năng hoặc thực thể kinh doanh. Mỗi slice nằm trong một trong bảy lớp (features, entities, widgets, pages) và chứa bộ mã hoàn chỉnh để triển khai chức năng cụ thể: thành phần UI, mô hình dữ liệu, client API, hằng số và kiểm thử.

Ranh giới slice được xác định bởi miền kinh doanh: feature auth bao gồm mọi thứ liên quan đến xác thực (biểu mẫu đăng nhập, biểu mẫu đăng ký, đặt lại mật khẩu); entity user bao gồm mô hình User, UserRepository và tuần tự hóa. Ranh giới không được chồng chéo: nếu feature auth cần dữ liệu người dùng — nó import entity user thay vì sao chép logic. Trong phát triển di động, slice FSD thường tương ứng với mô-đun Gradle trong Android hoặc gói Swift trong iOS.

Các slice bị cô lập nghiêm ngặt: cấu trúc bên trong của một slice không thể nhìn thấy được đối với các slice khác. Để tương tác giữa các slice, API công khai được sử dụng — tệp index.ts/index.js chỉ xuất những gì được phép sử dụng bên ngoài. Mọi thứ khác là mô-đun riêng tư. Cách tiếp cận này ngăn chặn các phụ thuộc ngẫu nhiên và đơn giản hóa việc tái cấu trúc: thay đổi triển khai riêng tư của một slice không ảnh hưởng đến các slice khác.

Phân đoạn: UI, API, Model, Lib bên trong slice

Bên trong mỗi slice FSD, mã được tổ chức thêm theo phân đoạn — các danh mục kỹ thuật lặp lại trong tất cả các slice. Bộ phân đoạn tiêu chuẩn bao gồm ui (thành phần giao diện), model (logic kinh doanh, Store, Actions, Reducer), api (yêu cầu máy chủ, biến đổi), lib (tiện ích và trình trợ giúp) và config (cấu hình tính năng).

Phân đoạnNội dungVí dụ
ui/Thành phần React/Vue/SwiftUI, kiểu, StorybookLoginForm.tsx, login.module.css
model/Store, Reducer, Actions, kiểu, hợp đồngLoginStore.ts, authReducer.ts
api/Client HTTP, biến đổi, gọi RPCauthApi.ts, loginMutation.ts
lib/Hàm trợ giúp, trình xác thựcvalidateEmail.ts, formatPhone.ts
config/Hằng số, cấu hình tính năngauthConfig.ts, endpoints.ts

Phân đoạn là khuyến nghị, không phải quy tắc nghiêm ngặt. Nếu slice nhỏ, các phân đoạn có thể được hợp nhất. Đối với slice lớn (tính năng có 10+ tệp), phân đoạn là bắt buộc — nếu không có nó, cấu trúc bên trong nhanh chóng biến thành «rổ» gồm 50 tệp, nơi việc tìm thành phần cần thiết mất nhiều phút. Trong phát triển di động, các phân đoạn thường được thay thế bằng cấu trúc tệp theo loại: mỗi tính năng là một tệp Swift riêng biệt hoặc lớp Kotlin với các kiểu bên trong.

FSD trong phát triển di động: thích ứng với Android và iOS

Trong phát triển di động, FSD thích ứng với các đặc điểm nền tảng — cấu trúc mô-đun của Android (mô-đun Gradle) và Swift Package Manager. Thích ứng Android giả định rằng mỗi slice là một mô-đun Gradle riêng biệt với build.gradle riêng. Các mô-đun feature-auth, feature-profile, entity-user, shared-ui được cô lập với nhau ở cấp độ xây dựng: feature-auth không thể import feature-profile trừ khi được chỉ định trong dependencies.

Thích ứng iOS được xây dựng trên Swift Package Manager: mỗi slice là một gói Swift với API công khai. Trong các dự án TCA, slice feature.auth chứa Reducer, Store, View và client API riêng. Theo Swift Community Survey 2024, 28% dự án iOS với TCA sử dụng kiến trúc slice gần với FSD.

Vấn đề chính của việc thích ứng FSD trên di động là sự trùng lặp của lớp shared. Trong phát triển di động, các thành phần UI (shared/ui) thường phụ thuộc vào nền tảng (Android Views vs Jetpack Compose vs SwiftUI), đòi hỏi các mô-đun shared riêng biệt cho mỗi công nghệ. Trong FSD, lớp shared thường độc lập với nền tảng (tiện ích, cấu hình), trong khi UI-kit được chuyển sang mô-đun riêng biệt hoặc thư viện thành phần.

Ưu và nhược điểm của Feature-Sliced Design

Ưu điểm của FSD trở nên rõ rệt trong các dự án lớn với 10+ nhà phát triển. Mỗi nhà phát triển hoặc nhóm làm việc trên slice riêng của mình mà không chạm vào mã của người khác. Xung đột git giảm 40–60% (dữ liệu từ nghiên cứu điển hình của feature-sliced.design). Các tính năng mới được thêm vào mà không có rủi ro làm hỏng tính năng hiện có, miễn là chúng chỉ sử dụng API công khai của slice. Tái cấu trúc một tính năng không yêu cầu thay đổi ở các tính năng khác — chỉ cần viết lại ui/model/api bên trong một slice trong khi giữ nguyên API công khai.

Khía cạnhFSDFeature-based (không FSD)Kiến trúc lớp
Cô lập tính năngNghiêm ngặtTrung bìnhThấp
Phát triển song song10+ nhóm3–5 nhóm1–2 nhóm
Tái sử dụng giữa dự ánCó (gói slice)Chỉ qua copy-pasteQua mô-đun shared
Rào cản gia nhậpCaoThấpTrung bình
Cô lập Gradle (Android)Gốc (mô-đun)Gốc (mô-đun)Yếu

Nhược điểm của FSD — lồng ghép quá mức cho dự án nhỏ. Nếu ứng dụng gồm 3–5 màn hình, bảy lớp và phân đoạn bên trong mỗi slice tạo ra nhiều mã tổ chức hơn chính ứng dụng. Rào cản gia nhập cao: nhà phát triển mới mất 2–4 tuần để học phương pháp. Ngoài ra, FSD tương thích kém với tạo mẫu nhanh — tạo mẫu yêu cầu import xuyên lớp thường xuyên, bị cấm trong FSD và làm chậm các vòng lặp.

Khuyến nghị bắt đầu với cấu trúc Feature-based đơn giản hơn và chuyển sang FSD khi số lượng màn hình vượt quá 20 và nhóm vượt quá 5 nhà phát triển.

Câu hỏi thường gặp

Sự khác biệt giữa FSD và kiến trúc Feature-based là gì?

Kiến trúc Feature-based nhóm mã theo tính năng mà không có quy tắc import nghiêm ngặt — feature Auth có thể import feature Profile khác mà không bị hạn chế. FSD thêm phân cấp lớp và quy tắc «các lớp chỉ nhìn xuống dưới». Trong Feature-based, entity và feature có thể ở cùng cấp và import lẫn nhau; trong FSD, entity nằm dưới feature, và feature import entity, không phải ngược lại. Feature-based phù hợp cho dự án nhỏ, FSD cho dự án lớn.

Làm thế nào để kiểm thử một slice bị cô lập?

Cô lập slice đơn giản hóa kiểm thử đơn vị — mỗi slice được kiểm thử độc lập bằng cách mô phỏng các phụ thuộc của lớp bên dưới. Đối với feature auth, chỉ cần mô phỏng entity user. Kiểm thử tích hợp xác minh API công khai của slice. Trong Android, mô-đun Gradle của một tính năng chứa thư mục kiểm thử riêng với kiểm thử Reducer, client API và UI (qua Compose Test). Trong iOS, gói slice bao gồm kiểm thử của tất cả các phân đoạn.

Có thể sử dụng FSD với Jetpack Compose không?

Có, FSD kết hợp tốt với Jetpack Compose, đặc biệt trong các dự án Android đa mô-đun. Mỗi slice là một mô-đun Gradle riêng biệt với API công khai qua chỉ thị exported. Lớp features chứa các tính năng Composable (LoginFeature, ProductListFeature), lớp entities chứa các lớp dữ liệu và Repository, shared chứa UI-kit (MaterialTheme-wrapper, thành phần tùy chỉnh). FSD được khuyến nghị cho các dự án Compose lớn với 5+ nhà phát triển.

Lớp nào là bắt buộc và lớp nào là tùy chọn?

Các lớp bắt buộc là app, shared, entities và features. Các lớp còn lại (processes, pages, widgets) là tùy chọn và được thêm khi cần. Trong phát triển di động, lớp pages thường được hợp nhất với định tuyến điều hướng, và widgets được thay thế bằng shared/ui-kit. Các quy trình (processes) thường không được sử dụng trong các dự án di động — vai trò của chúng được đảm nhận bởi lớp miền hoặc logic kinh doanh trong ViewModel. Điều chính là tuân thủ quy tắc phân cấp import.

FSD liên quan thế nào đến Domain-Driven Design?

FSD vay mượn từ DDD các khái niệm Bounded ContextUbiquitous Language. Mỗi slice tương ứng với một bounded context — ranh giới trong đó các thuật ngữ có ý nghĩa rõ ràng. Bên trong slice, một ngôn ngữ thống nhất (ubiquitous language) được sử dụng, dễ hiểu cho cả nhà phát triển và nhà phân tích kinh doanh. Ví dụ, trong slice auth, các thuật ngữ «đăng nhập», «mật khẩu», «token» có cùng ý nghĩa cho tất cả thành viên nhóm, giảm hiểu lầm giữa nhà phân tích và nhà phát triển từ 30–50%.

Tổng kết

  • Feature-Sliced Design (FSD) — phương pháp kiến trúc mô-đun nhóm mã theo tính năng kinh doanh (slice), mỗi slice chứa UI, logic, API và kiểm thử.
  • Bảy lớp của FSD: app, processes, pages, features, entities, widgets, shared — với quy tắc import nghiêm ngặt từ trên xuống dưới.
  • Các slice bị cô lập qua API công khai — cấu trúc bên trong không thể nhìn thấy đối với slice khác, ngăn chặn phụ thuộc vòng tròn.
  • Các phân đoạn bên trong slice (ui, model, api, lib, config) tổ chức mã theo tiêu chí kỹ thuật, nhưng không bắt buộc cho slice nhỏ.
  • Trong phát triển di động, FSD thích ứng qua mô-đun Gradle (Android) và gói Swift (iOS), đảm bảo cô lập ở cấp độ xây dựng.
  • Ưu điểm chính — phát triển song song, cô lập tính năng, tái sử dụng giữa dự án.
  • Nhược điểm chính — dư thừa cho dự án nhỏ, rào cản gia nhập cao, không tương thích với tạo mẫu nhanh.

Chúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay

IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.

Thảo luận dự án

Đọc thêm