Môi trường đích (Target Environments)

← Về MOC · Trước: Kiến trúc phân lớp (Layers)

1. Khái niệm

Nếu layer chia code theo chiều dọc (cấp độ trừu tượng), thì target environment (môi trường đích) chia code theo chiều ngang: code đó cần API nào để chạy.

Bên trong mỗi lớp, code được đặt vào thư mục con mang tên môi trường. Ví dụ: src/vs/platform/files/ có common/, browser/, node/, electron-main/…

2. Bảng quy tắc

Thư mụcAPI được dùngĐược import từ
commonChỉ JavaScript cơ bản – chạy được ở mọi môi trường—
browserWeb API (DOM – mô hình đối tượng tài liệu của trang web)common
nodeNode.js API (fs, child_process…)common
electron-browserBrowser API + một tập nhỏ API giao tiếp với Electron main (qua src/vs/base/parts/sandbox/electron-browser/globals.ts)common, browser, electron-browser
electron-utilityAPI của Electron utility process (tiến trình tiện ích)common, node
electron-mainAPI của Electron main process (tiến trình chính)common, node, electron-utility
flowchart BT
  common --> browser
  common --> node
  browser --> eb[electron-browser]
  common --> eu[electron-utility]
  node --> eu
  eu --> em[electron-main]
  node --> em

Điểm dễ nhầm

electron-browser không được dùng Node.js trực tiếp. Cửa sổ giao diện (renderer) của VS Code chạy ở chế độ sandbox (hộp cát – bị cô lập về bảo mật), nên muốn đọc file phải đi qua service/IPC tới tiến trình khác. Xem Kiến trúc đa tiến trình (Multi-process).

3. Ví dụ thực tế: một service có nhiều bản hiện thực

Một service thường có interface đặt ở common, còn implementation (bản hiện thực) đặt ở môi trường phù hợp:

src/vs/workbench/services/textfile/
├── common/textfiles.ts                         ← interface ITextFileService
├── browser/browserTextFileService.ts           ← bản cho web
└── electron-browser/nativeTextFileService.ts   ← bản cho desktop

Entry point desktop chọn bản desktop:

// trích src/vs/workbench/workbench.desktop.main.ts
import './services/textfile/electron-browser/nativeTextFileService.js';
import './services/dialogs/electron-browser/fileDialogService.js';

Như vậy các thành phần khác chỉ cần phụ thuộc vào interface ITextFileService (ở common) và không cần biết đang chạy desktop hay web. Cơ chế “đưa đúng bản hiện thực vào” chính là Dependency Injection.

4. Ba entry point của workbench

FileDùng cho
src/vs/workbench/workbench.common.main.tsPhụ thuộc dùng chung (≈ 264 dòng import)
src/vs/workbench/workbench.desktop.main.tsChỉ desktop
src/vs/workbench/workbench.web.main.tsChỉ web

Chỉ code được import từ entry point mới được nạp

Nếu bạn tạo file mới mà không file nào (trực tiếp hoặc gián tiếp) import nó từ các entry point trên, file đó sẽ không chạy. Thường bạn thêm import vào file .contribution.ts của tính năng (xem Contribution Model & Registry).

Nguyên tắc chính thức: ưu tiên viết code chạy được ở cả hai môi trường; code chỉ chạy một nơi là ngoại lệ. Nếu một service chỉ có bản desktop, code web dùng service đó sẽ lỗi.

5. Vận dụng (liên hệ thực tế)

Cách chia này giống việc tách interface và implementation khi một phần mềm phải hỗ trợ nhiều hệ quản trị CSDL: phần nghiệp vụ gọi một interface chung, còn tầng truy cập dữ liệu có bản riêng cho SQL Server và PostgreSQL. Thư mục common đóng vai interface; browser/node/electron-* đóng vai các bản hiện thực theo nền tảng.

Liên kết