Kiến trúc phân lớp (Layered Architecture)
← Về MOC · Liên quan: Môi trường đích (Target Environments)
1. Ý tưởng cốt lõi
Theo wiki Source Code Organization: VS Code gồm một core (lõi) được chia lớp và mô-đun hóa, và có thể mở rộng bằng extension. Extension chạy trong một tiến trình riêng gọi là extension host (xem Extension Host & RPC).
Core nằm ở src/vs/ và được chia thành các layer (lớp) có thứ tự. Quy tắc vàng: mỗi lớp chỉ được import từ các lớp nằm BÊN DƯỚI nó.
flowchart BT base["1. base<br/>tiện ích chung, UI cơ bản"] platform["2. platform<br/>DI + service dùng chung"] editor["3. editor<br/>Monaco Editor core"] workbench["4. workbench<br/>toàn bộ giao diện VS Code"] code["5. code<br/>entry desktop (Electron)"] server["6. server<br/>entry remote server"] sessions["7. sessions<br/>Agents Window"] base --> platform --> editor --> workbench --> sessions platform --> code platform --> server
2. Chi tiết từng lớp
2.1 base – nền tảng
- Tiện ích tổng quát và khối UI cơ bản, không phụ thuộc service nào.
- Ví dụ:
base/common/strings.ts,arrays.ts,async.ts,event.ts(sự kiện),lifecycle.ts(Disposable),observable.ts,uri.ts;base/browser/ui/(list, tree, scrollbar…). - Xem cơ chế quan trọng: Disposable & Event, Observables (lập trình phản ứng).
2.2 platform – dịch vụ nền
- Định nghĩa cơ chế service injection (tiêm dịch vụ) và các service cơ bản dùng chung giữa
workbenchvàcode. - Không được chứa code riêng của editor hay workbench.
- Ví dụ thư mục:
platform/instantiation(DI),platform/files(đọc/ghi file),platform/configuration(cài đặt),platform/storage,platform/log,platform/commands,platform/contextkey,platform/keybinding,platform/registry… - Xem: Dependency Injection & Services.
2.3 editor – Monaco Editor core
- Là lõi trình soạn thảo văn bản, không được phụ thuộc
nodehayelectron-*để có thể chạy trên web. - Bản Monaco Editor đầy đủ (gói npm dùng trong web app khác) được đóng gói ở repo riêng
microsoft/monaco-editor. - Cấu trúc con:
editor/common,editor/browser: phần lõi không thể thiếu.editor/contrib: 59 tính năng editor (find, folding, suggest, hover, multicursor, stickyScroll…), dùng chung cho VS Code và standalone editor.editor/standalone: chỉ dành cho bản standalone; không ai được phụ thuộc vào thư mục này.- Tính năng editor chỉ có trong VS Code thì đặt ở
workbench/contrib/codeEditor.
2.4 workbench – bàn làm việc
- Chứa Monaco Editor, notebook, custom editor và khung giao diện gồm Explorer, Status Bar, Menu Bar…
- Dùng Electron cho bản desktop, dùng browser API cho bản web.
- Cấu trúc con:
| Thư mục | Vai trò |
|---|---|
workbench/{common,browser,electron-browser} | Lõi workbench, càng tối giản càng tốt (layout, parts) |
workbench/browser/parts/ | Các “part” giao diện: activitybar, sidebar, editor, panel, statusbar, titlebar, auxiliarybar… |
workbench/services/ | Service lõi của workbench (95 nhóm) – không chứa service chỉ dùng trong một contrib |
workbench/contrib/ | Feature contribution (tính năng đóng góp): search, debug, git/scm, terminal, chat… (101 nhóm). Phần lớn code mới nên nằm ở đây |
workbench/api/ | Hiện thực Extension API (vscode.d.ts) – cả phía extension host và phía workbench |
2.5 code – điểm vào desktop
- “Khâu nối” mọi thứ cho ứng dụng desktop: file main của Electron, shared process, CLI.
- Ví dụ:
code/electron-main/main.ts,code/electron-main/app.ts. Xem Luồng khởi động (Startup flow).
2.6 server – điểm vào server từ xa
- Dùng cho Remote Development (SSH, Container, WSL, Codespaces): phần server chạy ở máy từ xa.
2.7 sessions – Agents Window (lớp mới)
- Cửa sổ dành cho quy trình làm việc với AI agent. Được import từ
workbenchtrở xuống, nhưngworkbenchkhông bao giờ được import từsessions. - Xem: Agents Window & AI trong repo.
3. Cơ chế bảo vệ quy tắc phân lớp
Quy tắc không chỉ nằm trên giấy, mà được kiểm tra tự động:
| Công cụ | Vị trí | Tác dụng |
|---|---|---|
ESLint rule local/code-layering | .eslint-plugin-local/code-layering.ts | Báo lỗi khi import sai lớp/môi trường |
ESLint rule local/code-import-patterns | .eslint-plugin-local/code-import-patterns.ts | Quy định mẫu import được phép theo từng thư mục |
npm run valid-layers-check | build/checker/layersChecker.ts | Kiểm tra phân lớp ở mức toàn dự án |
Ví dụ vi phạm (minh họa)
// File: src/vs/base/common/myUtil.ts (lớp base)
// ❌ SAI: base không được import từ platform (lớp cao hơn)
import { IFileService } from '../../platform/files/common/files.js';
// File: src/vs/workbench/contrib/myFeature/browser/myFeature.ts
// ✅ ĐÚNG: workbench được import từ platform và base
import { IFileService } from '../../../../platform/files/common/files.js';
import { URI } from '../../../../base/common/uri.js';Vì sao import có đuôi
.jsdù file là.ts?Code được biên dịch sang ESM (ECMAScript Modules – chuẩn module của JavaScript). Trong ESM, đường dẫn import phải trỏ đúng file sau biên dịch (
.js). TypeScript hiểu và ánh xạ ngược về file.ts.
4. Vì sao phải phân lớp?
- Tái sử dụng: lớp
editorchạy độc lập được → tách ra thành Monaco Editor dùng trên web. - Đa nền tảng: tách code phụ thuộc Node/Electron giúp cùng một code chạy cả desktop lẫn web.
- Dễ bảo trì: tránh phụ thuộc vòng (cyclic dependency). Repo còn có lệnh
npm run check-cyclic-dependencies.
Liên kết
- Lớp chia theo chiều dọc, còn môi trường đích chia theo chiều ngang: Môi trường đích (Target Environments)
- Thuật ngữ: Thuật ngữ (Glossary)