Tránh sử dụng cấu trúc dữ liệu array động trong PHP

Kinh Nghiệm

Bài viết này trình bày về cách tiếp cận hướng đối tượng object-oriented là nên sử dụng Classes để thay thế sử dụng arrays trong PHP. Tôi sẽ chỉ cho bạn thấy 1 góc nhìn khác về việc tại sao nên sử dụng Class/Object để thay thế array.

Trong thế giới PHP, thì việc sử dụng arrays ([] hoặc array()) là quá phổ biến. Array đóng 1 vai trò rất quan trọng trong PHP, tuy nhiên nó cũng có các mặt hạn chế riêng của nó.

Chúng ta xét ví dụ dưới đây, giả sử rằng bạn có 1 khối code block rất dài và phức tạp. Vì mục đích minh họa, ta sẽ giả sử khối code block sâu 2 cấp:

foreach (/* ... */) {
  foreach (/* ... */) {
    // thu thập dữ liệu data vào 1 mảng collection
  }
}

Bên ngoài khối block này, chúng ta sẽ có 1 mảng array dùng để thu thập tập dữ liệu data nằm bên trong vòng lặp foreach.

$collection = []; // For later use.
foreach (/* ... */) {
  $widget = [];
  foreach (/* ... */) {
    $widget = ...;
  }
  $collection[] = $widget;
}
// Further use of $collection.

Bản thân chúng ta đã bắt gặp hay đã tự viết đoạn code giống như sau. Kết quả là rất dễ dàng cho ra kiểu cấu trúc dữ liệu giống như sau:

$collection = [
  [
    'order' => (int),
    'original' => (object),
    'info' => [
      'message' => (string),
      'created_at' => (DateTime),
      ...
    ],
    ...
  ],
  ...
];

Cấu trúc dữ liệu động luôn là cách tiếp cận tồi. Rất có thể sau đó chính bạn (hay là 1 vài người nào đó) phải mở rộng cấu trúc dữ liệu này và sẽ không hình dung ra được 1 cách rõ ràng cấu trúc dữ liệu sẽ hình thù ra sao. Bạn phải thận trọng vào mọi dòng code để chắc rằng mình đang thay đổi đúng cấu trúc.

Cách tiếp cận tốt hơn là nên sử dụng Classes làm cấu trúc dữ liệu ở đây. Với Classes, bạn không thể tạo cấu trúc dữ liệu phát triển 1 cách động. Cấu trúc dữ liệu của bạn trở nên bất định (cố định). Nhưng cách tiếp cận này không phổ biến trong thế giới PHP, nơi mà mọi người thích sử dụng arrays hơn.

Nhưng trong ví dụ ở trên, bạn nên sử dụng Classes là tốt hơn. Thay vì sử dụng array, giờ ta thay đổi nó thành objects.

class Collection {
    /** @var Widget[] */
    private $widgets;

    public function __construct() {
        $this->widgets = [];
    }

    /** @return Widget[] */
    public function getWidgets(): array {
        return $this->widgets;
    }

    /** @param Widget[] $widgets */
    public function setWidgets(array $widgets): void {
        $this->widgets = $widgets;
    }

    /** @param Widget $widget */
    public function addWidget(Widget $widget) {
        $this->widgets[] = $widget;
    }
}

Ở đoạn code trên, ta vẫn sử dụng 1 mảng array cho widgets, nhưng ít nhất nó cũng được bao ngoài bởi 1 class. Hãy chắc rằng ta không quên khởi tạo $widgets trong constructor. Đối với mảng arrays bên trong 1 class thì nên có phương thức add(). Trong ví dụ này ta gọi nó là addWidget().

Tiếp, ta tạo ra 1 Widget class:

class Widget {
    /** @var int */
    private $order;

    /** @var SomeObject */
    private $original;

    /** @var Info */
    private $info;

    // More properties here.
    ...

    public function __construct()
    {
        $this->order = 0;
    }

    // Getters and Setters here.
    ...
}

với trường info field: ta cũng tạo ra 1 Info class.

class Info {
    /** @var string */
    private $message;

    /** @var \DateTime */
    private $createdAt;

    // More properties here.
    ...

    // Getters and Setters here.
    ...
}

Giờ ta thay đổi đoạn code vòng lặp thành sử dụng objects.

$collection = new Collection();
foreach (/* ... */) {
  $widget = new Widget();
  foreach (/* ... */) {
    $widget->...;
  }
  $collection->addWidget($widget);
}

Kết luận

Thay vì sử dụng 1 cấu trúc dữ liệu array con lồng vào trong 1 array cha, chúng ta nên tạo ra 1 lớp class dành riêng, ta nên hướng tới sử dụng nhiều classes hơn. Đây là 1 điều tốt. Và ta nên đảm bảo có 1 namespace dành riêng cho các data classes này. \App\Data là 1 gợi ý tốt.

Ví dụ trong bài viết là cách tiếp cận để sử dụng cấu trúc dữ liệu 1 cách tường minh hơn trong PHP. Cách tiếp cận này sẽ khiến code trở nên dễ dàng maintainable đối với các ứng dụng PHP có vòng đời dài hạn bằng cách tránh sử dụng cấu trúc dữ liệu array động. Thỉnh thoảng, bạn vẫn có thể chỉ sử dụng arrays, nhưng nên ít sử dụng chúng khi có thể.


Trả lời

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 *