FDE PulseViệc làm FDE đang mở 632Mới trong 7 ngày 57Công ty đang tuyển 95Nhận làm từ xa 24%Lương trung vị (Mỹ) $205kTuyển nhiều nhất Databricks 114
EN

Tờ báo của nghề Forward Deployed Engineer

Bách khoa

Vòng system design của FDE: thiết kế quanh hệ thống legacy của khách, không xây lại từ đầu

Tin tuyển FDE nói rõ bạn sẽ làm việc trong những quyết định người khác đã đưa ra, nên một kiến trúc vẽ trên giấy trắng là kiến trúc cho một khách hàng không tồn tại.

Ảnh thật một phòng máy chủ on-prem với các tủ rack và dây cáp, gợi hệ thống legacy của khách hàng; hoặc các kỹ sư đang phác kiến trúc trên bảng trắng.
Ảnh: Moses Cursor Ssebunya / CC0
Chia sẻLinkedInFacebookX

Tóm tắt nhanh

  • Tin tuyển FDE như của Praxent yêu cầu tích hợp với hệ thống được giao, kể cả core legacy, nên hãy coi ràng buộc của khách là đề bài.
  • Trình tự an toàn: tìm điểm nối, kết nối outbound, lấy sự kiện qua CDC, dịch qua ACL, rồi dùng façade chuyển dần từng chức năng.
  • Đừng đề xuất viết lại toàn bộ, kế hoạch mà Martin Fowler cho rằng phần lớn đều thất bại, và đừng để schema cũ lọt vào service mới.
Sơ đồ kiến trúc chia làm hai vùng bởi firewall. Bên trái, trong mạng của khách: hệ thống hợp đồng không được sửa code, nối xuống database; change data capture (CDC) đưa sự kiện từ database sang một agent chỉ kết nối ra ngoài. Mũi tên vượt firewall sang phía FDE, vào anti-corruption layer (khối được tô màu nhấn) dịch schema cũ, rồi đi lên dịch vụ phân loại hồ sơ bồi thường.
Với đề bài công ty bảo hiểm: không sửa code, được đọc database, firewall không mở chiều vào. Dữ liệu ra qua CDC và một agent chỉ kết nối ra ngoài, rồi đi qua anti-corruption layer trước khi tới service mới.

Thử hình dung đề bài: khách hàng là một công ty bảo hiểm có hệ thống quản lý hợp đồng chạy on-prem nhiều năm nay, đội vận hành không cho ai sửa. Họ muốn một service phân loại hồ sơ bồi thường. Bạn có 45 phút và một tấm bảng trắng.

Phản xạ của nhiều kỹ sư là vẽ ngay một kiến trúc sạch: API gateway, microservice, database mới, rồi đề xuất “dần dần chuyển hết sang”. Ở vòng SWE thông thường, câu trả lời đó có thể đủ. Với một vị trí FDE, nó bỏ qua đúng phần việc mà tin tuyển dụng mô tả.

Tin tuyển FDE của Praxent ghi rõ yêu cầu tích hợp gọn gàng với những hệ thống bạn thực sự được giao, kể cả các core legacy, và nói thẳng rằng bạn làm việc bên trong những quyết định do người khác đưa ra.

Vì thế, cách chuẩn bị hợp lý là giả định người phỏng vấn muốn xem bạn thiết kế quanh ràng buộc ra sao, chứ không phải bạn xóa ràng buộc giỏi đến đâu.

Vì sao “viết lại cho sạch” là câu trả lời sai?

Martin Fowler cảnh báo về kế hoạch viết lại một lần cho xong: nghe đơn giản, nhưng theo quan sát của ông, phần lớn những kế hoạch như vậy kết thúc bằng thất bại. Phương án ông ủng hộ là hiện đại hóa từng phần, và nó có tên: Strangler Fig.

Theo tài liệu kiến trúc Azure của Microsoft, Strangler Fig thay dần từng phần chức năng của hệ thống cũ bằng ứng dụng và service mới. Trong lúc đó, hệ thống cũ vẫn chạy những chức năng chưa được chuyển. Cơ chế cốt lõi là một façade, tức một lớp proxy, đứng chặn trước back end cũ và quyết định mỗi request đi vào ứng dụng cũ hay service mới.

Nhưng pattern nào cũng có điều kiện. Microsoft ghi rõ Strangler Fig có thể không phù hợp nếu bạn không truy cập được mã nguồn hệ thống cũ, đồng thời cũng không có điểm tích hợp nào khác được phép thay đổi, chẳng hạn database. Đó chính là câu hỏi đầu tiên bạn nên đặt ra trong buổi phỏng vấn.

Bắt đầu bằng câu hỏi, đừng vội vẽ

Với đề bảo hiểm ở trên, năm phút đầu nên dành để hỏi. Code của hệ thống hợp đồng có sửa được không? Nếu không, có được đọc database của nó không? Mạng nội bộ cho phép kết nối theo chiều nào? Ai sẽ duyệt quyền truy cập, và thường mất bao lâu?

Câu cuối không thừa. Appsierra, một công ty cung cấp FDE, cho rằng cấp quyền truy cập, review bảo mật và phê duyệt của khách thường mất nhiều thời gian hơn cả việc tìm được kỹ sư.

Đó là nhận định của nhà cung cấp chứ không phải dữ liệu độc lập, nhưng nếu bạn đưa thời gian review vào kế hoạch, bạn cho thấy mình hiểu dự án thực sự có thể bị chậm ở đâu.

Giả sử người phỏng vấn trả lời: không được sửa code, được đọc database, firewall không mở chiều vào. Ba câu trả lời đó quyết định gần hết kiến trúc.

Ví dụ mẫu: dựng đường dữ liệu từng lớp một

Bắt đầu từ mạng. Khi firewall không mở chiều vào, bạn đặt một agent trong mạng của khách và cho nó chỉ kết nối ra ngoài. Palantir Foundry từng làm đúng như vậy: agent trong mạng khách liên tục poll Foundry qua kết nối HTTPS một chiều đi ra để nhận việc.

Tài liệu của họ hiện đánh dấu kiến trúc agent worker này là legacy, nhưng nguyên lý không mở cổng chiều vào vẫn đáng học theo khi bạn vẽ phương án.

Tiếp theo là cách lấy sự kiện. Vì không được sửa code, bạn không thể chèn lệnh “gửi event khi có hồ sơ mới” vào ứng dụng. Với những thành phần không sửa được, Microsoft gợi ý lấy sự kiện từ chính database, ví dụ dùng change data capture đọc transaction log, để không phải đụng tới code ứng dụng.

Sự kiện đã ra được tới nơi, nhưng nó vẫn mang hình dạng của hệ thống cũ. Microsoft cảnh báo hệ thống legacy thường có schema rối và API lỗi thời. Nếu không có lớp cô lập, thiết kế mới sẽ dần nhiễm ngữ nghĩa của hệ thống cũ. Lớp cô lập đó gọi là anti-corruption layer (ACL).

Thử hình dung bảng hồ sơ cũ có các cột viết tắt, mã trạng thái dạng số và số tiền lưu dưới dạng số nguyên nhân 100. ACL là nơi duy nhất biết những quy ước đó:

# ACL: dịch bản ghi legacy sang mô hình của service mới
STATUS_MAP = {"01": "submitted", "02": "in_review", "09": "closed"}

def to_claim(row: dict) -> Claim:
    return Claim(
        claim_id=row["CLM_NO"].strip(),
        policy_id=row["POL_REF"].strip(),
        status=STATUS_MAP.get(row["ST_CD"], "unknown"),
        amount=Decimal(row["AMT_X100"]) / 100,
    )

Service phân loại chỉ làm việc với Claim và không bao giờ đọc ST_CD. Đây cũng là phần việc nặng ngoài đời: Appsierra mô tả công việc tích hợp của FDE là đối chiếu schema, cách đặt tên và những chỗ thiếu dữ liệu thật của khách với những gì sản phẩm cần.

Cuối cùng là façade. Ngày đầu, chỉ một đường dẫn được chuyển sang service mới, mọi thứ khác vẫn đi vào hệ thống cũ:

MIGRATED = {"/claims/triage"}

def route(path: str) -> str:
    return NEW_SERVICE if path in MIGRATED else LEGACY

Mỗi lần chuyển thêm một chức năng chỉ là thêm một dòng vào MIGRATED, và lùi lại cũng dễ như vậy.

Mỗi lớp đều có giá, hãy nói ra trước

Hãy tự nêu chi phí trước khi bị hỏi. Microsoft ghi rõ ACL làm tăng độ trễ cho các lời gọi giữa hai hệ thống. Nếu bước phân loại phải trả kết quả ngay cho nhân viên đang nghe điện thoại, bạn phải tính phần độ trễ đó vào ngân sách.

Nếu hệ thống cũ chạy theo batch hoặc chậm, bạn có thêm một lựa chọn: ACL dạng event-driven qua một hàng đợi như Service Bus, Event Grid hay Event Hubs.

Theo Microsoft, cách này tách phần hệ thống mới khỏi giới hạn throughput của hệ thống cũ. Cái giá là dữ liệu đến chậm hơn và chỉ nhất quán sau một khoảng trễ (eventual consistency), và bạn nên nói rõ điều đó.

Câu trả lời greenfield

  • Vẽ kiến trúc mới trước khi hỏi
  • Đề xuất viết lại toàn bộ hệ thống
  • Giả định có thể mở firewall chiều vào
  • Đọc thẳng schema cũ trong service mới

Câu trả lời của FDE

  • Hỏi điểm nối được phép chạm trước
  • Dùng façade chuyển dần từng chức năng
  • Đặt agent chỉ kết nối ra ngoài
  • Dịch mọi thứ qua ACL và nêu độ trễ nó thêm vào

Những cái bẫy nên tránh

Cái bẫy đầu tiên là áp Strangler Fig mà không kiểm tra điều kiện. Nếu khách không cho chạm vào code lẫn database, façade không có chỗ để bám, và bạn phải nói thẳng điều đó thay vì cố nhét pattern vào.

Một cái bẫy khác là để ACL chỉ có tên trên sơ đồ. Nếu một service khác ngoài ACL vẫn đọc mã trạng thái cũ, ngữ nghĩa legacy đã lọt vào hệ thống mới. Và đừng quên con người: không ai duyệt quyền truy cập thì kiến trúc đẹp mấy cũng nằm yên trên giấy.

Về sự nghiệp, khi đọc tin tuyển dụng, những cụm như “legacy cores”, “on-prem” hay “existing systems” là gợi ý tốt về nội dung vòng system design. Trong CV, đừng chỉ liệt kê công nghệ. Hãy viết theo kiểu “đưa dữ liệu từ hệ thống X qua CDC, không cần sửa code phía khách”, vì đó đúng là loại tích hợp mà các tin tuyển FDE mô tả.

Bài tập tuần này rất đơn giản: lấy đề công ty bảo hiểm ở trên, đổi một câu trả lời thành “không được đọc database”, rồi giải lại. Nếu bạn vẫn giải thích được vì sao kiến trúc phải đổi, bạn đã luyện đúng kỹ năng mà tin tuyển FDE đang tìm.

Bài này có hữu ích không?

Dùng cùng trợ lý AIHỏi Claude ↗Hỏi ChatGPT ↗
6 nguồn
Đọc tiếp trên lộ trình · Chặng 2: Kỹ thuật rộngPython chậm ở đâu: chọn thread, process hay asyncio khi xử lý dữ liệu của kháchThêm thread vào một script chậm có khi chẳng nhanh hơn chút nào. Trước khi chọn công cụ, bạn phải biết chương trình đang chờ hay đang tính.