Sự thật ẩn giấu đằng sau những dòng code

Các software developer hẳn cũng đều đã từng nghe qua một câu tương tự như thế này:

“Sự thật chỉ có thể tìm thấy ở 1 nơi duy nhất: code”– Robert C. Martin 

Nhưng điều đó có nghĩa là gì ?

Dựa trên điều luật nổi tiếng trong Agile Manifesto : “Thực hành lập trình luôn hơn đọc trăm cuốn sách hay”

Có thể nói các developers viết các tài liệu về software behavior dưới hình thức những dòng code.

Thực ra, các chú thích hay các thông số kỹ thuật cũng có thể ghi nhận được từ software behavior. Tuy nhiên, đôi khi các chú thích hay các thông số kỹ này thuật không được cập nhập dù code thì vẫn được phát triển. Thế là những chú thích, thông số trở nên lỗi thời. Trái lại, code  luôn phản ánh và tạo nên định nghĩa về software behavior.

Vì thế mà khi bạn muốn hiểu về software behavior, hãy nhìn vào code.

Viết cho các độc giả của bạn

Có thể xem code là một loại tài liệu. Và lẽ tất nhiên, bất cứ loại tài liệu nào cũng có những nhóm độc giả riêng của mình.

Người xem code có thể là là một compiler hoặc interpreter, hay cũng có thể là các developer khác.

Vì vậy, mà bạn code không phải chỉ để cho chính mình mà còn phải cho người khác hiểu được. Bởi những developer khác sẽ làm việc với code cũng như giúp code của bạn mở rộng và phát triển hơn.

Một phương pháp thường gặp để code dễ hiểu là sử dụng clean code. Bằng việc sử ​​dụng ngôn ngữ lập trình dễ hiểu cho variable và method names. Điều đó làm giảm bớt những code comment.

Clean code nên được dùng với nguyên tắc sau: Điều gì mà ta có thể đạt được nhờ vào một phương pháp chứ không phải làm sao mà phương pháp đó có hiệu quả.

Hãy đoán xem phương pháp này có công dụng gì:

BigDecimal addUp(List<BigDecimal> ns){..}


Vậy giờ ta thử viết nó ra theo phong cách của clean code xem:

BigDecimal calculateTotal(List<BigDecimal> individualPrice){..}

Clean code là một ý tưởng tốt. Nhưng thế vẫn là chưa đủ.

Tầm quan trọng của việc chia sẻ hiểu biết

Khi có một yêu cầu mới, bạn cần phải hiểu làm cách nào để thực hiện nó, và điều đó ảnh hưởng như thế nào đến code.

Sẽ là một thách thức nếu phần mềm của bạn đã được viết cách đây một khoảng thời gian.

Sau đây là một tình huống mà tôi bắt gặp khá thường xuyên:

X: chúng ta không thể tiếp tục duy trì tính năng Foo

Y: Tại sao?

X: bởi vì Z là người duy nhất biết về nó- ông ấy đã implement code mà chúng ta đang muốn thay đổi

Y: vậy tại sao chúng ta không hỏi ông ấy?

X: bởi vì, ông ấy ốm/ đang trong nghĩ lễ/ đang có cuộc họp,/..

Y: oh

Vấn đề là, nêu code bạn viết dễ hiểu thì ai cũng sẽ đọc được nó

Có rất nhiều cách để làm điều đó. Ví như, Pair programming là một ý tưởng không tồi, hay trau đổi với các developer khác về code của bạn.

Tuy nhiên, cũng cần lưu ý, nếu có quá nhiều developer tham gia vào phát triển 1 sản phẩm sẽ thật khó để làm hài lòng tất cả, cũng như là vấn đề nếu họ bỏ giữa chừng thì sao?

Câu chuyện

Clean code giúp bạn chọn được những từ hay ý đẹp.

Câu hỏi đặt ra là: Bạn sẽ dùng chúng để kể câu chuyện gì qua code của bạn ?

Tôi thì chắc chắn chả biết rồi, chuyện của bạn mà.

Tuy nhiên, thông qua câu chuyện về một điển hình kinh doanh, mà tôi sắp giới thiệu với bạn, tôi tin tưởng tưởng khá chắc chắn rằng bạn sẽ cảm thấy thú vị với câu chuyện code đằng sau đó.

Câu chuyện từ cửa hàng găng tay

Là một người sử dụng phần mềm, tôi luôn mong muốn đạt được kết quả tốt nhất. Vì thế, vào mùa đông, tôi muốn mua một đôi găng tay mới để giữ ấm cho các ngón tay khi phải làm việc.

Vì vậy, tôi dạo qua các trang web bán găng tay. Các web này cho phép tôi mua găng tay trực tuyến.

Basic flow” ( hay còn được biết đến với tên gọi  “kịch bản ngày vui” ) được áp dụng trong trường hợp cụ thể này như sau:

  • Hệ thống bắt đầu với một giỏ hàng trống.
  • Hệ thống hiển thị danh sách găng tay hiện có
  • Tôi lựa cho găng tay mà mình thích thêm nó vào giỏ hàng. Hệ thống  ghi nhận đơn đặt hàng của tôi.
  • Tôi kiểm tra
  • Tôi nhập chi tiết thông tin giao hàng và phương thức thanh toán thanh toán. Hệ thống sẽ lưu các thông tin này.
  • Hệ thống hiển thị bản tóm tắt đơn đặt hàng.
  • Tôi xác nhận. Hệ thống bắt đầu vận chuyển đơn đặt hàng của tôi.

Sau vài ngày, tôi có găng tay mang

Còn đây là câu chuyện tôi muốn đọc trong code

Chương 1: use cases

Chương đầu tiên của câu chuyện là về các use case. Khi tôi đọc code tôi muốn có thể làm theo từng bước cho đến khi ra kết quả mong đợi

Từ góc độ người dùng, tôi muốn biết hệ thống phản ứng thế nào khi gặp vấn đề. Dưới góc nhìn của một user.

Tôi cũng muốn hiểu sự thay đổi có thể xảy ra xuyên suốt quá trình.

Ví dụ: người dùng thường cố gắng quay trở lại chi tiết hóa đơn thanh toán với thông tin vận chuyển, để biết:  Điều gì đã xảy ra? Thậm chí điều gì đó có thể xảy ra hay không?

Tôi muốn hiểu tường tận về code để có thể giải quyết vấn đề trong mọi trường hợp

Vậy một use-case sẽ có những thành phần nào?

Phần cơ bản của một use-case là “step” – các bước mang  người dùng tới gần hơn kết quả mong đợi

Ví dụ: “Hệ thống hiển thị danh sách găng tay.”

Không phải tất cả người dùng đều có thể đi thẳng một bước đạt được kết quả kỳ vọng. Chỉ có một nhóm người dùng nhất định (actors) bao gồm: những khách hàng mua găng tay, những nhà marketing cung cấp găng tay mới tham gia vào hệ thống.

Hệ thống cũng có thể tự chạy một số “Step”.  Giống như việc hiển thị danh sách găng tay, hệ thống tự chạy một số bước mà  người dùng không cần thực hiện thêm bất cứ thao tác nào.

Hoặc, một “Step” là sự tương tác với người dùng. Hệ thống sẽ đưa ra những phản ứng khi có event cho customer. Ví dụ: user điền thông tin vào mục shipping, hệ thống sẽ tự dộng lưu lại những thông tin đó.

Tôi muốn biết được loại data nào cần trong những event đó. Thông tin về Shipping thì sẽ bao gồm tên người dùng, địa chỉ , số điện thoại, etc.

Và người dùng phải thực hiện tuần tự các bước. Ví như: người dùng chỉ có thể thanh toán sau khi cung cấp đầy đủ thông tin vận chuyển. Rõ ràng, có một “flow” các bước diễn ra tuần tự trong trường hợp này. Ngoài ra, còn có những điều kiện được đặt ra để cho phép hệ thống có những phản ứng thích hợp.

Để hiểu về code, bạn cần có một cách học thật tốt để biết về nhiều thứ

Đối với 1 use-case tương tự như trường hợp  “mua găng tay”

  • Tuần tự các bước

Đối với mỗi bước:

  • Actors nào có quyền truy cập  (có nghĩa là nhóm người nào sử dụng )
  • Điều kiện để hệ thống phản ứng
  • Nếu bước này là tự động, hoặc dựa trên sự tương tác của người dùng
  • Phản ứng của hệ thống

Đối với mỗi tương tác từ người dùng:

  • Các user event (như “người sử dụng nhập thông tin vận chuyển”)
  • Dữ liệu đi kèm với tương tác

Một khi tôi biết nơi để tìm một use-case và các phần của nó trong code, tôi sẽ có thể đi sâu hơn nữa.

Chương 2: chia nhỏ thành các bước thông qua components

Trách nhiệm của components:

Tạm xem các thành phần tạo nên software là các component. Vậy  mỗi Component sẽ đảm nhận những chức năng riêng, góp phần tạo nên solfware

Một component có thể là:

  • Component kỹ thuật như database,
  • Một dịch vụ như “dịch vụ giỏ hàng”
  • Một entity trong domain model

Điều đó phụ thuộc vào thiết kế phần mềm của bạn. Nhưng bất kể là gì: bạn cũng thường cần một vài component để biết được một bước của 1 use-case.

Hãy nhìn vào system reaction của step. Khi hệ thống hiển thị một danh sách găng tay. Bạn cần phải phát triển ít nhất hai chức năng: tìm thấy găng tay trong cơ sở dữ liệu và chuyển danh sách găng tay vào trang web.

Khi đọc code tôi muốn hiểu những điều sau đây:

  • Chức năng của từng thành phần là gì?

Ví dụ: “find gloves” cho database.

  • Inputs/outputs của mỗi chức năng là gì?

Ví dụ :

  • Inputs: tiêu chí để tìm găng tay.
  • outputs : danh sách găng tay.
  • Ai đang cùng chịu trách nhiệm chức năng này

Ví dụ: Đầu tiên tìm găng tay. Chuyển kết quả sang trang web thứ hai.

Chương 3: Nhiệm vụ của component là gì?

Code của component sẽ đảm nhận mọi nhiệm vụ.

Vốn là điều hay xảy ra đối với các mô hình miền có sử dụng thuật ngữ  liên quan trong lĩnh vực kinh doanh.

Ví dụ như các thuật ngữ găng tay, đặt hàng.

Với domain model mô tả data về găng tay gồm có: có màu sắc, thương hiệu, kích thước, giá cả ,… Mô hình miền cũng thực hiện tính toán trên dựa trên data để đưa ra tổng giá trị đơn hàng người dùng phải chi trả .

Component có thể là một bộ phận kỹ thuật như kho dữ liệu. Code cần phải trả lời câu hỏi: Làm thế nào để khởi tạo, tìm kiếm, cập nhật và xóa các thông tin trong data?

Kể câu chuyện của bạn

Câu chuyện của bạn có thể giống hoặc không giống câu chuyện trên.

Dù câu chuyện của bạn là gì, ngôn ngữ lập trình vẫn cho bạn sự tự do tuyệt đối để kể câu chuyện của mình.

Điều đó giúp các developer thích nghi được với những hoàn cảnh và các yêu cầu  khác nhau.

Tuy nhiên, nó cũng tiềm ẩn nguy cơ khi các developer kể quá nhiều điều khác nhau khiến câu chuyện trở nên khó hiểu. Kể cả khi là để cho ra một sản phẩm. Vì thế mà ta luôn gặp phải việc đọc code của người khác viết cực kì khó khăn do nó quá rối rắm.

Một cách để giải quyết vấn đề này là sử dụng các design pattern có sẵn.Chúng cung cấp cho bạn cấu trúc code mà bạn cần. Nhờ đó mà team của bạn có thể đi đến tiếng nói chung về cấu trúc của code.

Ví dụ, khung Rails được dựa trên mô hình Model View Controller nổi tiếng

Model này là nơi lưu trữ các domain data.

The view ám chỉ phía client với giao diện người dùng, như các trang HTML. Đây là nguồn gốc của các user events

Các controller sẽ nhận các user events từ phía máy chủ. Nó chịu trách nhiệm điều phối flow.

Vì vậy, khi có nhiều developer sử dụng Rails, họ biết phần nào của code có chức năng gì, và cân nhắc sử dụng chúng một cách thích hợp.

Họ chia sẻ những hiểu biết của mình, khắc phục những vấn đề gặp phải, và thậm chí hưởng lợi từ những chia sẽ đó.

Nếu bạn thấy đến đây là ổn rồi thì cũng tốt. Nhưng tôi còn muốn đi xa hơn thế.

Requirements

Nhiều khách hàng hỏi tôi làm thế nào để giải quyết với vấn đề về tài liệu phần mềm với tầm nhìn dài hạn.

Khi làm việc trong một môi trường đòi hỏi sự nhanh nhạy, làm thế nào để bạn tạo documentation để thực hiện software maintenance?

Những yêu cầu nào đã được thực hiện?

Bạn tìm thấy vị trí được thêm vào ở đâu trong code?

Hàng hoạt câu hỏi được đặt ra cho tôi, lúc đầu tôi cũng không có câu trả lời thỏa mãn. Tất nhiên ngoại trừ: tầm quan trọng của các bài kiểm tra viết, tự động, code sạch, chia sẻ sự hiểu biết.

Nhưng một vài năm trước, tôi bắt đầu suy nghĩ: Nếu sự thật nằm bên trong code, thì code có thể nói lên sự thật . Nói cách khác: nếu bạn quan tâm đến việc kể câu chuyện của mình bằng code tại sao bạn phải diễn giải lại câu chuyện đó bằng lời?

Cần có một cách tốt hơn. Phải tạo ra tài liệu để kể câu chuyện đó một cách chính xác, mà ai cũng có thể hiểu. Và nó phải luôn được cập nhật thường xuyên.

Và như vậy thì chỉ có một nguồn duy nhất: đó là chính bản thân Code.

Sau nhiều thí nghiệm, tôi đã thu được kết quả. Nó đã được công bố trong dự án Github có tên  gọi là requirementsascode.

Cách thức mà nó hoạt động

  • Ví dụ: UseCasemodel định nghĩa các khái niệm về the actorsuse cases, their flowsand steps.  Như đã được giới thiệu ở phần đầu của bài viết.
  • Mô hình UseCaseModelRunner. Mỗi người dùng đều có những cách thức sử dụng khác nhau, bởi vì mỗi người dùng có thể đi theo những con đường khác nhau thông qua các mô hình use-case
  • Người dùng  tương tác với các user event thông qua giao diện tương tác được gọi là system reaction
  • Nhưng tương tác chỉ được thực hiện khi người dùng tuân thủ tuần tự các bước

Ví dụ: người dùng chỉ có thể cung cấp thông tin thanh toán nếu đã hoàn thành thông tin giao hàng

  • Hệ thống tương tác (systemreaction) là một phương pháp. Phương pháp này có nhiệm vụ phối hợp các bộ phận với nhau nhằm thực hiện các bước, như được mô tả trong chương 2.
  • Chương 3 nằm ngoài phạm vi của requirementsascode. Nó mang tính ứng dụng nhiều hơn. Điều đó làm cho các yêu cầu bằng code tương thích với các thiết kế phần mềm tùy ý.

Vì vậy, UseCaseModelRunner kiểm soát hành vi hiển thị của người sử dụng phần mềm. Dựa trên một UseCaseModel.

Với requirementsascodeextract, bạn có thể tạo ra tài liệu từ các mô hình use case tương tự. Bằng cách đó, tài liệu hướng dẫn luôn phản ánh cách phần mềm hoạt động.

Yêu cầu bằng code sử dụng FreeMarker template engine giúp bạn tạo ra bất kỳ tài liệu văn bản  nào bạn thích, ví dụ các trang HTML. Quá trình xử lý có thể biến nó thành các định dạng tài liệu khác như PDF.

Nguồn: blog.topdev.vn via Medium