Code Refactoring là gì


Khái niệm Tối ưu hóa Code

Tối ưu hóa Code là quá trình thay đổi cấu trúc nội bộ của mã nguồn mà không ảnh hưởng đến hành vi bên ngoài của hệ thống.

Tối ưu hóa Code là việc viết lại mã nguồn một cách khoa học hơn, nhằm duy trì tính chính xác và giá trị chức năng của mã nguồn đó.

Tối ưu hóa Code có thể được thực hiện ở nhiều mức độ: Hệ thống -> Chức năng -> Tệp/ Lớp -> Phương thức/ Hàm. Đối với các mức độ này, “cấu trúc nội bộ” và “hành vi bên ngoài” của hệ thống sẽ được hiểu theo nhiều cách khác nhau. Ví dụ, khi tối ưu hóa một lớp, cấu trúc nội bộ bao gồm các thuộc tính và phương thức của lớp, trong khi hành vi bên ngoài là nhiệm vụ mà lớp thực hiện. Vì vậy, trong trường hợp này, tối ưu hóa được hiểu là viết lại các thuộc tính và phương thức sao cho không làm thay đổi nhiệm vụ của lớp.

Vì sao cần tối ưu hóa Code

Tối ưu hóa không làm hệ thống chạy nhanh hơn hay bảo mật hơn, nhưng nó giúp mã nguồn dễ tiếp cận, dễ đọc và dễ hiểu, từ đó giúp rất nhiều trong quá trình bảo trì và mở rộng hệ thống.

Khi nào cần thực hiện tối ưu hóa Code

Bất cứ khi nào bạn muốn mã của mình “tốt hơn” thì có thể thực hiện tối ưu hóa. Tuy nhiên, có một số giai đoạn dưới đây được cho là thích hợp hơn để thực hiện tối ưu hóa.

Có Thể Bạn Quan Tâm :   Máy lọc nước tiếng Anh là gì? Những điều cần biết về máy lọc nước

Khi thêm chức năng mới vào mã nguồn cũ

Đây là thời điểm bạn phải đọc lại mã nguồn cũ để hiểu và thêm một phần mới vào đó. Có thể phần mới này sẽ ảnh hưởng đến các phần mã nguồn cũ, vì vậy đây là thời điểm thích hợp để thực hiện tối ưu hóa.

Khi tiến hành xem xét mã nguồn

Khi những người có kinh nghiệm xem xét mã nguồn cho những người ít kinh nghiệm, họ sẽ chỉ ra cách viết mã nguồn khoa học hơn cho người ít kinh nghiệm. Từ đó, người ít kinh nghiệm học hỏi và tự tối ưu hóa mã nguồn của mình để nâng cao trình độ.

Khi cần chuyển giao lại

Có những mã nguồn phức tạp và không rõ đến mức ngay cả người viết nó cũng cần thời gian để hiểu logic. Việc chuyển giao lại những mã nguồn như vậy gây khó khăn cho người mới. Do đó, để người mới tiếp cận dễ dàng hơn, đây cũng là một thời điểm thích hợp để tối ưu hóa mã nguồn.

Mã nguồn nào cần tối ưu hóa và khi nào hoàn thành?

Để biết mã nguồn cần tối ưu hóa hay không, ta có thể sử dụng các tiêu chí gọi là “Mùi xấu trong mã” (Bad code smells). Các tiêu chí này được sử dụng để xác định những điểm yếu trong mã và đề xuất các kỹ thuật tối ưu hóa thích hợp. Tùy thuộc vào mức độ áp dụng các kỹ thuật này, mã sẽ được tối ưu đến một mức độ nhất định. Có nhiều kỹ thuật tối ưu hóa mã nguồn, tuy nhiên, thông thường, chỉ áp dụng một số kỹ thuật phổ biến.

Một số điểm yếu và kỹ thuật tối ưu hóa

Do có nhiều kỹ thuật tối ưu hóa mã nguồn khác nhau và khá dài, trong phạm vi bài viết này, tôi chỉ mô tả những phần liên quan đến Bloaters (thu gọn, làm gọn).

Có Thể Bạn Quan Tâm :  

Điểm yếu: Phương thức, hàm quá dài

Nguyên nhân: Việc thêm mã vào một phương thức, hàm liên tục khiến tổng lượng mã trong phương thức, hàm ngày càng tăng. Mục đích ban đầu của phương thức, hàm có thể không còn như lúc đầu, từ đó việc đọc lại ngày càng trở nên khó khăn và tốn thời gian hơn. Phương pháp “Tách phương thức/ hàm” có thể được sử dụng để chia nhỏ một phương thức, hàm lớn thành những phương thức, hàm nhỏ hơn có nhiệm vụ riêng biệt.

void printPet() {
  printBackground();
  System.out.println("name: " + name);
  System.out.println("legs: " + getNumOfLeg());
}

Sau khi tối ưu hóa:

void printPet() {
  printBackground();
  printDetails(getNumOfLeg());
}
void printDetails(int legs) {
  System.out.println("name: " + name);
  System.out.println("legs: " + legs);
}

Phương pháp “Bảo tồn đối tượng toàn diện”: thay vì lấy giá trị từ đối tượng vào tham số và truyền tham số đó vào phương thức khác, gây ra thừa thãi tham số và khó kiểm soát các giá trị tham số khi có thay đổi, hãy sử dụng trực tiếp đối tượng đó trong các phương thức cần dùng.

int start = valueRange().getStart();
int end = valueRange().getEnd();
boolean withinPlan = plan.withinRange(start, end);

Sau khi tối ưu hóa:

boolean withinPlan = plan.withinRange(valueRange());

Phương pháp “Thay thế biến tạm bằng truy vấn”: trong mã có sử dụng các tính toán vào biến tạm và sau đó sử dụng biến tạm đó cho các xử lý tiếp theo.

double CalculateTotal() {
  double basePrice = quantity * itemPrice;
  if (basePrice > 1000) {
    return basePrice * 0.95;
  } else {
    return basePrice * 0.98;
  }
}

Sau khi tối ưu hóa:

double CalculateTotal() {
  if (BasePrice() > 1000) {
    return BasePrice() * 0.95;
  } else {
    return BasePrice() * 0.98;
  }
}
double BasePrice() {
  return quantity * itemPrice;
}

Điểm yếu: Quá nhiều tham số trong phương thức, hàm

Với quá nhiều tham số trong phương thức, hàm, sẽ dễ gây nhầm lẫn, khó nhớ và khó hiểu. Có thể áp dụng một trong các phương pháp sau để xử lý tình trạng này.

Có Thể Bạn Quan Tâm :   AFK là gì trong game Liên Quân, FF? Viết tắt của từ nào

Thay thế tham số bằng giá trị từ cuộc gọi phương thức:

int basePrice = quantity * itemPrice;
double seasonDiscount = store.GetSeasonalDiscount();
double fees = store.GetFees();
double finalPrice = GiscountedPrice(basePrice, seasonDiscount, fees);

Sau khi tối ưu hóa:

int basePrice = quantity * itemPrice;
double finalPrice = GiscountedPrice(basePrice, store);

Truyền đối tượng đầy đủ: thay vì truyền các giá trị riêng lẻ, có thể gom chúng vào một đối tượng nếu chúng có liên quan.

int weight = calculator(numberOfpet,legs,head,body);

Sau khi tối ưu hóa:

... 
class pet{ 
  int legs; 
  int head; 
  int body; 
} 
...
int weight = calculator(numberOfpet,pet);

Điểm yếu: Lớp quá lớn

Lớp có quá nhiều thuộc tính, phương thức trở nên khó hiểu và khó thay đổi. Có thể áp dụng các phương pháp sau để xử lý tình trạng này.

Chia nhỏ: Xem xét việc chia một phần trong lớp lớn thành các lớp nhỏ hơn nếu có thể, từ đó tách phần mã này để tạo thành một lớp con.

class house{
  int table;
  int freeze;
  int keyboard;
  int monitor;
  ....
}

Sau khi tối ưu hóa:

class Computer{
  int keyboard;
  int monitor;
  ...
}

class house{
  int table;
  int freeze;
  Computer computer;
  ....
}

Sử dụng lớp cha chung hoặc thực hiện giao diện: Nếu nhiều lớp có những phần dùng chung, hãy thu gọn chúng lại.

class bicycle{
  int wheel;
  int body;
  bool isRunning(){ ... }
  person getRider(){ ... }
}

class Car{
  int wheel;
  int body;
  int energyLevel;
  bool isRunning(){ ... }
  person getDriver(){ ... }
  int getEnergy(){ .... }
}

Sau khi tối ưu hóa:

interface moveThings{
  int wheel;
  int body;
  bool isRunning(){ }
}

class bicycle implements moveThings{ .... }

class Car implements moveThings{ ... }

Tổng kết

Đối với các dự án, quy mô nhỏ hoặc lớn, tối ưu hóa mã nguồn là cần thiết. Tối ưu hóa mã nguồn đảm bảo tính dễ đọc, dễ hiểu, dễ mở rộng và bảo trì cho hệ thống. Ai cũng muốn đọc mã nguồn sáng sủa, chẳng ai muốn đúc kết vào một dây xích chó, phải không? Việc tối ưu hóa mã nguồn cũng cần được kiểm tra lại để đảm bảo tính chính xác của hệ thống.

Back to top button