Skip to content

Instantly share code, notes, and snippets.

@longtth
Last active August 17, 2021 15:54
Show Gist options
  • Save longtth/bf7629c2147f1893bb75680a58141f12 to your computer and use it in GitHub Desktop.
Save longtth/bf7629c2147f1893bb75680a58141f12 to your computer and use it in GitHub Desktop.
2021-08-17-things-you-should-never-do-part-1
title date category tags
Vài thứ "không được thử dù chỉ 1 lần", phần 1
2021-08-17 21:19 +0700
translate
software-engineering

Vài thứ "không được thử dù chỉ 1 lần", phần 1

có thể đọc bài có màu mè ở đây: https://gist.github.com/longtth/bf7629c2147f1893bb75680a58141f12

bài gốc của Joel Spolsky, đồng sáng lập của StackOverflow

Link gốc: https://www.joelonsoftware.com/2000/04/06/things-you-should-never-do-part-i/

bài dịch này được dịch trong lúc có 1 tấn task đang đè, dành tặng bạn Hoàng nhân dịp bạn đòi rã hết cái app 20k LOC ra làm lại từ đầu.

Bài này bác Joel viết cho lớp người làm công ty bán phần mềm để kiếm sống, to hơn anh em mình nhiều nhưng từ trong đó chúng ta cũng học được nhiều điều quý giá

Tóm tắt cho mấy bạn lười đọc:

  • đừng vội vã shift delete toàn bộ code cũ
  • déll có lý do gì để tin là cái đống source mới code lại sẽ chạy mượt hơn và ít bug đống code đang có, lỡ nó tệ hơn thì sao?
  • bình tĩnh và tối ưu từng phần nếu kiến trúc của app cũ thực sự như loằn
  • tìm đúng cái hàm chạy chậm và sửa đúng cái hàm đó là đủ
  • code cũ đặt tên như loằn, vậy thì đơn giản là Ctrl R-R trong Visual Studio hoặc vài macro trong mấy editor khác là xong.

Netscape 6.0 release bản beta vào 2000/11/14, không có bản 5.0. Và phiên bản chính thức gần nhất của nó là 4.0, được release khoảng 3 năm trước, 3 năm là một khoảng thời gian dài kinh dị trong thế giới internet. Trong 3 năm này, Netscape ngồi một bên, nhìn thị trường sụt giảm trong vô vọng.

Tui hơi hà khắc khi chi trích họ vì phải chờ quá lâu để có bản cập nhật nhỉ!? Họ đâu cố tình đâu, phải không?

Ờm, thực ra là có, bọn họ release chậm như vậy bằng cách chọn thực thi 1 quyết định chiến lược tồi tệ nhất đối với 1 công ty phần mềm:

Họ đập hết đi làm lại từ đầu.

Netscape không phải là công ty đầu tiên đạp vào cái hố này. Borland cũng thất bại tương tự khi mua Arago và cố gắng biến nó thành dBase for Windows, một dự án tồi tệ mà tốn quá nhiều thời gian để hoàn thành đến nỗi Microsoft Access cắn xong hết thị phần, còn gói mang về, không để lại gì cho họ, rồi họ nhảy hố một lần nữa khi nỗ lực viết lại từ đầu Quattro Pro và làm mọi người "ngạc nhiên chưa" với số lượng tính năng ít ỏi (và bug) mà nó có. Microsoft cũng không ngoại lệ, họ cũng nhảy hố một lần, khi cố viết lại MSWord từ đầu trong 1 dự án chết có tên là Kim-tự-tháp (Pyramid) mà rồi sau đó bị cắt, ném bỏ và lặng lẽ quét-xuống-dưới-thảm. May mắn thay cho Microsoft, họ chưa bao giờ dừng đào sâu vào các nền tảng đang có, vậy nên họ vẫn có gì đó để đưa đến tay người dùng, thế nên, Kim-tự-tháp chỉ là 1 thảm họa tài chính, không đến nỗi là một thảm họa chiến lược.

Anh em chúng ta đều là lập-trình-viên, và lập-trình-viên thì luôn có sẵn cái máu kiến-trúc-sư trong tim, và thứ đầu tiên anh em ta đến một địa phận mới, đó là ủi-phẳng cái khoảnh đất đó để xây nên một cái gì đó to lớn và đẹp đẽ và...
Nghĩ tới việc phải mày mò, sửa chỗ này một tí, thay cái kia một tẹo, nghe chán hẳn phải không nào?

Có một lý do tế nhị mà tất cả anh em lập-trình-viên đều muốn ném cái source đang có đi và làm lại từ đầu, đó là họ luôn thấy cái code cũ là một-đống-bùi-nhùi. Và thú vị là: họ thường sai. Nguyên nhân gốc rễ của việc này là một quy luật căn bản của việc lập trình:

Viết code thì dễ hơn đọc code nhiều

Đây chính là lý do vì sao tái sử dụng code cực khó. Đây chính là lý do ông nào trong team bạn cũng có riêng 1 hàm để "chẻ" một cái string thành 1 mảng kí tự. Họ tự viết cái hàm đó bởi vì viết ra nó dễ dàng hơn và vui thích hơn là mày mò tìm cách sử dụng cái hàm cũ của ông khác đã viết nhiều lần.

Hệ quả của tiên đề này là, mỗi khi nói chuyện với bất kì ông dev nào bạn biết, họ đều sẽ bảo rằng "cái đống code này nó như rối nhùi, giờ tao chỉ muốn bỏ hết đi để làm lại từ đầu".

Tại sao nó rối nhùi?

Họ thường sẽ trả lời thế này "nhìn đây, có 1 cái hàm dài 287 lines và tao déll hiểu một nửa số API được gọi ở đây để làm gì nữa".

Trước khi phần mềm bảng tính cho Windows của Borland được phát hành, Philipe Kahn, anh founder của Borland thường được nhắc đến nhiều lần trong mấy tạp chí, khoe khoang rằng Quatro Pro sẽ tốt hơn Microsoft Excel bao nhiêu lần, vì nó được viết lại từ đầu. Tất cả đều là source mới, làm như source cũ nó bị rỉ sét vậy.

Cái ý tưởng code mới nó tốt hơn code cũ nó khá là ngớ ngẩn. Code cũ đã được dùng, nó đã được test. Rất nhiều bug đã được tìm thấy, và chúng đã được fixed. Không vấn đề gì với nó ở đó cả (chừng nào nền tảng, vẫn còn đó, nghiệp vụ vẫn còn đó). Nó không tự nhiên phát sinh bug chỉ vì nó nằm đó trên ổ cứng của anh, mà ngược lại, bạn nhỏ à. Phần mềm có giống như oto, để trong gara một hồi thì bị rỉ đi đâu.

Quay lại với cái hàm 287 lines kia. Đúng, tôi hiểu, nó chỉ là 1 cái hàm đơn giản để hiển thị 1 cái cửa sổ, nhưng nó đã lớn lên từng chút một dù không ai biết tại sao. Ờm, để tui giải thích cho: bug fixes. Vài dòng trong đó là khi Nancy thêm vào khi cô ấy cần cài được phần mềm này trên 1 cái máy không có Internet Explorer. Vài dòng khác, xử lý lỗi phát sinh khi không đủ bộ nhớ để cấp phát. Vài dòng nữa, để fix lỗi khi cái file đang nằm trong đĩa mềm và anh user rút cmn cái đĩa ra giữa chừng. Cái LoadLibrary nhìn phát tởm vì nó phải làm cho đoạn code này chạy được trên Windows 95.

Mỗi một bug trong đó phải mất nhiều tuần được vận hành trong thế giới thực mới được tìm thấy. Mấy anh dev cũ đã mất nhiều ngày thậm chí nhiều tuần để fix được.

Khi anh ném source cũ vào thùng rác để "bỏ đi hết ta làm lại từ đầu", anh đang ném bỏ hết đống kiến thức đấy. Ném bỏ tất cả những bản fix bug đã có, và hàng năm trời công sức kèm theo.

Anh đang ném bỏ vị trí dẫn đầu trong thị trường của mình, anh đang tặng cho đối thủ của mình 2-3 năm thời gian, và tin tôi đi, trong ngành phần mềm, đó là một khoảng thời gian rất dài đấy.

Anh đang tự đưa mình vào tình thế cực kì nguy hiểm nơi anh sẽ chuyển giao một phiên bản code thiếu nhiều năm kinh nghiệm, hoàn toàn không thể thực thi sự điều chỉnh chiến lược nào cũng như không thể phản ứng kịp với nhu cầu của thị trường, đơn giản vì trong thời gian đó (3 năm của Netscape) anh éo có code chạy được để mà chuyển giao. Tệ nhất, trong thời gian đó, anh còn thậm chí không kinh doanh được gì cả.

Anh đang lãng phí hàng tấn công sức để viết lại những dòng code đã tồn tại.

Ngược lại thì sao, có khi nào đống code hiện tại của Netscape thực sự tồi tệ đến nỗi phải viết lại toàn bộ không? Ờm, có lẽ nó khá tệ, nhưng bạn biết sao không? Nó đang chạy tốt trên hàng trăm ngàn máy tính trong thế giới thực.

Khi một anh lập-trình-viên nói rằng cái đống code anh ấy đang xử lý là một đống bùi nhùi, thường có 3 tình huống xảy ra:

Thứ nhất, vấn đề kiến trúc. Code base không được tối ưu. Cái đoạn code của tầng networking lại quăng 1 cái dialog trong khi cái dialog này đáng lẽ phải được xử lý ở tầng UI... Các vấn đề này có thể được xử lý, từng chút một bằng cách di chuyển code một cách cẩn thận, tối ưu hóa, và thay đổi interfaces. Điều này có thể được hoàn thành bởi 1 lập trình viên cẩn thận, sửa code và unit test nghiêm chỉnh, và không ai (không phần mềm liên quan nào) bị "toang" do những thay đổi đó. Hầu như tất cả các vấn đề về kiến trúc có thể được giải quyết mà không cần phải ném bỏ code. Trong dự án Juno, tụi tui dành nhiều tháng trời chỉ để tái-kiến-trúc cho code, chuyển các đoạn code đến đúng nơi của nó, tạo lại các lớp cơ bản hợp lý, và viết lại các interface "sắc bén" giữa các module. Nhưng tụi tui hoàn thành việc đó một cách cẩn thận, từng chút một, với code base đang có, và khi release, không có bug nào tái diễn, không bug mới phát sinh, và code base vẫn còn đó, chỉ là trong 1 diện mạo khác, chuẩn chỉnh hơn.

Thứ hai, vấn đề hiệu năng, nghe đồn là cái phần code render của Netscape khá là chậm. Nhưng điều này chỉ ảnh hưởng một phần của dự án, nơi mà bạn có thể tối ưu hoặc thậm chí viết lại. Nhưng, bạn không cần phải viết lại toàn bộ từ đầu. Khi tối ưu hiệu năng, 1% công việc mang lại 99% hiệu quả.

Thứ ba, "vở sạch chữ đẹp", tôi từng làm trong 1 dự án, có 1 cái kiểu dữ liệu tên là FuckedString. Một dự án khác, có một nửa số biến được đặt với convention bắt đầu bằng dấu gạch dưới _, nửa còn lại bắt đầu bằng m_, nhìn tởm nhỉ. Nhưng thẳn thắn mà nói, mấy cái này có thể được fix trong 5 phút, với sự hỗ trợ của các text editor và IDE, chứ không cần phải "đập đi hết ta làm lại từ đầu".

Quan trọng là, khi bạn "đập đi hết ta làm lại từ đầu", éo có gì để tin rằng bạn sẽ làm tốt hơn lần trước cả. Thứ nhất, chưa chắc bạn có đội cũ, vậy nên bạn không có nhiều kinh nghiệm hơn. Khả năng cao là bạn sẽ mắc các lỗi cũ, một lần nữa, và tạo ra thêm nhiều bug so với version đang có.

Cái ý niệm "làm ra 1 sản phẩm sẵn sàng để vứt bỏ" (build one to throw away) rất là nguy hiểm khi áp dụng cho các phần mềm thương mại. Nếu bạn đang viết code dạng thí nghiệm, bạn có thể sẽ muốn xóa hết cái hàm mới viết tuần trước khi nghĩ ra 1 thuật toán tốt hơn. Tốt, không sao cả. Có khi bạn sẽ muốn tối ưu lại một class để dễ sử dụng hơn, cũng tốt thôi. Nhưng ném bỏ toàn bộ 1 cái chương trình đang chạy tốt thì lại là một điều điên cuồng và dại dột. Và nếu Netscape có vài giám sát trưởng thành với kinh nghiệm trong ngành phần mềm, có lẽ họ sẽ không bắn vào chân mình như thế.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment