Một pattern hay của Facebook PHP SDK

Do có nhu cầu tìm một cách tốt để xây dựng các bộ thư viện. Và Github đã tư vấn cho mình một em gái khá xinh tươi là Facebook PHP SDK. Minh vốn thích cách chiều chồng của Laravel, Cú pháp trong nó rất gọn nhẹn, nên code bằng nó khá là nhanh và cũng tiện lợi. Nhưng Laravel thì quá phức tạp để có thể tìm hiểu nhanh chóng, Mình đã từng tách thành công component validate của nó ra chạy stand-alone, nhưng đó chỉ là một phần nhỏ thôi, vẫn không thể hiểu nổi 10% của nó. Facebook PHP SDK cũng có phần nào tính cách giống Laravel, nhưng đơn giản và dễ hiểu hơn.

Facebook PHP SDK định nghĩa hai khái niệm là Node và Edge. Node là các đối tượng, còn Edge là các collection được phân trang, và có thể dịch chuyển tới các trang khác. Cái mình thích ở đây, là Edge và Node đều tự wrap kết quả trả về của mình và các property của nó vào các class để có thể sử dụng mà không cần dùng keywork “new” nhiều lần.

Một ví dụ đơn giản để hiểu chỗ này là như sau, nếu bình thường bạn sẽ phải gọi code kiểu này :

// Find user and make new instance $user = new User(["id"=>12]); $groupId = $user->getGroup(); //create group instance $group = new Group(#groupId);

Thì trong Facebook PHP SDK bạn có thể viết lại như sau :

$user = new User(['id'=>12]); $user->getGroup() ->setName('New name') ->save();

Điều này rất hay, nó được hiện thực trong các framework hỗ trơm ORM như Laravel, Kohana, … dùng để map các Class với các table, và vì các table có liên kết với nhau, vì vậy trong các class tương ứng với các table có liên kết này đều cần có thuộc tính để link, và các thuộc tính này cũng phải là instance của class được liên kết. Facebook PHP SDK đã hiện thực điều giống giống như vậy nhưng với database là data lấy từ các API trên remote server.

Trong mỗi class, sẽ có một objectClassMap giống như vầy :

/** * @var array Maps object key names to GraphNode types. */ protected static $graphObjectMap = [ 'cover' => 'FacebookGraphNodesGraphCoverPhoto', 'place' => 'FacebookGraphNodesGraphPage', 'picture' => 'FacebookGraphNodesGraphPicture', 'parent_group' => 'FacebookGraphNodesGraphGroup', ];

Khi tạo một instance để map với dữ liệu lấy từ API, họ sẽ kiểm tra dữ liệu đó có key trùng với phần key của map, và sẽ tạo instance là class ở phần value, sau đó gán vào một properti là $items cho instance đó. Nhờ vậy họ có thể làm được điều mình thích ở trên. Đây là hàm makeNode của họ :

/** * Safely instantiates a GraphNode of $subclassName. * * @param array $data The array of data to iterate over. * @param string|null $subclassName The subclass to cast this collection to. * * @return GraphNode * * @throws FacebookSDKException */ public function safelyMakeGraphNode(array $data, $subclassName = null) { $subclassName = $subclassName ?: static::BASE_GRAPH_NODE_CLASS; static::validateSubclass($subclassName);

`// Remember the parent node ID
$parentNodeId = isset($data['id']) ? $data['id'] : null;

$items = [];

? $graphObjectMap[$k]
null;
? $graphObjectMap[$k]
null;
? $graphObjectMap[$k]
null;
? $graphObjectMap[$k]
null;
? $graphObjectMap[$k]
null;
? $graphObjectMap[$k]
null;
? $graphObjectMap[$k]
null;
? $graphObjectMap[$k]
null;
? $graphObjectMap[$k]
null;
? $graphObjectMap[$k]
null;
? $graphObjectMap[$k]
null;
? $graphObjectMap[$k]
null;
null;

// Could be a GraphEdge or GraphNode
$items[$k] = $this->castAsGraphNodeOrGraphEdge($v, $objectSubClass, $k, $parentNodeId);
} else {
$items[$k] = $v;
}
}`

return new $subclassName($items); }

Rất hay đúng không, Họ cũng làm tương tự như vậy cho edge, nhưng edge thì họ phải lưu thêm biến $request, dùng để build request khi muốn chuyển trang.

Giờ thì thấy nó rất rõ ràng, nhưng mình cũng đã phải mất mấy ngày mới đọc nổi, và giữa chừng cũng đang chán nản và dẹp qua một bên, nhưng sau đó nhờ việc code SDK cho Faceplusplus.com tiếp xúc với cấu trúc dữ liệu được trả về từ API của họ, Sự lặp đi lặp lại trong cấu trúc dữ liệu đơn giản đó, làm mình phải code đi code lại một đoạn code, không thích điều đó nên mình mới phát triển nó thành một kiểu map tương tự như trong facebook. và hiện thực nó thành một phiên bản đầu tiên của pattern này trong plugin SmartCrop. Trong phiên bản này mình đặt một map duy nhất ở tại class base.

Dù không trực tiếp đọc code của facebook ngay khi làm và tới thời điểm trước đó thì vẫn chưa hiểu nó, nhưng rõ ràng, là chính nhờ đã đọc trước nên cách hiện thực này mới được hình thành. Não thật là kỳ diệu, nên có một bài học được rút ra là “cứ đọc và thực hành” ( nghe vô duyên ghê ).

Bộ não này thật là thứ vô giá, nhưng nó lại rất mong manh. Thật lãng phí cho từng giây phút ta dùng nó làm chuyện vô ích, càng lãng phí hơn khi để mua vui mà ta dùng hóa chất ức chết hoạt động của nó.