Bỏ qua tới nội dung
Kiên

Từ viết code sang ra quyết định

· 4 phút đọc

Cái gì thật sự thay đổi khi công việc chuyển từ "viết tính năng" sang dẫn một team sáu kỹ sư và ôm một release train đa repo. Đơn vị công việc trở thành một quyết định thay vì một cái diff, review thôi không còn là thứ chen ngang, và cách nhanh nhất để mất một tuần hoá ra là trả lời miệng một câu hỏi thay vì viết câu trả lời ra.

  • leadership
  • code review
  • quy trình
  • multi-repo
Mục lục
  1. Đơn vị công việc giờ là một quyết định
  2. Review thôi không còn là thứ chen ngang
  3. Cuộc nói chuyện rẻ nhất diễn ra trước khi branch tồn tại
  4. Phải có người giữ thứ tự merge
  5. Cái gì khó lên
  6. Cái mình đếm được

Suốt phần lớn thời gian đi làm, câu trả lời thật thà cho "hôm nay làm được gì" là một cái diff. Có hôm đẹp, có hôm nát, nhưng luôn là một thứ chỉ vào được: số dòng thay đổi, test xanh, một merge request mang tên mình.

Rồi công việc đổi — một team sáu kỹ sư, và một release train chạy trên cả một cụm repo thay vì một repo. Không ai đưa cho mình tài liệu nào giải thích cái gì thật sự đã khác đi. Nên đây là cái tài liệu đó, viết muộn.

Đơn vị công việc giờ là một quyết định

Một cái diff có hạ tầng đỡ nó. Nó được review, nó chạy qua CI, nó merge hoặc không. Một quyết định thì không có gì cả. Module supplier mới đi theo pattern offer nào trong hai pattern. Thay đổi schema này ra trước consumer hay ra cùng. Con bug này có đáng giữ cả chuyến tàu lại không. Không có pipeline nào đỏ lên khi một quyết định sai — phản hồi đến sau vài tuần, đội lốt, thường là dưới dạng bug của một người khác.

Sản phẩm một ngày của mình giờ hay là một đoạn văn: đây là cái ta làm, đây là lý do, đây là cái ta chủ động không làm. Mình mất một thời gian dài đến xấu hổ mới chấp nhận được rằng viết cái đoạn văn đó cho tử tế chính là công việc, chứ không phải phần rườm rà bám quanh công việc.

Review thôi không còn là thứ chen ngang

Hồi còn là senior engineer, review là khoản thuế chắn giữa mình và cái branch của mình. Mình làm nó có trách nhiệm, và âm thầm khó chịu với nó.

Khi có sáu người cùng merge, review không phải thuế đánh lên công việc nữa. Nó là công việc. Nó là chỗ duy nhất mà sáu quyết định cục bộ của sáu người hội tụ thành thiết kế của một hệ thống, thay vì sáu thiết kế đứng cạnh nhau. Mỗi lần mình đọc lướt một cái review để quay về "việc của mình", mình không tiết kiệm được thời gian — mình chỉ hoãn lại một cú lệch mà sau này kéo về đắt hơn nhiều. Mình thôi không nhét review vào mấy khe trống trong lịch nữa, mà coi nó là khối việc hạng nhất của ngày. Thứ không sống sót qua cú chuyển đổi này là cái ý nghĩ rằng trạng thái mặc định trên lịch của mình là "đang viết code".

Cuộc nói chuyện rẻ nhất diễn ra trước khi branch tồn tại

Cái nếp mình giờ ép chính mình và cả team theo: việc nào còn độ tự do thiết kế thì nói chuyện trước khi tạo branch, không phải sau khi merge request đã mở. Một cuộc nói chuyện trước branch tốn đúng một cuộc nói chuyện. Cũng cuộc nói chuyện đó sau khi code đã tồn tại thì tốn một lần viết lại — cộng thêm cái phần không ai tính giá, là phải nói với một người rằng thứ họ làm xong là thứ sai. Cuộc nói chuyện đó lần nào cũng tệ hơn, và code thì biết cãi: một khi nó đã tồn tại, nó tự bào chữa cho nó.

Phải có người giữ thứ tự merge

Release train là phần không có hình chiếu nào trong công việc một-repo. Đơn vị release là cả cụm repo, không phải từng repo. Một lần go-live có thể trải trên mười một repo, và khi đã trải như thế, thứ tự merge là một phần của thiết kế: contract phía backend phải vào trước những consumer đọc nó. Chạy ngược lại là mở ra một khung thời gian mà consumer hỏi xin một cái shape chưa tồn tại — và trong domain này, thứ đó hiếm khi crash. Nó tính ra một con số sai, một cách đầy tự tin.

Cái thứ tự đó không tự giữ được nó. Phải có một người biết nó, viết nó ra cùng với tính năng, và kiểm nó đúng ngày. Đó không phải kỹ năng mình có hồi còn là engineer, vì hồi đó mình chưa từng cần tới — repo của mình là cả thế giới, còn thứ tự merge của người khác chỉ là chuyện thời tiết.

Cái gì khó lên

Trước hết là làm nút cổ chai. Quyết định xếp hàng chờ mình y như request xếp hàng trước một service thiếu tài nguyên, và khác với service, mình không scale ngang được. Có những ngày, việc hữu ích nhất mình làm là trả lời cái hàng đợi đó thật dứt khoát, theo đúng thứ tự.

Thứ hai là cơn ngứa tay muốn tự sửa luôn. Mình thường sửa được trong một tiếng. Mỗi lần làm thế, cái một tiếng đó rẻ mà bài học thì đắt: cái module đó thành của mình vĩnh viễn, và người kỹ sư đáng ra phải own nó thì học được rằng bài khó là để đẩy lên trên, không phải để giải. Ngồi im nhìn người khác debug là một kỹ năng mình vẫn còn kém.

Thứ ba — và cái này tốn nhất — là trả lời thay vì viết ra. Trả lời một câu hỏi trong chat thì câu trả lời bốc hơi ngay lúc gửi đi; câu hỏi quay lại, từ một người khác, vào tháng sau. Viết câu trả lời ra một lần thì câu hỏi chết hẳn. Cách nhanh nhất để mất một tuần là trả lời miệng cùng một câu hỏi, hết lần này đến lần khác, trong lúc tự nhủ rằng mình đang nhiệt tình giúp đỡ.

Cái mình đếm được

Mình sẽ không đặt một con số năng suất nào ở đây. Mình chưa từng đo nó, và cái site này không đăng con số nào mình không tự dựng lại được.

Cái mình chỉ vào được là những thứ tồn tại vì công việc đã đổi: những bộ runbook mà trước kia là các câu trả lời mình phát ra từng cái một; những flow được viết thành tài liệu cho các hệ thống trước đó chỉ sống trong lịch sử commit; một approval engine mà hành vi của nó giờ nằm trên giấy dưới dạng mười một mã lỗi được tài liệu hoá, bảy sơ đồ flow, và mười tám user story — viết ngược từ code ra, vì code đã ship trước khi story tồn tại, và người kế tiếp không đáng phải ngồi dịch ngược thứ mình vốn đã biết.

Không cái nào trong đó là một cái diff. Toàn bộ chúng giờ là công việc.

Bài liên quan

· 4 phút đọc

Tám gateway service, một nhánh tích hợp chung, và một cú đẩy lên production luôn là hành động có chủ đích, gom theo đợt, với một con người đứng ở nút bấm. "Đơn vị release là cả cụm, không phải từng repo" trông như thế nào khi nó phải chạy hàng tuần, thay vì nằm yên trong danh sách nguyên tắc.

  • release engineering
  • multi-repo
  • quy trình
  • CI/CD

· 5 phút đọc

Một danh sách những thứ là contract mà nhìn không giống contract — một định danh client cầm giữa hai lần gọi, một mã lỗi đã ghi thành tài liệu, và ba nghĩa khác nhau của thiếu field, field rỗng và field null. Vì sao thêm thì gần như miễn phí còn bỏ đi là một đợt release phối hợp qua những repo mình không deploy, và giữ cho mọi thứ chạy được thì tốn thật những gì.

  • API design
  • tương thích ngược
  • multi-repo
  • release