BÀI VIẾT CÓ BỐI CẢNH

Kiến trúc góc thực tế cho cuộc sống thực

Chỉ số kiến ​​trúc Angular hoàn chỉnh hướng tới thực tiễn thực tế - vấn đề thực tế, mô hình thực tế, quyết định thực tế. Không có lý thuyết trống rỗng.

Kiến trúc góc thực tế cho cuộc sống thực
14 Apr

Kiến trúc góc thực tế cho cuộc sống thực

Chỉ số kiến ​​trúc Angular hoàn chỉnh hướng tới thực tiễn thực tế - vấn đề thực tế, mô hình thực tế, quyết định thực tế. Không có lý thuyết trống rỗng.

Hầu hết các khóa học kiến ​​trúc Angular đều dạy lý thuyết. Không phải cái này.

Tại đây, bạn học cách phát hiện các vấn đề thực sự, đưa ra quyết định phù hợp và xây dựng hệ thống có thể tồn tại khi nhóm phát triển, sản phẩm thay đổi và thời gian trôi qua.

Hai mươi mô-đun. Định hướng thực hành. Không có đệm.


INDEX — Kiến trúc góc thực tế cho cuộc sống thực

01 — Vấn đề kiến ​​trúc cơ sở
  • Logic nghiệp vụ trong các thành phần
  • Chúa phục vụ
  • Trạng thái trùng lặp hoặc rải rác
  • Khớp nối giữa các tính năng
  • Trách nhiệm hỗn hợp
  • Các thư mục trông gọn gàng nhưng không có tỷ lệ
  • Trừu tượng sớm
  • Kỹ thuật quá mức không cần thiết
  • Kiến trúc được thiết kế cho ngày hôm nay nhưng không dành cho tăng trưởng
  • Mã khó xóa, di chuyển hoặc tái cấu trúc
02 — Cấu trúc dự án thực tế
  • Dựa trên tính năng và dựa trên lớp
  • Khi nào nên sử dụng từng phương pháp
  • Cách phát hiện cấu trúc không có tỷ lệ
  • Cách chia theo miền hoặc ngữ cảnh giới hạn
  • Cách sắp xếp thư mục cho các đội thực sự
  • Quy ước đặt tên hữu ích
  • Cái gì nên cho và cái gì KHÔNG nên cho vào shared
  • Cách kiểm tra xem cấu trúc hiện tại của bạn có hỗ trợ ×10 không
03 — Kiến trúc thành phần
  • Thành phần quá lớn
  • Các thành phần có quá nhiều trách nhiệm
  • Thành phần thông minh và ngu ngốc
  • Vùng chứa/trình bày trong Angular hiện đại
  • Thành phần thành phần
  • Khi nào nên tái sử dụng và khi nào KHÔNG
  • Cách thiết kế API thành phần sạch
  • Đầu vào/Đầu ra so với tín hiệu so với dịch vụ
  • Các vấn đề điển hình trong mẫu
  • Cách phát hiện các thành phần khó bảo trì
04 — Trạng thái thực trong Angular
  • Những loại trạng thái tồn tại
  • Cách phát hiện việc lạm dụng trạng thái
  • Trạng thái cục bộ so với trạng thái chia sẻ so với toàn cầu so với trạng thái máy chủ
  • Tín hiệu so với RxJS
  • Vị trí trạng thái
  • Khi nào nên sử dụng trạng thái dịch vụ
  • Khi nào nên sử dụng kho tín hiệu
  • Khi nào nên sử dụng NgRx
  • Cách phát hiện tình trạng tập trung quá mức
  • Cách phát hiện sự hỗn loạn phân tán
  • Các lỗi điển hình về tác dụng phụ
  • Bình thường hóa trạng thái
  • Danh sách kiểm tra trạng thái
05 — Truyền thông và luồng dữ liệu
  • Dữ liệu giảm/sự kiện tăng
  • Giao tiếp chính xác giữa các thành phần
  • Giao tiếp không chính xác giữa các thành phần
  • Giao tiếp giữa các tính năng
  • Dấu hiệu khớp nối ẩn
  • Sử dụng dịch vụ để liên lạc
  • Sử dụng tín hiệu để liên lạc
  • Khi xe buýt sự kiện là một ý tưởng tồi
  • Cách kiểm tra địa chỉ phụ thuộc
  • Cách phát hiện luồng dữ liệu khó theo dõi
06 — Lớp dữ liệu và quyền truy cập API
  • Dịch vụ so với kho lưu trữ
  • DTO so với mô hình
  • Chuyển đổi và lập bản đồ
  • Đặt bộ điều hợp ở đâu
  • Các lỗi điển hình khi sử dụng API
  • Cách tách giao diện người dùng khỏi phần phụ trợ
  • Thử lại, lưu vào bộ nhớ đệm, phân trang
  • Cuộn vô hạn
  • REST và GraphQL từ kiến ​​trúc
  • Cách kiểm tra xem lớp dữ liệu của bạn sạch hay hỗn hợp
07 — Kiến trúc định tuyến
  • Thiết kế các tuyến đường có chủ ý
  • UX + SEO trong các tuyến đường
  • Những tuyến đường lười biếng
  • Vệ binh
  • Giải quyết
  • URL làm nguồn trạng thái
  • Liên kết sâu
  • Các tuyến đường đi kèm
  • Những tuyến đường được nghĩ ra một cách tồi tệ
  • Danh sách kiểm tra để xem xét điều hướng và khả năng mở rộng
08 — Kết xuất và chiến lược toàn cầu
  • SPA, SSR, SSG, ISR
  • Cách chọn theo ngữ cảnh
  • SEO so với sự phức tạp
  • Hiệu suất so với chi phí
  • Kiến trúc SSR góc
  • Hydrat hóa và tác động kiến ​​trúc
  • Khi nào KHÔNG sử dụng SSR
  • Cách kiểm tra xem ứng dụng có cần chiến lược hiển thị khác không
09 — Kiến trúc hiệu suất
  • Phát hiện thay đổi, OnPush, tín hiệu và hiệu suất
  • Lười tải thật
  • Chiến lược chia tách và bó mã
  • Bộ nhớ đệm
  • Cuộn và ghi nhớ ảo
  • Ngân sách hiệu suất
  • Cách phát hiện tắc nghẽn kiến ​​trúc
  • Những điều cần kiểm tra trước khi "tối ưu hóa"
  • Cách phân biệt vấn đề về mã và vấn đề kiến ​​​​trúc
10 — Kiến trúc thử nghiệm
  • Những gì cần kiểm tra và những gì không
  • Đơn vị vs tích hợp vs e2e
  • Khả năng kiểm tra theo thiết kế
  • Cách phát hiện mã khó kiểm tra
  • Chế giễu có ý nghĩa
  • Sự mong manh trong thử nghiệm và thử nghiệm quá mức
  • Kiểm tra hợp đồng frontend-backend
  • Danh sách kiểm tra để kiểm tra xem một kiến ​​trúc ủng hộ hay phá vỡ việc kiểm thử
11 — Nx và monorepo thực sự
  • Khi nào nó đáng và khi nào thì không
  • Ứng dụng so với lib, ranh giới, biểu đồ phụ thuộc
  • Thư viện chia sẻ được thực hiện tốt và kém
  • Bị ảnh hưởng, bộ nhớ đệm, quyền sở hữu mã
  • Cách mở rộng quy mô cho nhiều nhóm
  • Chống mẫu Monorepo
  • Xem lại danh sách kiểm tra
12 — Microfrontends và liên kết mô-đun
  • Khi có và khi không
  • Vấn đề thực sự họ giải quyết là gì?
  • Chi phí ẩn
  • Máy chủ và điều khiển từ xa, lập phiên bản, liên lạc giữa các MFE
  • Triển khai độc lập và độ phức tạp của tổ chức
  • Danh sách kiểm tra để quyết định xem nó có thanh toán hay không
13 — Hệ thống thiết kế hữu ích
  • Họ giải quyết vấn đề gì và khi nào thì không cần đến vấn đề nghiêm trọng?
  • Thư viện thành phần, mã thông báo, chủ đề, biến thể
  • Tính nhất quán và tính linh hoạt
  • Sách truyện, đồng bộ thiết kế-phát triển
  • Lỗi điển hình
  • Cách kiểm tra xem hệ thống giao diện người dùng của bạn có đang mở rộng hoặc gặp sự cố không
14 — Bảo mật giao diện người dùng
  • XSS, CSRF, vệ sinh
  • Kiến trúc xác thực: JWT, mã thông báo làm mới
  • Bảo vệ và truy cập dựa trên vai trò
  • Vấn đề bảo mật trong SSR
  • Danh sách kiểm tra sửa đổi thực tế
15 — Khả năng quan sát và bảo trì
  • Ghi nhật ký, theo dõi lỗi, Sentry, số liệu
  • Theo dõi khái niệm, cờ tính năng, thử nghiệm A/B
  • Cách phát hiện điểm mù
  • Cách kiểm tra xem ứng dụng có thể hoạt động được trong quá trình sản xuất hay không
16 — DevEx và tư duy nền tảng
  • Kinh nghiệm và công cụ dành cho nhà phát triển
  • CI/CD, máy phát điện, sơ đồ, tự động hóa
  • Cách phát hiện ma sát không cần thiết
  • Cách thiết kế kiến ​​trúc cho nhóm chứ không chỉ mã
17 — Sự đánh đổi và ra quyết định
  • Làm thế nào để biện minh cho các quyết định
  • Chi phí so với lợi ích, độ phức tạp so với khả năng mở rộng, tốc độ so với khả năng bảo trì
  • Xây dựng so với mua
  • Cách viết ADR
  • Cách bảo vệ quyết định trong cuộc phỏng vấn hoặc công việc thực tế
18 — Kiến trúc góc cạnh phản mẫu
  • Kỹ thuật quá mức, các lớp vô dụng, trừu tượng hóa sớm
  • shared trạng thái toàn cầu được thiết kế kém, không cần thiết
  • Phụ thuộc chéo, khớp nối im lặng
  • Mô-đun hóa kém, bỏ qua các số liệu thực
  • danh sách kiểm tra cờ đỏ
19 — Kiểm tra thực tế các ứng dụng Angular
  • Cách đánh giá một ứng dụng hiện có
  • Những gì cần xem đầu tiên
  • Dấu hiệu nào cho thấy nợ nghiêm trọng
  • Cách ưu tiên các vấn đề
  • Cái gì cần sửa trước và cái gì chưa chạm tới
  • Cách thực hiện đánh giá kiến ​​trúc hữu ích
20 — Trường hợp thực tế và đào tạo
  • Kiểm toán thương mại điện tử
  • Kiểm tra bảng điều khiển SaaS
  • Kiểm toán hậu cần doanh nghiệp
  • Kiểm tra ứng dụng công khai với SEO
  • Thiết kế ứng dụng từ đầu
  • Thiết kế lại ứng dụng hỗn loạn
  • Câu hỏi phỏng vấn
  • Bài tập phát hiện, quyết định và cải tiến

Mô-đun 0 - Cơ sở hệ thống

Điểm 0 không phải là mô-đun nội dung. Đó là cách nhìn mà bạn sẽ sử dụng trong suốt lộ trình.

Trước khi nói về các vấn đề cụ thể trong Angular, bạn cần trả lời một câu hỏi:

Làm thế nào để bạn nhìn vào một ứng dụng mà bạn không biết và quyết định xem nó tốt hay xấu?

Có bốn kỹ năng cơ bản cho điều đó.


1. Phân tích ứng dụng mà không cần chạm vào mã

Lần đọc đầu tiên của một ứng dụng không có trong trình chỉnh sửa. Nó ở trong cấu trúc. Trước khi mở một tệp, bạn có thể trích xuất thông tin:

  • Các thư mục được gọi là gì? Những cái tên có nói lên công việc của họ không?
  • Có thư mục shared nặng hơn mọi thứ khác không?
  • Cấu trúc có bao nhiêu cấp độ lồng nhau?
  • Các mô-đun hoặc tính năng có tên miền hoặc tên kỹ thuật không?
  • Dịch vụ ở đâu? Lỏng lẻo hoặc trong các tính năng?

Điều này đã cho bạn biết rất nhiều điều về việc liệu người tạo ra ứng dụng có suy nghĩ về mặt kinh doanh hay về mặt kỹ thuật hay không.


2. Review kiến ​​trúc một cách thực tế

Review không phải là đọc code từ trên xuống dưới. Đó là đặt câu hỏi với tiêu chí:

  • Logic kinh doanh tồn tại ở đâu?
  • Ai biết được ở mỗi lớp có gì?
  • Bạn phải thay đổi bao nhiêu trang web để thêm tính năng mới?
  • Có sự phụ thuộc nào đi sai hướng không?

Một kiến ​​trúc sư cấp cao không bắt đầu với thành phần phức tạp nhất. Bắt đầu với các điểm rủi ro cao nhất: dịch vụ dùng chung, trạng thái toàn cầu và lớp truy cập dữ liệu.


3. Phát hiện vấn đề trước khi lập trình

Hầu hết thiệt hại về kiến ​​trúc xảy ra trong những quyết định ban đầu dường như không liên quan:

  • "Hiện tại tôi đang đưa dịch vụ này lên một dịch vụ chia sẻ"
  • "Thành phần cha mẹ xử lý trạng thái này, sau đó chúng ta di chuyển nó"
  • "Chúng tôi sử dụng NgRx cho mọi thứ nên nó rất nhất quán"

Những quyết định này có hậu quả thực sự nhiều tháng sau đó. Tiêu chí kiến ​​trúc là phải biết mỗi quyết định mua cái gì và nó đang gánh chịu khoản nợ gì.


4. Chuyển lý thuyết thành danh sách kiểm tra thực tế

Mỗi khái niệm mà chúng ta sẽ thấy trong lộ trình này - các thành phần thông minh/câm, vị trí trạng thái, dịch vụ thần thánh, v.v. - phải kết thúc bằng một câu hỏi mà bạn có thể tự hỏi mình khi xem xét mã thực:

  • Thành phần này có biết dữ liệu đến từ đâu không?
  • Dịch vụ này có nhiều lý do để thay đổi?
  • Trạng thái này tồn tại ở hai nơi khác nhau phải không?

Nếu bạn không thể biến một khái niệm thành một câu hỏi ôn tập thì bạn vẫn chưa tiếp thu được nó.


Mô-đun 1 - Cách phân tích ứng dụng Angular mà không cần chạm vào mã

Quá trình xem xét kiến ​​trúc đầu tiên diễn ra trước khi mở trình chỉnh sửa. Chỉ cần từ cấu trúc thư mục và tên tệp, bạn đã có thể trích xuất các tín hiệu rõ ràng về chất lượng. Đây là điều mà một kiến ​​trúc sư cấp cao sẽ làm trong 10 phút đầu tiên với một ứng dụng không xác định.

Tại sao nó lại quan trọng?

  • Nếu bạn mất nhiều thời gian để phát hiện các vấn đề về kiến ​​trúc thì chi phí sửa chữa chúng sẽ tăng theo cấp số nhân.
  • Cấu trúc được thiết kế kém ngay từ ngày đầu tiên đã trở thành món nợ kỹ thuật khiến cả nhóm bị cản trở nhiều tháng sau đó.
  • Phát triển khả năng phán đoán trực quan nhanh chóng cho phép bạn đưa ra quyết định tốt hơn trước khi viết một dòng mã.

Bước 1 - Đọc cấu trúc thư mục dưới dạng bản đồ

Cấu trúc thư mục là quyết định kiến ​​trúc rõ ràng đầu tiên. Nó cho bạn biết nhóm đã tổ chức thế giới tinh thần của họ như thế nào: họ suy nghĩ về mặt công nghệ hay kinh doanh?

Tính năng là gì?

Một tính năng là một chức năng kinh doanh hoàn chỉnh. Không phải là một loại tập tin. Không phải là một lớp kỹ thuật.

Hãy nghĩ về một ứng dụng thương mại điện tử. Các tính năng là:

  • Danh mục sản phẩm
  • Giỏ hàng
  • Quá trình thanh toán
  • Hồ sơ người dùng
  • Quản lý đơn hàng

Mỗi trong số đó là một phần kinh doanh có ý nghĩa riêng của nó. Người dùng nhập, duyệt danh mục, thêm vào giỏ hàng, kiểm tra. Đó là những tính năng.

Mô hình 1 — Tổ chức theo lớp kỹ thuật (có vấn đề ở quy mô lớn)

Đây là điều mà hầu hết mọi người đều làm khi bắt đầu vì nó có vẻ gọn gàng:

src/app/
  components/
    product-card.component.ts
    product-list.component.ts
    cart-item.component.ts
    checkout-form.component.ts
    user-profile.component.ts
  services/
    product.service.ts
    cart.service.ts
    checkout.service.ts
    user.service.ts
  models/
    product.model.ts
    cart.model.ts
    user.model.ts

Vấn đề thực sự: bạn phải sửa đổi quy trình thanh toán. Để hiểu những gì liên quan, bạn điều hướng giữa ba thư mục khác nhau — bạn tìm thành phần trong components/, dịch vụ trong services/, mô hình trong models/. Nếu có một đường ống thanh toán cụ thể thì đường ống đó nằm trong pipes/ được trộn lẫn với các đường ống từ các tính năng khác.

Để thay đổi một tính năng, bạn điều hướng qua toàn bộ ứng dụng. Đó là sự ghép nối theo cấu trúc. Khi nhóm phát triển, hai người làm việc trên các tính năng khác nhau liên tục chạm vào cùng một thư mục → xung đột trong git, khó biết ai sở hữu cái gì.

Mô hình 2 — Tổ chức theo tính năng (tỷ lệ nào)

src/app/
  features/
    catalog/
      components/
        product-card.component.ts
        product-list.component.ts
      services/
        product.service.ts
      models/
        product.model.ts
      catalog.routes.ts
    cart/
      components/
        cart-item.component.ts
        cart-summary.component.ts
      services/
        cart.service.ts
      cart.routes.ts
    checkout/
      components/
        checkout-form.component.ts
        order-confirmation.component.ts
      services/
        checkout.service.ts
      checkout.routes.ts
  shared/
  core/

Tại sao tính năng này hoạt động: Khi bạn nhấn vào thanh toán, mọi thứ trong thanh toán đều ở cùng nhau. Một nhà phát triển mới biết chính xác nơi cần tìm. Một người có thể sở hữu toàn bộ tính năng. Bạn có thể xóa toàn bộ đối tượng địa lý bằng cách chỉ xóa thư mục của đối tượng đó. Xung đột Git giữa các tính năng khác nhau gần như biến mất hoàn toàn.

Quy tắc chung: nếu bạn xóa một đối tượng địa lý, bạn có thể xóa toàn bộ thư mục của đối tượng đó mà không cần chạm vào bất cứ thứ gì khác không? Nếu câu trả lời là có thì tính năng này được cách ly tốt. Nếu bạn phải tìm kiếm các phần trong ứng dụng thì không phải vậy.

Bước 2 - Đọc tên

Tên là tài liệu. Một cái tên xấu che giấu mục đích và tăng thêm gánh nặng nhận thức cho mỗi người đọc mã.

shared/ — nội dung nên chứa và nội dung không nên chứa

shared/ dành cho những thứ có nhiều tính năng sử dụng và KHÔNG có logic kinh doanh riêng.

Đúng trong shared/:

shared/
  components/
    button/
    modal/
    spinner/
    avatar/
  pipes/
    date-format.pipe.ts
    truncate.pipe.ts
  directives/
    click-outside.directive.ts
  validators/
    email-validator.ts

Chúng là những phần giao diện người dùng có thể tái sử dụng hoặc các tiện ích thuần túy. Họ không biết gì về kinh doanh. ButtonComponent không biết đó là nút thanh toán hay nút hồ sơ người dùng. Anh ta chỉ biết làm một cái nút.

Không chính xác trong shared/:

shared/
  services/
    cart.service.ts           ← lógica de negocio aquí
    user-auth.service.ts      ← pertenece a auth/core
    product-filter.service.ts ← pertenece a catalog
    report-generator.service.ts ← pertenece a reporting

Khi bạn thấy các dịch vụ có logic nghiệp vụ bên trong shared/, điều đó có nghĩa là ai đó không biết đặt chúng ở đâu và đặt chúng ở đó. Theo thời gian shared/ trở thành ứng dụng tổng hợp.

core/ — nó là gì và không phải là gì

core/ dành cho cơ sở hạ tầng đơn lẻ cần toàn bộ ứng dụng một lần.

Đúng trong core/:

core/
  services/
    auth.service.ts
    logger.service.ts
    error-handler.service.ts
  interceptors/
    auth.interceptor.ts
    error.interceptor.ts
  guards/
    auth.guard.ts
  models/
    user-session.model.ts

Không chính xác trong core/:

core/
  components/
    dashboard.component.ts  ← eso es una feature
    home.component.ts       ← igual
  services/
    product.service.ts      ← pertenece a catalog
    report-generator.service.ts ← pertenece a reporting

Đây là những thứ được khởi tạo một lần và ảnh hưởng đến toàn bộ ứng dụng. Trình chặn chặn xác thực chặn tất cả yêu cầu HTTP cho toàn bộ ứng dụng, đó là lý do tại sao nó tồn tại trong core/.

Tên mơ hồ - cờ đỏ

Một cái tên mơ hồ là một quyết định bị trì hoãn. Khi ai đó tạo data.service.ts, họ chưa quyết định dịch vụ đó đang nói về dữ liệu nào.

những gì bạn thấy Nó có thể có nghĩa là gì
shared/ rất lớn Tất cả mọi thứ không phù hợp ở bất cứ nơi nào khác. Nó trở thành một túi hỗn hợp.
common/ Giống như shared/ nhưng có tên tệ hơn. Không có tiêu chí về những gì đi vào.
utils/ với các dịch vụ Logic kinh doanh được ngụy trang dưới dạng tiện ích. Cờ đỏ nghiêm trọng.
helpers/ Giống như utils/. Cái tên không nói lên điều gì về trách nhiệm.
components/ trong thư mục gốc Không có tổ chức theo tên miền. Tất cả các thành phần với nhau.
core/ với 40 tệp Cốt lõi được xác định kém. shared/ đã được sử dụng làm giá trị thứ hai.
app.service.ts Một dịch vụ thần đang chờ đợi để phát triển. Tín hiệu báo động tối đa.
data.service.ts Dữ liệu về cái gì? Trách nhiệm vô thời hạn từ tên.
helper.service.ts Nó kết thúc là một dịch vụ với các phương pháp không liên quan.
main.component.ts "chính" là gì? Tên chung chung che giấu trách nhiệm thực sự.

Quy tắc đặt tên: Nếu tên tệp không cho bạn biết chính xác chức năng của nó thì tệp đó có thể thực hiện quá nhiều chức năng hoặc bị định vị sai.

Ví dụ cụ thể về những cái tên mơ hồ và những gì chúng che giấu:

  • utils/format.ts với 800 dòng: kết hợp định dạng ngày + xác thực biểu mẫu + chuyển đổi API.
  • helper.service.ts: cuối cùng trở thành một dịch vụ thần thánh với những phương pháp không liên quan.
  • app.service.ts: một dịch vụ được gọi là toàn bộ ứng dụng có trách nhiệm đối với toàn bộ ứng dụng.

Bước 3 - Đếm và đo mà không cần mở tập tin

Trước khi đọc mã, bạn có thể thực hiện những quan sát này trực tiếp từ cấu trúc:

Kích thước thành phần như một dấu hiệu

Dấu hiệu Nó chỉ ra điều gì?
+300-400 dòng trong một thành phần Bạn hầu như luôn làm quá nhiều việc. Nó không phải là một quy tắc tuyệt đối nhưng nó đáng để nghiên cứu.
+10 đầu vào và đầu ra API quá phức tạp. Ứng viên được chia thành nhiều thành phần.
Cuộc gọi HTTP trực tiếp trong thành phần Kết hợp trình bày với truy cập dữ liệu. Lớp dịch vụ bị thiếu.
1-2 thành phần cho mỗi tính năng Có lẽ họ đang làm quá nhiều. Thiếu sự chia rẽ nội bộ.
+20 nhà cung cấp toàn cầu Quá nhiều trạng thái và logic tập trung. Không phải mọi thứ cần phải mang tính toàn cầu.

Dịch vụ toàn cầu — mối nguy hiểm của providedIn: 'root'

Dịch vụ toàn cầu có nghĩa là bất kỳ thành phần nào của bất kỳ tính năng nào cũng có thể đưa vào và sử dụng nó. Điều đó tạo ra sự phụ thuộc vô hình giữa các tính năng lẽ ra phải độc lập.

// Servicio que DEBERÍA ser local a la feature de catalog:
@Injectable({ providedIn: 'root' })  // ← señal de problema
export class ProductFilterService { ... }

// Ahora cualquier componente de cualquier feature puede usarlo.
// Si catalog cambia su lógica de filtrado, puede romper
// algo en una feature aparentemente no relacionada.

Bước 4 — app.module.ts hoặc app.config.ts: nội dung cần tìm

Trong các ứng dụng có mô-đun (Angular < 17 hoặc cũ)

@NgModule({
  imports: [
    BrowserModule,
    HttpClientModule,
    RouterModule,
    AuthModule,       // ← bien, infraestructura singleton

    ProductModule,    // ← señal de problema
    CartModule,       // ← señal de problema
    CheckoutModule,   // ← señal de problema
    UserModule,       // ← señal de problema
    DashboardModule,  // ← señal de problema
    // Si hay 15+ módulos de features aquí,
    // el lazy loading no está funcionando.
  ],
  providers: [
    ProductService,   // ← si hay 20+ providers aquí,
    CartService,      // hay demasiada centralización
    UserService,
    AuthService,
  ]
})

Các mô-đun tính năng nên được tải từng phần (theo yêu cầu), không được nhập trực tiếp vào mô-đun gốc. Nếu tất cả đều ở đây, chúng đều được tải khi khởi động ngay cả khi người dùng không bao giờ cần đến chúng.

Trong các ứng dụng độc lập (Angular 17+)

// app.config.ts
export const appConfig: ApplicationConfig = {
  providers: [
    provideRouter(routes, withLazyLoading()),   // ← correcto
    provideHttpClient(withInterceptors([authInterceptor])),
    provideAnimations(),

    ProductService,   // ← esto NO debería estar aquí
    CartService,      // ← pertenece a la feature de cart
  ]
}

Quy tắc cấu hình chung: Cấu hình chung chỉ được có cơ sở hạ tầng ảnh hưởng đến toàn bộ ứng dụng: bộ định tuyến có tải chậm, HttpClient với các bộ chặn toàn cầu, hoạt ảnh, dịch vụ đơn lẻ cơ sở hạ tầng (auth, logger, trình xử lý lỗi). Nếu bạn thấy các dịch vụ tính năng trong cấu hình chung thì có nghĩa là ai đó đang đăng ký mọi thứ trên toàn cầu để thuận tiện chứ không cần thiết.

Danh sách kiểm tra hoàn chỉnh - Lần đọc đầu tiên của ứng dụng Angular

Kết cấu

  • Cấu trúc được tổ chức theo tính năng (miền nghiệp vụ) hay theo lớp kỹ thuật?
  • Tôi có thể xóa toàn bộ đối tượng địa lý bằng cách chỉ xóa thư mục của nó mà không chạm vào bất kỳ thứ gì khác không?
  • Các đối tượng địa lý có tên miền doanh nghiệp (checkout, catalog) hoặc tên kỹ thuật (list, form, detail) không?
  • Có thư mục nào có tên mơ hồ: utils, helpers, common, misc, data không?

shared/core/

  • shared/ chỉ chứa các thành phần và tiện ích giao diện người dùng mà không có logic nghiệp vụ phải không?
  • core/ chỉ chứa cơ sở hạ tầng đơn lẻ (thiết bị chặn, bảo vệ, dịch vụ xác thực) phải không?
  • Có dịch vụ nào có logic nghiệp vụ trong shared/ không?
  • core/ có các thành phần tính năng hoặc dịch vụ miền không?

Dịch vụ và nhà cung cấp

  • Các dịch vụ kinh doanh nằm trong phạm vi tính năng của bạn hay lỏng lẻo trên toàn cầu?
  • Có hơn 20 nhà cung cấp toàn cầu không?
  • Mô-đun gốc hoặc app.config.ts có nhập mô-đun tính năng trực tiếp (không lười biếng) không?
  • Có dịch vụ nào có providedIn: 'root' dành riêng cho một đối tượng địa lý không?

Tên

  • Tên tập tin có nói chính xác chức năng của chúng không?
  • Có tệp nào có thể áp dụng tên cho bất kỳ phần nào của ứng dụng không?
  • Có tệp có tên app.service.ts, data.service.ts hoặc helper.service.ts không?
  • shared/ có nặng hơn bất kỳ tính năng riêng lẻ nào không?

Bài tập

Tìm kiếm bất kỳ dự án Angular công khai nào trên GitHub - đó có thể là dự án của riêng bạn hoặc dự án nguồn mở. Không cần mở bất kỳ tệp nào, chỉ cần nhìn vào cấu trúc và tên thư mục:

  1. Bạn sử dụng mô hình tổ chức nào: tính năng hay tầng kỹ thuật?
  2. Cái tên nào khiến bạn nghi ngờ hay nghi ngờ?
  3. Bạn nghi ngờ logic nghiệp vụ ở đâu?
  4. Bạn nghĩ thư mục nào có nhiều trách nhiệm nhất?
  5. Bạn có thể xóa một tính năng mà không cần chạm vào bất cứ thứ gì khác không?

Chia sẻ những gì bạn quan sát được trong buổi học và chúng ta cùng nhau xem xét nó như một kiến ​​trúc sư cấp cao sẽ làm.


Nhắc: phân tích dự án của bạn với 4 điểm

Sao chép lời nhắc này và sử dụng nó với bất kỳ AI nào (ChatGPT, Claude, Copilot) chuyển nó vào cây thư mục trong dự án của bạn:


Phân tích kiến ​​trúc dự án áp dụng 4 điểm này của Trụ cột 1 và tạo báo cáo.

ĐIỂM 1 - Cấu trúc thư mục

Phân tích apps/libs/ rồi trả lời:

  • Tổ chức theo tính năng (lĩnh vực kinh doanh) hay theo tầng kỹ thuật?
  • Bạn có thể xóa toàn bộ đối tượng địa lý bằng cách chỉ xóa thư mục của nó không?
  • Các tính năng có tên miền (checkout, catalog) hoặc tên kỹ thuật (list, form, detail) không?
  • Có thư mục nào có tên mơ hồ: utils, helpers, common, misc, data không?
  • Hiển thị cây thư mục thực tế bạn đã tìm thấy.

ĐIỂM 2 - Tên tệp và thư mục

Tìm kiếm toàn bộ dự án và danh sách:

  • Các tập tin có tên mơ hồ: data.service.ts, helper.service.ts, app.service.ts, main.component.ts, utils có dịch vụ bên trong.
  • Dịch vụ có logic nghiệp vụ trong phạm vi shared/.
  • Các thành phần hoặc dịch vụ miền trong core/.
  • shared/ có nặng hơn bất kỳ tính năng riêng lẻ nào không? Số tập tin.

ĐIỂM 3 — Dịch vụ toàn cầu

Tìm kiếm toàn bộ dự án:

  • Tất cả các dịch vụ có providedIn: 'root' — liệt kê chúng là những dịch vụ nào và liệu chúng có nên cục bộ cho một đối tượng địa lý hay không.
  • Đếm tổng cộng có bao nhiêu nhà cung cấp toàn cầu.
  • Xác định các dịch vụ kinh doanh đã đăng ký trên toàn cầu khi chúng phải nằm trong tính năng của bạn.
  • Tìm kiếm các dịch vụ trong libs/services/ rõ ràng thuộc về một miền cụ thể.

ĐIỂM 4 — Cấu hình chung (app.config.ts hoặc app.module.ts)

Tìm tệp cấu hình gốc của từng ứng dụng và phân tích:

  • Những gì được đăng ký trên toàn cầu mà không nên?
  • Các mô-đun tính năng được tải theo chế độ tải chậm hay được nhập trực tiếp?
  • Có dịch vụ kinh doanh nào trong cấu hình toàn cầu không?
  • Tổng cộng có bao nhiêu nhà cung cấp được đăng ký trên toàn cầu?

ĐỊNH DẠNG BÁO CÁO

Đối với mỗi điểm, hãy sử dụng cấu trúc chính xác này:

✅ Có gì hay

(danh sách cụ thể với các ví dụ mã thực)

⚠️ Dấu hiệu cần kiểm tra

(danh sách cụ thể với đường dẫn tệp và tại sao nó là một dấu hiệu)

❌ Giải quyết vấn đề

(danh sách cụ thể với đường dẫn tệp, vấn đề và tác động thực tế)

Cuối cùng nó bao gồm:

Tóm tắt điều hành

Một bảng có 4 điểm, biểu tượng cảm xúc trạng thái (❌ ⚠️ ❌) và dòng kết luận cho mỗi điểm.

Ưu tiên các bước tiếp theo

Danh sách tối đa 5 hành động cụ thể được sắp xếp theo tác động, kèm theo đường dẫn chính xác của file hoặc thư mục cần chạm vào.

Hãy trực tiếp. Đừng giải thích đặc điểm hay lý thuyết là gì. Chỉ cần phân tích dự án cụ thể này và đưa ra những phát hiện thực sự.

Góc, AI và hệ thống được giải thích từ các quyết định thực tế. Mỗi bài viết cung cấp cho bạn một cái gì đó bạn có thể áp dụng trực tiếp.

SEO cho Angular không màu mè: cần sửa gì trước khi thêm SSR