Một số mẹo giúp bạn viết code PHP tốt và dễ đọc hơn

Khi bắt tay vào thực hiện một dự án, việc viết code sao cho gọn gàng, dễ đọc và dễ bảo trì, sửa chữa khi có bug luôn là vấn đề mà các dev cần để tâm. Để đạt được những tiêu chí trên, các dev trong team cần phải hiểu và tuân theo một số quy tắc viết code mà team đặt ra. Vậy, các chuẩn viết code (hay coding standards) này là gì? Có các mẹo nào giúp cho việc viết code PHP tốt hơn và dễ đọc hơn? Câu trả lời sẽ được giải đáp ngay trong bài viết này.

Một số mẹo giúp bạn viết code PHP tốt và dễ đọc hơn

Bộ chuẩn viết code (coding standards) là gì?

Bộ chuẩn viết code là một bộ quy tắc khi viết code được các dev trong cùng một dự án đặt ra để mọi người cùng làm theo. Khi các dev cùng viết code theo một bộ tiêu chuẩn như vậy, code sẽ dễ đọc, dễ tái sử dụng và cải tiến hơn.

Cụ thể, dưới đây là các lợi ích mà bộ chuẩn viết code mang lại:

  • Một bộ chuẩn viết code chung đóng vai trò như một blueprint cho các thành viên trong dự án, từ đó giúp mọi người hiểu được code của nhau dễ dàng hơn.
  • Khi có cách viết code phù hợp, code của bạn sẽ trở nên đơn giản và rõ ràng hơn, giúp bạn tránh được những sai lầm phổ biến.
  • Nếu không có chuẩn viết code, đôi khi bạn sẽ phải xem, sửa lại code nhiều lần. Với chuẩn viết code đã được thống nhất từ trước, bạn sẽ hiểu những dòng code đã viết dễ dàng hơn, từ đó xem và sửa lại cũng nhanh chóng và thuận lợi hơn.
  • Khi bạn muốn nhân bản code cho nhiều dự án, trang web khác, chất lượng của code sẽ tốt hơn.

Một bộ quy tắc viết code thường bao gồm các yếu tố sau:

  • Việc đặt tên biến, hằng, hàm, class, …
  • Sử dụng khoảng trắng hay tab
  • Việc khai báo và sử dụng biến
  • Comment
  • Độ dài tối đa mỗi dòng code, file, …

Trong trường hợp bạn đang phát triển các sản phẩm cho WordPress như theme và plugin, bạn cần tuân thủ các quy tắc trong bộ WordPress Coding Standards. Tuy nhiên, bộ quy tắc này có một số yêu cầu khá khắt khe mà mình nghĩ bạn có thể không cần làm theo. Còn dưới đây là các yêu cầu chính trong bộ quy chuẩn của WordPress mà bạn cần tuân thủ:

Lùi đầu dòng và độ dài dòng code

Bạn nên sử dụng tab thay vì dấu cách để giúp các máy khác hiển thị code được linh hoạt nhất. Về độ dài dòng code, bạn nên giữ các dòng code của mình từ 75 đến 85 ký tự để cho code dễ đọc hơn.

Khai báo mảng

WordPress bắt buộc các dev phải khai báo mảng dạng dài array(1, 2, 3). Tuy nhiên, từ bản 5.4 trở đi, PHP hỗ trợ viết theo dạng ngắn [1, 2, 3].

Thẻ PHP ngắn

WordPress yêu cầu bạn phải viết đầy đủ thẻ PHP như sau:

<?php echo 'Some text'; ?>

Nhưng từ bản 5.4, PHP hỗ trợ viết thẻ ngắn (và tính năng này luôn được bật), nên bạn có thể dùng nó để cho câu lệnh gọn gàng hơn:

<?= 'Some text'; ?>

Cấu trúc điều khiển

Cấu trúc điều khiển bao gồm if, for, while, switch, … Giữa các từ này và dấu mở ngoặc, bạn nên sử dụng một dấu cách (nhớ là chỉ nhấn phím cách một lần thôi nhé) để phân biệt chúng với các cấu trúc gọi hàm.

if ( ( điều_kiện1 ) || ( điều_kiện2 ) ) { 
hành động cần thực thi 1; 
} elseif ( ( điều_kiện3 ) && ( điều_kiện4 ) ) { 
hành động cần thực thi 2; 
} else { 
hành động cần thực thi mặc định; 
}

Với các lệnh switch, bạn có thể viết như sau:

switch ( điều_kiện ) {
case 1:
hành động cần thực thi
break;
 
case 2:
hành động cần thực thi
break;
default:
hành động mặc định
break;
}

Lời gọi hàm

Khi gọi hàm, bạn nên thêm MỘT dấu cách giữa tên hàm, dấu ngoặc mở và biến đầu tiên chứ đừng viết liền nhé. Bạn cũng nên thêm dấu cách giữa dấu phẩy và từng tham số, giữa tham số cuối, dấu ngoặc đóng và dấu chấm phẩy. Để giúp bạn dễ hình dung, dưới đây là ví dụ về chuẩn viết code của phần gọi hàm:

$var = foo( $bar, $baz, $quux );

Đặt tên file và class

Trong WordPress, tất cả các class đều phải được đặt tên dạng Ten_Class. Bạn cần viết hoa chữ cái đầu mỗi từ và phân cách nhau bằng dấu gạch dưới. 

Tên file của class được viết dạng class-ten-class.php. Bạn cần thêm tiền tố class- và viết thường tên class, cũng như phân cách các từ bằng dấu gạch ngang.

Tuy nhiên, khi làm việc với các plugin hay các theme lớn, chúng ta sẽ dùng Composer để tự động load các file và cách làm này sẽ không hiệu quả nữa bởi Composer tuân theo cách viết của PSR. Do vậy, lúc này, chúng ta sẽ tuân theo quy tắc đặt tên file và class của PSR như sau:

  • Tên class: có dạng TenClass (viết hoa chữ cái đầu của mỗi từ và viết liền các từ).
  • Tên file: có dạng TenClass.php (tên file trùng với tên class).

Ngoài ra, các file này sẽ được đặt trong các thư mục tương ứng với namespace của chúng. Ví dụ như một class có tên đầy đủ là \ALSearch\Shortcode\Field sẽ được đặt trong thư mục src\ShortCode với tên file là Field.php. Trong ví dụ này, thư mục src tương ứng với namespace ALSearch, còn các phần tiếp theo trong tên class tương ứng với các mục theo cùng phân cấp.

Điều kiện Yoda

Khi thực hiện các phép so sánh logic liên quan đến các biến, bạn hãy luôn đặt biến ở phía bên phải và đặt các hằng số, nghĩa đen hoặc lệnh gọi hàm ở phía bên trái nhé.

if ( true === $the_force ) {
    $victorious = you_will( $be );
}

Mục đích của cách viết này là để đảm bảo kiểu dữ liệu (khi so sánh PHP sẽ ép kiểu) và tránh lỗi như khi bạn viết = thay vì viết ==. Tuy nhiên, cách viết này có một nhược điểm, đó là nó khiến cho code của bạn khó đọc và khó hiểu hơn, nhất là với những coder mới vào nghề.

Toán tử ?:

WordPress không cho phép bạn sử dụng toán tử ?: ở dạng ngắn mà luôn yêu cầu bạn viết đầy đủ như sau:

$type = $type ? $type : 'select';

Tuy nhiên, từ bản 5.3 trở đi, bạn có thể viết ngắn lại để dễ đọc hơn như dưới đây:

$type = $type ?: 'select';

Các mẹo viết code PHP hiệu quả trên thực tế

Trên thực tế, chúng mình đã áp dụng một số cách viết code trong các dự án để giúp code tối ưu, dễ bảo trì và dễ đọc hơn. Mình đã tổng hợp lại những mẹo đó ở các phần dưới đây:

Viết code một cách thống nhất

Các bạn hãy viết cùng một kiểu trong một hàm, class, hoặc file, tránh viết các kiểu khác nhau cho đoạn code tương tự, giống như ví dụ dưới đây:

<?php if ( $args['label'] ) : ?>
    <span class="als-field__label"><?php echo esc_html( $args['label'] ); ?></span>
<?php endif; ?>
 
<?php
if ( $args['prefix'] ) {
    echo '<span class="als-field__prefix">' . esc_html( $args['prefix'] ) . '</span>';
}

Các bạn có thể thấy, đoạn code trên hiển thị label và prefix nhưng cách viết lại khác nhau dù cách hiển thị giống nhau. Vì vậy, mình sẽ viết lại cho thống nhất như sau:

if ( $args['label'] ) {
    echo '<span class="als-field__label">', esc_html( $args['label'] ), '</span>';
}
if ( $args['prefix'] ) {
    echo '<span class="als-field__prefix">', esc_html( $args['prefix'] ), '</span>';
}

Trả về sớm – early return

Nếu viết các khối điều kiện quá lớn, code sẽ rất khó đọc và bạn sẽ khó theo dõi logic hơn. Để khắc phục điều này, bạn cần phải viết các khối điều kiện nhỏ lại. Một trong những kỹ thuật để viết chúng nhỏ lại là “early return” – tạm dịch là trả về sớm ngay khi có thể.

Ví dụ, mình có đoạn code sau chưa được tối ưu:

if ( 'none' !== $field['sanitize_callback'] ) {
    if ( is_callable( $field['sanitize_callback'] ) {
        $value = call_user_func( $field['sanitize_callback'], $value, $args );
    } else {
        // Đoạn code rất dài.
    }
}
return $value;

Khi dùng early return, đoạn code này được viết lại như sau:

if ( 'none' === $field['sanitize_callback'] ) {
    return $value;
}
if ( is_callable( $field['sanitize_callback'] ) {
    return call_user_func( $field['sanitize_callback'], $value, $args );
}
// Đoạn code rất dài.
return $value;

Đặt giá trị mặc định

Việc đặt giá trị mặc định giúp chúng ta loại bỏ các câu điều kiện dùng để kiểm tra sự tồn tại của giá trị đó, từ đó giúp code của bạn đơn giản và dễ đọc hơn.

Dưới đây là đoạn code chưa được tối ưu bằng việc đặt giá trị mặc định:

if ( isset( $args['prefix'] ) && $args['prefix'] !== '' ) {
    echo '<span class="als-field__prefix">', esc_html( $args['prefix'] ), '</span>';
}
if ( isset( $args['label'] ) && $args['label'] !== '' ) {
    echo '<span class="als-field__label">', esc_html( $args['label'] ), '</span>';
}

Sau khi dùng giá trị mặc định, đoạn code trở nên dễ đọc hơn:

$args = wp_parse_args( $args, [
    'prefix' => '',
    'label' => '',
] );
 
if ( $args['prefix'] ) {
    echo '<span class="als-field__prefix">', esc_html( $args['prefix'] ), '</span>';
}
if ( $args['label'] ) {
    echo '<span class="als-field__label">', esc_html( $args['label'] ), '</span>';
}

Output nhiều giá trị với echo

Khi cần output nhiều đoạn text, chúng ta thường viết code như sau:

echo '<span class="als-field__prefix">' . esc_html( $args['prefix'] ) . '</span>';

Tuy nhiên, cách làm này không tối ưu bằng việc dùng hàm echo. Hàm echo cho phép chúng ta truyền nhiều tham số 1 lúc, do đó hoạt động nhanh hơn hàm thường dùng:

echo '<span class="als-field__prefix">', esc_html( $args['prefix'] ), '</span>';

Khai báo muộn và khai báo khi cần thiết

Hay nhớ rằng, bạn chỉ nên khai báo các biến khi nào cần thiết thôi nhé. Việc khai báo này bao gồm cả việc khởi tạo giá trị ban đầu nữa.

Thêm vào đó, bạn nên khai báo muộn nhất có thể. Tốt hơn hết là bạn nên khai báo ngay trên đoạn code sử dụng biến đó.

Sau đây là ví dụ về việc khai báo biến thừa:

$date = parent::get_date();
$format = ''; // Khai báo thừa, vì biến này được khai báo lại ở đoạn code dưới

if ( $meta ) {
    $format = 'Y-m-d';
    return date( $format, $date );
}

Đúng ra, các bạn nên khai báo như sau:

$date = parent::get_date();

if ( $meta ) {
    $format = 'Y-m-d';
    return date( $format, $date );
}

Ví dụ về khai báo biến quá sớm khi ta chưa dùng đến:

$format = 'Y-m-d';

// Đoạn code rất dài.

return date( $format, $date );

Bạn chỉ nên khai báo biến $format ngay trước đoạn code dùng nó như sau:

// Đoạn code rất dài.

$format = 'Y-m-d';
return date( $format, $date );

Lời cuối

Việc cải tiến và tối ưu code luôn là vấn đề khiến các coder quan tâm. Code của bạn càng chuẩn, càng dễ đọc, team bạn sẽ làm việc với nhau hiệu quả hơn cũng như dễ dàng xử lý khi có vấn đề xảy ra. Đừng quên áp dụng các mẹo ở trên để có được kết quả tốt nhất nhé.

Nếu có thêm các mẹo hay ho nào khi viết code, đừng ngại chia sẻ với chúng mình bằng cách để lại bình luận trong bài viết.

Để lại bình luận

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *