Công việc của bạn không chỉ là viết mã. Đó là đưa ra các quyết định. Bạn học hỏi từ chúng. Theo thời gian, bạn sẽ mắc ít sai lầm hơn. Cuối cùng, bạn sẽ dẫn dắt người khác vượt qua màn sương mù tương tự. Hành trình đó—từ việc viết logic đến việc chịu trách nhiệm về kết quả—là điều phân biệt giữa một người chỉ biết gõ cú pháp và một người xây dựng các hệ thống.
Bạn đưa ra những lựa chọn mỗi ngày. Có những lựa chọn cảm thấy thật tầm thường, như việc chọn màu sắc cho một nút bấm. Những lựa chọn khác lại tái cấu trúc toàn bộ sản phẩm. Bí quyết nằm ở việc nhận ra sớm rằng cả hai đều có liên quan đến nhau. Một quyết định nhỏ được đưa ra một cách cẩu thả có thể trở thành một rào cản lớn về sau, trong khi một lựa chọn khó khăn được đưa ra sớm thường trông như một sự thiên tài khi nhìn lại.
Phạm vi ảnh hưởng của những lựa chọn sớm
Khi mới bắt đầu, những sai lầm của bạn chỉ vang vọng trong một căn phòng nhỏ. Một commit lỗi làm hỏng một bản build cục bộ. Một hàm viết cẩu thả làm chậm một màn hình. Phạm vi ảnh hưởng vẫn còn hạn hẹp. Bạn tác động đến ít người và chi phí khắc phục rất thấp.
Nhưng khi bạn phát triển, dù là với tư cách một kỹ sư cá nhân hay một công ty, các quyết định của bạn sẽ tác động đến nhiều hệ thống hơn. Cùng một lựa chọn đó khi được thực hiện ở quy mô lớn có thể tiêu tốn hàng tuần trời. Đó là lý do tại sao bạn phải học cách đưa ra những lựa chọn có tính toán ngay từ bây giờ, trước khi cái giá phải trả trở nên quá đắt.
Hãy nghĩ về ba cái bẫy phổ biến:
Sử dụng một nền tảng mà các dependency của bạn không hỗ trợ có thể tiêu tốn hàng chục hoặc hàng trăm giờ kỹ thuật. Những giờ đó không chỉ là việc gõ phím. Đó là việc debug các vấn đề tương thích kỳ lạ, vá các thư viện trung gian (transitive libraries), và giải thích với các bên liên quan tại sao một tính năng đơn giản lại mất cả một quý.
Chuyển từ xác thực dựa trên session sang JWTs ở giai đoạn đầu của sản phẩm sẽ giúp tránh được việc phải viết lại toàn bộ một cách tốn kém sau này. Việc refactor logic đăng nhập khi bạn chỉ có hàng nghìn người dùng sẽ dễ dàng hơn nhiều so với khi bạn đã có hàng triệu người dùng và thời gian downtime gây thiệt hại về tiền bạc thực tế.
Việc ước tính thời gian gấp đôi dự đoán tốt nhất của bạn chỉ có tác dụng nếu bạn sử dụng khoảng thời gian dự phòng đó để bảo vệ chất lượng. Việc kéo dài lịch trình chỉ để lướt mạng xã hội là sự lãng phí. Việc kéo dài nó để bạn có thể viết test, xem xét các trường hợp biên (edge cases) và xác minh khả năng quan sát (observability) là một sự đầu tư.
Quy luật ở đây rất đơn giản: nợ kỹ thuật (technical debt) sẽ cộng dồn. Hãy trả nó khi số nợ gốc còn nhỏ.
Ngày chốt và ảo tưởng về sự kiểm soát
Deadline có ở khắp mọi nơi. Ngày phát hành, ngày demo, ngày đóng băng mã nguồn (code freeze). Trong các công ty lớn, chúng thường phục vụ mục đích tâm lý nhiều hơn là mục đích kỹ thuật. Chúng tạo ra cảm giác kiểm soát được sự phức tạp mà không ai thực sự hiểu hết được.
Tác dụng phụ là điều có thể dự đoán được. Khi ngày chốt đến gần, chất lượng sẽ giảm xuống. Các nhóm sẽ lược bỏ các bài kiểm tra, comment qua phần xử lý lỗi và tung ra những đoạn mã mà không ai muốn bảo trì. Deadline được hoàn thành. Lịch trình trông có vẻ gọn gàng. Nhưng sản phẩm thì tệ đi.
Điều này xảy ra vì các kỹ sư luôn yêu thích mã nguồn hoàn hảo và kiến trúc thanh lịch. Đó là bản chất của chúng ta. Nhưng một câu trả lời hoàn hảo không phải lúc nào cũng tồn tại. Lựa chọn đúng đắn là lựa chọn phù hợp với trạng thái hiện tại của nhóm bạn. Một startup ba người không cần những quy trình rườm rà như một nền tảng y tế được quản lý chặt chẽ. Bạn xây dựng dựa trên vị thế hiện tại của mình, chứ không phải dựa trên vị thế của một tổ chức kỹ thuật một nghìn người từ năm năm trước.
Khi sự tăng trưởng phá vỡ các quy tắc cũ
Đây là điều mà ban lãnh đạo thường bỏ lỡ. Khi một công ty phát triển, các deadline cũng phải phát triển theo. Các quy trình mở rộng. Nhân sự mới gia nhập và cần được đào tạo nhập môn (onboarding). Các nhiệm vụ nhân lên vì có nhiều sản phẩm hơn. Các yêu cầu tuân thủ chồng chất—từ đánh giá bảo mật nội bộ, kiểm toán bên ngoài đến kiểm tra quản trị dữ liệu. Diện tích bề mặt (surface area) tăng lên, nhưng vạch đích vẫn đứng yên một chỗ.
Việc sử dụng cùng một deadline cho khối lượng công việc lớn hơn không làm cho nhóm làm việc nhanh hơn. Nó chỉ khiến họ trở nên cẩu thả. Các bước quan trọng bị cắt bớt. Tài liệu biến mất. Việc ứng phó sự cố trở nên hoàn toàn mang tính đối phó. Những kỹ sư từng tung ra những dòng mã sạch sẽ giờ đây chỉ tung ra những "miếng băng cá nhân" (giải pháp tạm thời) vì lịch trình không thể thay đổi.
Nếu một công ty muốn tốc độ ở quy mô lớn, họ phải thêm các luồng công việc song song hoặc kéo dài thời gian thực hiện. Bạn không thể nén một backlog đang ngày càng lớn vào một sprint vốn đã cảm thấy quá tải từ ba đợt tuyển dụng trước.
Xây dựng khoảng dự phòng
Một thói quen sẽ giúp bạn giữ được sự tỉnh táo: hãy giả định rằng điều gì đó sẽ đi chệch hướng. Đó không phải là sự bi quan. Đó là sự thực tế.
Hệ thống có thể lỗi. Các API của bên thứ ba có thể bị trễ. Các yêu cầu thay đổi vì quản lý sản phẩm vừa nói chuyện với khách hàng ngày hôm qua. Khi bạn lập kế hoạch cho những trở ngại, deadline của bạn sẽ luôn thực tế. Bạn có được khả năng lựa chọn giữa tốc độ và chất lượng. Nếu không có khoảng dự phòng đó, lựa chọn sẽ được quyết định thay cho bạn trong mọi trường hợp. Bạn buộc phải chọn tốc độ, điều đó đồng nghĩa với việc bạn buộc phải hy sinh chất lượng.
Khoảng thời gian dự phòng đó cũng chính là nơi việc học hỏi diễn ra. Nếu mọi giờ làm việc đều được dành cho việc phát triển tính năng, sẽ không còn ai có không gian để cải thiện build pipeline, tái cấu trúc query layer, hay viết tài liệu cho API contract. Đội ngũ sẽ mãi bị mắc kẹt ở tốc độ phát triển hiện tại.
Thay thế lỗi này bằng lỗi khác
Chúng ta hiện đang lao vào một sự đánh đổi kỳ lạ. Chúng ta đang thay thế các lỗi do con người bằng các lỗi phần mềm không xác định (non-deterministic). Các mô hình ngôn ngữ lớn có thể tạo mã boilerplate, gợi ý các bài kiểm tra và soạn thảo tài liệu nhanh hơn bất kỳ kỹ sư junior nào. Nhưng chúng thực hiện điều đó một cách đầy tự tin, và chúng làm sai theo những cách mà
