+1

Clean code

Clean code là gì? Làm sao biết code nào sạch code nào không? Mã sạch là gì? Tại sao developer chúng ta cần mã sạch, nó liên quan gì đến chuyện trở thành một developer tốt hơn. Có bạn trả lời mã sạch đương nhiên là mã không bị thối rồi 😄. Cũng đúng, vậy mã như thế nào là mã không được sạch. Xem thử đoạn code dưới đây nhé:

public object calTotalCost(){
  var list = Products.getItems();
  var totalCost =0;

  if(list != null){
      foreach (var item in list)
      {
          totalCost += item.getCost();

          if(totalCost > user.Balance){
              return ErrorMessage("User balance not enough");
          }
      }
  }

  return totalCost;
}

Trong đoạn code này những thứ gì bạn cảm thấy nó không được sạch lắm? Chắc nhiều bạn nhìn vào kêu là: "thằng này code ngu vãi, giờ này còn ai code chuối như vậy nữa 😄". Thực sự thì thời gian đầu mình cũng ngu ngu kiểu như thế. =)). Nên giờ chia sẻ lại cho những bạn nào còn chưa giác ngộ về clean code 😄 Quay lại cái example, đoạn code này có rất nhiều vấn đề về clean code:

  1. [Meaningful names]: Tên biến rất là không có chút ý nghĩa gì. Thằng code mấy dòng này nó code xong chạy ok, no problem, tuyệt vời. Sau 3 tháng features mới nhiều và có liên quan tới phần code này, quay lại đọc chả hiểu nó làm cái mọe gì - phải lại đọc code, debug để biết nó làm cái gì, ác hơn đọc cũng chả biết là cái gì -> tốn rất nhiều giời gian vô ích -> fail.
  2. [Don't return null]: Tự dưng cái hàm getItems trả lại null làm cái beep gì để tốn cái công phải kiểm tra null ta, cứ chỗ nào xài là phải tốn công kiểm tra null, cũng khá là dư thừa phải không? Cái chúng ta muốn chỉ là đơn giản lấy danh sách sản phẩm và tính tổng tiền thôi mà. Thay vì return null chúng ta có thể trả về một empty list.
  3. [CLass, method does one thing well]: Great!!, một hàm mà làm được cả hai chức năng nếu có kết quả trả về thì biết tổng sản phẩm của khách hàng này mua, còn lỗi thì biết khách hàng mua quá số tiền hiện có. Nhưng cuối cùng thì được gì, chỉ là gây khó khăn để hiểu, phải document rườm rà để giải thích, gây khó khăn cho mấy đồng nghiệp khác sử dụng method này, gặp mình dẹp luôn viết hàm khác cho khỏe 😄

Ví dụ của mình quá múa rìu qua mắt thợ phải không? Nhìn vào là thấy rồi, phân với chả tích 😄. Nhưng đó là một trong rất nhiều vấn đề về mã sạch (clean code) mà khi chúng ta muốn trở thành một developer tốt hơn chúng ta cần phải quan tâm, những bậc cao nhân trong nghiệp lập trình, thì chỉ cần nhìn code thì chúng ta đã cảm thấy rất phê, những thứ cao siêu đầy kinh nghiệm ẩn chứa trong những dòng code nhìn có vẻ thật quá đơn giản.

Kiến thức và kinh nghiệm mình cũng chỉ có hạn nên cần phải đọc thêm bí kíp để biết thêm những gì ngoài kiến thức bé nhỏ của mình, và đây là hai cuốn sách mà nếu muốn uyên thâm hơn trong vấn đề clean code này các bạn nên tìm đọc:

  • Clean Code (Robert C. Martin)
  • The Clean Coder (cũng ông Robert C. Martin luôn) Mình sẽ list lại cũng như bàn luận thêm về những gì được viết trong sách, thật ra nói clean code là gì đó khá thực thể nhưng nó cũng khá là cảm tính kiểu như chúng ta luôn thấy bạn gái đứa khác đẹp trong khi nó nghĩ ngược lại 😄. Nhưng đây là những chia sẽ của các bậc tiền bối đầu ngành nên nó là những kinh nghiệm rất quý giá cho nghiệp lập trình chúng ta 😃
  1. Các chia sẽ của các bậc tiền bối về clean code
  • Clean code does one thing well. (Bjarne Stroustrup)
  • Clean code is simple and direct, clean code read like well-written prose. (Grady Booch)
  • Clean code can be read, clean code should be literate. It has meaningful names (Dave Thomas)
  • Clean code always looks like it was written by someone who cares. (Micheal Feathers)
  • Reduced duplication, high expressiveness, and early building of simple abstractions. (Ron Jeffries)
  • You know you are working on clean code when each routine you reads turns out to be pretty much what you expected. (Ward Cunningham)

Với những chia sẽ về clean code này thì nó có thể thấm hoặc sẽ thấm với bất cứ lập trình viên nào, với bản thân mình là thế. Mình cũng chưa thể nào nói là đã hiểu hết những chia sẽ này, vì thật sự cũng không hiểu nó nói gì 😄. 2. Clean code rules 2.1. Meaningful names 2.1.1. Use intention-revealing Names Đặt tên biến là một nghệ thuật trong lập trình đấy nhé,phải đặt cái tên phải thật là ý nghĩa, dể hiễu, đọc phát hiểu ngay, đúng ngữ pháp (với mình =]]). Kiểu như Trần Nhật, Lục Thị Mỹ (muốn con mình đi nước ngoài) hay Nguyễn Vàng, Nguyễn Kim (muốn con cái giàu có)...

Đừng như Nguyễn Văn A, Nguyễn Văn B mà mấy ông thầy dạy lập trình hay lấy ra làm ví dụ nhé. Có lẽ cuộc đời thằng Nguyễn Văn A là hay được đem ra làm ví dụ nhất cuộc đời này. Kệ nó đi 😄. Nói chung đặt tên biến trong lập trình rất quan trọng, project thành bại một phần do nó mà ra. Ví dụ:

public List<Customer> GetData()
    {
        var list1 = new List<Customer>();
        var data = ServiceRepository.GetPlainCustomers();
        foreach(var item in data)
        {
            if (item != null && item.IsValid)
                list1.Add(item);
        }
        return list1;
    }

Đậu xanh, 2 tháng sau hay sau này là không biết nó làm cái nồi gì luôn. Phắc ziu thằng viết ra hàm này. Như thế này thì tốt hơn nhiều phải không, bỏ thêm vài giây để suy nghĩ tên biến, tiết kiệm được hàng giờ đồng hồ sau này 😃

public List<Customer> GetValidCustomers()
    {
        var validCustomers = new List<Customer>();
        var plainCustomers = ServiceRepository.GetPlainCustomers();
        foreach(var customer in plainCustomers)
        {
            if (customer != null && customer.IsValid)
                validCustomers.Add(customer);
        }
        return validCustomers;
    }

2.1.2. Use Pronounceable Names

//BAD
public class Customer
    {
        private DateTime joinhhmmdd;
        private DateTime lstloghhmmdd;
        private string custId = "ID123";
    }


//GOOD
public class Customer
    {
        private DateTime JoinTime;
        private DateTime LastLoginTime;
        private string CustomerId = "ID123";
    }

2.1.3. Use Searchable Names

//BAD
for(int j =0; j<34 ;j++){
    s += (t[j] * 4) / 5;
}

//GOOD
 int realDaysPerIdealDay = 4;
 const int WORK_DAYS_PER_WEEK =5;
 int sum 0;
 for(int i=0;i< NUMBER_OF_TASKS; i++)
 {
     int realTaskDays = taskEstimate[j] * realDaysPerIdealDay;
     int realTaskWeeks = (realTaskDays / WORK_DAYS_PER_WEEK);
     sum+=realTaskWeeks;
 }

Trên đây là những chia sẻ nho nhỏ của mình về clean code, và mỗi chúng ta muốn trở thành 1 better developer thì nên chú ý và tích lũy những thứ nhỏ nhặt như vậy. Tất nhiên mình cũng chưa đạt cảnh giới viết đoạn code nào là easy to understand, tuy nhiên đều cân nhắc và suy ngẫm cũng như nhờ các bậc tiền bối cao nhân chỉ giáo thêm. Hy vọng các bạn sẽ có được những tiến bộ trong công việc coder của mình.


All Rights Reserved

Viblo
Let's register a Viblo Account to get more interesting posts.