Những pha bẻ lái code chất lượng cao javascript - Phần 1

Nội dung bài viết

Nghề lập trình ngày nào mà chảng phải kinh qua những cú pháp có điều kiện. Đó là những trường hợp mà chúng ta những devjs thường xuyên gặp phải. Và chính bản thân tôi, tôi cũng thích những tình huống về logic và có điều kiện. Những lúc đó kinh nghiệm sẽ mách bảo ta làm thế nào để bẻ lái cho đàn em đứng sau lưng ta, gật đầu liên tục....


Code chất lượng cao


Đầu tiên theo bản thân tôi, code chất lượng cao để đạt được thì phải phụ thuộc nhiều vào 2 yếu tố: "Kinh nghiệm" và "Tư duy". 

Kinh nghiệm thì phải có, bất cứ ngành nghề nào cũng cần có kinh nghiệm, vì trải qua bao nhiêu bugs bao nhiêu error và bao nhiêu năm chúng ta mới có thể quay lại review code của chính chúng ta và lắc đầu ngao ngán. 

Tư duy thì chưa hẳn có kinh nghiệm rồi mới có tư duy. Tư duy hiểu ở đây là tố chất xử lý tình huống của mỗi lập trình viên. Nó hình thành khác nhau và khác nhiều so với kinh nghiệm. 

Để viết code chất lượng cao và có thể bảo trì dễ dàng, chúng ta hãy bắt đầu với điểm nhỏ nhất, và xem xét quá trình phát triển hằng ngày, và tối ưu hoá được cái nào hay cái ấy. 

Chúng ta sẽ cần đến nhiều phần để nói hết những vấn đề về cách code, chất lượng code... Và có lẽ đây là phần đầu tiên.


Tối ưu hoá code qua những ví dụ đơn giản đến phức tạp


Bây giờ tôi sẽ đưa ra một tình huống check điều kiện lồng nhau. Và các bạn hãy cùng nhau xem xét như thế nào?

function supply(fruit, quantity) {
  const redFruits = ['apple', 'strawberry', 'cherry', 'cranberries'];
  // 1: kiểm tra xem có thật tồn tại hay không?
  if (fruit) {
    // 2: nằm trong danh sách mảng hay không?
    if (redFruits.includes(fruit)) {
      console.log('Đã tìm thấy một loại trái cây lạ');
      // 3: Số lượng lớn hơn 10 không?
      if (quantity > 10) {
        console.log('Có thể đặt hàng số lượng lớn');
      }
    }
  } else {
    throw new Error('Không phải trái cây');
  }
}

Đó chỉ là một vi dụ mà thôi, nhưng ở đây chúng ta thấy một pha xử lý cồng kềnh và khó đỡ. Khi check qua nhiều lệnh if. ở đó là 3 cấp để sử dụng lệnh if. Nếu là bạn, thì bạn xử lý thế nào??? Còn ở đây chúng ta sẽ xem xét một nỗ lực. 

Đầu tiên nếu "Nó không phải là trái cây" thì return luôn. Mức lồng ghép của if else sẽ được giảm xuống một mức, điều này dễ hiểu và dễ duy trì hơn.

function supply(fruit, quantity) {
  const redFruits = ['apple', 'strawberry', 'cherry', 'cranberries'];
  if (!fruit) throw new Error('Không phải trái cây'); // 1: kiểm tra xem có thật tồn tại hay không?
  if (!redFruits.includes(fruit)) return; // // 2: nằm trong danh sách mảng hay không? return
  
  console.log('Đã tìm thấy một loại trái cây lạ');
  
  // 3: Số lượng lớn hơn 10 không?
  if (quantity > 10) {
    console.log('Có thể đặt hàng số lượng lớn');
  }
}

Chúng ta mới chỉ xem xét một ví dụ đơn giản thôi, đừng đùa. Từ từ! Tiếp theo chúng ta sẽ xem xét thêm một ví dụ có nhiều điều kiện hơn.

function pick(color) {
  // Chọn đúng màu sẽ có thưởng
  if(color === 'red') {
      return ['apple', 'strawberry']; 
  } else if (color === 'yellow') {
      return ['banana', 'pineapple'];
  } else if (color === 'purple') {
      return ['grape', 'plum'];
  } else {
      return [];
  }
}

Giả sử sau khi phân tích vấn đề thì chúng ta có thể tối ưu hơn khi sử dụng switch

function pick(color) {
  // Chọn đúng màu sẽ có thưởng
  switch (color) {
    case 'red':
      return ['apple', 'strawberry'];
    case 'yellow':
      return ['banana', 'pineapple'];
    case 'purple':
      return ['grape', 'plum'];
    default:
      return [];
  }
}

Code sau khi tối ưu hóa với việc sử dụng switch trông gọn gàng và rõ ràng, nhưng nó vẫn rất dài dòng. Thử tiếp tục tối ưu hóa xem: Với sự trợ giúp của cấu trúc {key: value} của Object, chúng ta có thể liệt kê tất cả các tình huống trong Object, sau đó sử dụng key làm chỉ mục để lấy nội dung trực tiếp thông qua Object.key hoặc Object[key]

const fruitColor = {
  red: ['apple', 'strawberry'],
  yellow: ['banana', 'pineapple'],
  purple: ['grape', 'plum'],
};
function pick(color) {
  return fruitColor[color] || [];
}

Or có thể sử dụng Map()

const fruitColor = new Map()
.set('red', ['apple', 'strawberry'])
.set('yellow', ['banana', 'pineapple'])
.set('purple', ['grape', 'plum']);

function pick(color) {
  return fruitColor.get(color) || [];
}

Sau khi tối ưu hóa, code chúng ta trông ngắn gọn hơn và dễ mở rộng hơn nhiều so với trước. Cũng còn nhiều cách khác như việc sử dụng filter().

const fruits = [
  { name: 'apple', color: 'red' }, 
  { name: 'strawberry', color: 'red' }, 
  { name: 'banana', color: 'yellow' }, 
  { name: 'pineapple', color: 'yellow' }, 
  { name: 'grape', color: 'purple' }, 
  { name: 'plum', color: 'purple' }
];

function pick(color) {
  return fruits.filter(f => f.color === color);
}

Để xem phần 2 tôi sẽ nói về "Sử dụng các tính năng mới của mảng để đơn giản hóa các phán đoán logic"...

Có thể bạn đã bị missing