Cách hiện đại hoá hệ thống legacy mà không cần một cuộc viết lại kiểu big-bang đầy rủi ro
Mọi CTO rồi cũng sẽ tiếp nhận nó: một hệ thống cả thập kỷ tuổi vẫn đang vận hành doanh nghiệp nhưng làm chậm mọi ý tưởng mới đến mức lê thê. Nhà cung cấp ban đầu đã biến mất, những lập trình viên xây dựng nó đã chuyển công tác, và mỗi lần release là một lần cầu nguyện. Đến một lúc nào đó, một thành viên hội đồng quản trị đặt câu hỏi tự nhiên: "Sao chúng ta không viết lại luôn đi?" Chỉ một câu hỏi đó đã đốt cháy nhiều ngân sách IT hơn bất kỳ vụ hack hay sự cố nào. Các nghiên cứu của Standish Group và McKinsey đã nhiều lần cho thấy các dự án viết lại toàn bộ quy mô lớn thất bại hoặc vượt ngân sách nghiêm trọng trong hơn hai phần ba trường hợp. Kiểu thất bại luôn giống nhau. Đến tháng thứ mười tám, bạn đã tiêu hàng triệu, chưa đưa được gì lên production, và hệ thống cũ vẫn là cái đang trả lương cho nhân viên.
Huyền thoại về cuộc viết lại từ con số không
Cuộc viết lại kiểu big-bang hấp dẫn vì nó hứa hẹn một sự đoạn tuyệt sạch sẽ. Vứt bỏ mớ hỗn độn, thuê một đội mới, dùng công cụ hiện đại, và tái xuất sau một năm với một hệ thống mới đẹp đẽ. Trong thực tế, năm đó gần như không bao giờ kết thúc theo cách đã hoạch định. Hệ thống cũ không chỉ là code. Nó là mười năm quy tắc nghiệp vụ, các trường hợp biên, các bản vá pháp lý, và những cách chữa cháy âm thầm mà không ai ghi lại. Một cuộc viết lại bắt đầu từ một đặc tả mô tả những gì doanh nghiệp nghĩ phần mềm đang làm, chứ không phải những gì nó thực sự làm. Mỗi quy tắc bị quên mà được phát hiện trong quá trình migration đều làm phát sinh thêm hàng tuần. Trong khi đó hệ thống cũ vẫn tiếp tục tiến hoá, vì doanh nghiệp không thể dừng lại, và hệ thống mới ngày càng tụt lại phía sau trước khi kịp ship dù chỉ một tính năng.
Có một mô hình tư duy tốt hơn. Hãy coi hệ thống legacy ít giống một căn nhà bạn phá bỏ và giống hơn một cây cầu bạn thay từng làn một trong khi xe vẫn đang chạy qua. Mục tiêu không phải là đến trạng thái đích nhanh hơn. Mục tiêu là giữ cho doanh nghiệp vẫn vận hành mỗi tuần trong suốt cuộc hành trình.
Hiện đại hoá không phải một quyết định, mà là bốn
Trước khi chọn kế hoạch, hãy tách các quyết định thường bị gói chung và ra cùng lúc.
1. Hiện đại hoá code, hay hiện đại hoá kiến trúc? Viết lại cùng một monolith bằng một ngôn ngữ mới mang lại rất ít giá trị. Chia trách nhiệm thành các service có thể deploy và scale độc lập mới là nơi có đòn bẩy kinh doanh thực sự, nhưng chỉ khi các domain đã được hiểu rõ. Hãy làm phần kiến trúc trước phần code.
2. Rehost, refactor, hay replace? Không phải module nào cũng xứng đáng được đối xử như nhau. Một số ổn định và nhàm chán và chỉ nên được chuyển sang hạ tầng hiện đại ("rehost"). Một số khác chứa logic nghiệp vụ cần được bảo toàn và dọn dẹp tại chỗ ("refactor"). Một vài cái gắn chặt với quá khứ đến mức chỉ có một triển khai mới hoàn toàn mới là được ("replace"). Chọn theo từng module, không phải theo cả hệ thống, chính là điều biến một canh bạc mười tám tháng thành một chuỗi thắng lợi hai tháng một lần.
3. Dữ liệu trước, hay tính năng trước? Trong hầu hết các hệ thống legacy, schema database mới là legacy thực sự, chứ không phải phần code ngồi trên nó. Nếu kế hoạch hiện đại hoá của bạn không có một chiến lược dữ liệu rõ ràng (schema mới, đường migration, dual-write hoặc đồng bộ dựa trên event trong giai đoạn chuyển tiếp), nó sẽ sụp đổ ngay lần đầu tiên hai hệ thống bất đồng về nguồn sự thật.
4. Ai sở hữu quá trình chuyển tiếp? Một dự án hiện đại hoá không có một product owner chịu trách nhiệm duy nhất sẽ trôi dạt. Nó cần một người có thể nói không với các tính năng mới trong hệ thống legacy, bảo vệ roadmap, và làm trung gian cho cuộc căng thẳng hằng ngày giữa "giữ hệ thống cũ sống" và "đầu tư vào hệ thống mới".
Strangler pattern, giải thích bằng ngôn ngữ thông thường
Mô hình đáng tin cậy nhất cho việc hiện đại hoá trong thế giới thực là cái mà Martin Fowler đặt tên là strangler fig approach. Ý tưởng rất đơn giản. Đặt một lớp routing, thường là một API gateway hoặc một orchestrator nhẹ, ở phía trước hệ thống legacy. Mọi năng lực mới đều được xây dựng trong kiến trúc mới và phục vụ thông qua router đó. Các năng lực hiện có tiếp tục chạy trên backend legacy cho đến khi bạn chủ động migrate chúng, từng lát cắt có ranh giới rõ ràng một. Qua nhiều tháng hoặc nhiều quý, hệ thống mới từ từ mọc bao quanh hệ thống cũ và cuối cùng thay thế nó, mà không cần một cuối tuần cut-over kịch tính nào.
Tác động kinh doanh của mô hình này mới là điều quan trọng. Luôn có một hệ thống đang chạy trên production. Mỗi lát cắt được migrate mang lại giá trị tự thân, cho dù giá trị đó là một trang nhanh hơn, một report sạch hơn, hay một tích hợp mới, thay vì tích tụ trong một branch sẽ không ship trong cả năm. Nếu có gì đó hỏng, bạn rollback một lát cắt, không phải cả công ty. Và đội ngũ học được hành vi thực sự của hệ thống legacy theo từng bước, đó là cách trung thực duy nhất để học nó.
Một câu chuyện từ thực địa
Một nhà bán lẻ khu vực mà chúng tôi từng làm việc cùng đang vận hành toàn bộ quy trình đơn hàng và tồn kho trên một ERP mười lăm năm tuổi. Mỗi mùa cao điểm, hệ thống chậm lại đến mức lê thê, và mọi nỗ lực thêm một kênh e-commerce đều thất bại vì ERP không theo kịp. Hai nhà cung cấp trước đã đề xuất thay thế toàn bộ: mười hai tháng, bảy con số, không có tiến độ nhìn thấy được trước tháng thứ chín. Cả hai dự án đều bị huỷ.
Cách tiếp cận thay thế nhìn rất khác. Trong sáu tuần đầu tiên, đội ngũ đặt một lớp API mỏng ở phía trước ERP và chỉ chuyển đường đọc catalog sản phẩm sang một service hiện đại được hỗ trợ bởi một search index đúng nghĩa. Thời gian tải trang trên storefront giảm từ ba giây xuống dưới nửa giây. Chỉ riêng lát cắt đó không hề chạm vào đường ghi của ERP, nên rủi ro gần như bằng không, và nó đã tự trả tiền cho giai đoạn công việc tiếp theo bằng ba tháng tăng chuyển đổi. Tiếp nhận đơn hàng theo sau, rồi đến giữ chỗ tồn kho, rồi đến báo cáo. Mười tám tháng sau, ERP chỉ còn làm chưa đến một phần tư những gì trước đây nó từng làm, được lặng lẽ nghỉ hưu module theo module, không có lấy một ngày downtime.
Một roadmap thực dụng
Nếu hôm nay bạn đang nhìn chằm chằm vào hệ thống legacy của chính mình, trình tự giữ rủi ro thấp và đà tiến cao nhìn như sau:
- Vẽ bản đồ, đừng đoán. Dành hai đến bốn tuần để tạo ra một bảng kê trung thực về các module, tích hợp, luồng dữ liệu, và các quy trình nghiệp vụ phụ thuộc vào từng cái. Bạn không thể hiện đại hoá cái bạn không thể mô tả.
- Chọn một lát cắt có giá trị cao, rủi ro thấp. Một thứ đang làm doanh nghiệp đau đớn hằng ngày nhưng không chạm vào đường ghi crown-jewel. Một read model, một report, một view hướng khách hàng. Ship nó lên production phía sau lớp routing trong vòng một quý.
- Đo lường mọi thứ. Log, metric, và error budget. Bạn sắp chạy hai hệ thống song song, và bạn cần nhìn thấy mỗi hệ thống đang làm gì.
- Chỉ migrate đường ghi khi phía đọc đã nhàm chán. Một khi kiến trúc mới đã chứng minh nó có thể phục vụ traffic một cách an toàn, hãy bắt đầu chuyển các thao tác ghi với dual-write hoặc event replay để giữ cả hai hệ thống nhất quán trong giai đoạn chuyển tiếp.
- Nghỉ hưu một cách có chủ đích. Một module legacy chưa xong cho đến khi nó bị tắt hẳn. Đặt ngày shutdown rõ ràng cho từng lát cắt và giữ đúng ngày đó.
Bài học trung thực
Hiện đại hoá là một kỷ luật kinh doanh, không phải một dự án code. Những đội ngũ thành công coi nó là một khoản đầu tư nhiều năm với lợi nhuận theo từng quý, thay vì một lần release anh hùng duy nhất. Họ chống lại áp lực chính trị buộc phải hứa hẹn một cuộc viết lại từ con số không, và họ xây dựng uy tín bằng cách ship những chiến thắng nhỏ, nhìn thấy được ngay từ quý đầu tiên.
Nếu tổ chức của bạn đang ở đầu hành trình này, hoặc đã đang sống chung với một cuộc viết lại bị đình trệ, cách nhanh nhất để reset là mời một đội ngũ đã từng làm việc này. Tại MercTechs, chúng tôi giúp khách hàng SME và doanh nghiệp hiện đại hoá các nền tảng legacy theo từng bước, bảo vệ hoạt động kinh doanh trong giai đoạn chuyển tiếp, và mang lại giá trị đo lường được ở mỗi bước. Nếu điều đó nghe gần với thứ bạn cần hơn là một lời hứa mười hai tháng nữa, chúng tôi rất vui được trao đổi.