Tìm hiểu Google protocol buffer

Chào mừng các bạn đã quay lại với thachleblog. Ở bài trước, mình có giới thiệu về serialize và deserialize để convert object sang dạng byte stream (và ngược lại). Tuy nhiên, dữ liệu dạng byte stream này không thể chia sẻ cho các ứng dụng được viết bằng các ngôn ngữ khác. Google có phát triển một platform để giải quyết vấn đề này chính là Protocol Buffer (viết tắt là protobuf). Protobuf giải quyết vấn đề này như thế nào? Cơ chế hoạt động ra sao, chúng ta cùng tìm hiểu nhé.

Giới thiệu

Protocol Buffer là một platform được phát triển bởi google được sử dụng để serialize dữ liệu thành dạng byte stream (tương tự Thrift của facebook và Microsoft Bond protocols). Phiên bản đầu tiên được giới thiệu vào năm 2008, phiên bản mới nhất hiện tại là 3.3.0.

Ưu điểm

Như mình đã đề cập ở phần giới thiệu, protobuf giải quyết vấn đề của serialize trong Java đó là dữ liệu được serialize chỉ đọc được bởi Java. Dữ liệu được serialize bởi protobuf có thể được deserialize bằng các ngôn ngữ khác nhau.

Ngoài ra, dữ liệu protobuf nhẹ và nhanh hơn so với xml và json, sau đây là so sánh giữa dữ liệu protobuf và XML:

  • Dữ liệu protobuf “nhẹ hơn” từ 3 – 10 lần
  • Protobuf xử lý nhanh hơn 20 – 100 lần

Nguồn: https://developers.google.com/protocol-buffers/docs/javatutorial

Cơ chế hoạt động

Protobuf cho phép định nghĩa object dưới dạng struct (message) với định dạng .proto. File này sẽ được dùng chung để protobuf compiler compile sang các ngôn ngữ tương ứng. Do đó, object này có thể được sử dụng bởi các ngôn ngữ khác nhau. Về cơ chế mình cũng thấy giống giống như JVM. Các bạn có thể xem lại bài Tại sao Java là một ngôn ngữ lập trình độc lập nền tảng?

Tìm hiểu Google protocol buffer

Hình minh họa vai trò của protocal buffer compiler

Cài đặt và sử dụng

Đầu tiên chúng ta sẽ cần tải protobuf compiler tại https://github.com/google/protobuf/releases, có bản cho cả windown, linux và macos.

Sau khi giải nén là ta đã có thể sử dụng. Kiểm tra version bằng lệnh: protoc –version

Tiếp theo, chúng ta cần định nghĩa file .proto theo cấu trúc struct, dưới đây là file addressbook mình lấy trong thư mục example:

// [START declaration]
syntax = "proto3";
package tutorial;
// [END declaration]
 
// [START java_declaration]
option java_package = "thach.le.protobuf";
option java_outer_classname = "AddressBookProtos";
// [END java_declaration]
 
 
// [START messages]
message Person {
  string name = 1;
  int32 id = 2;  // Unique ID number for this person.
  string email = 3;
 
  enum PhoneType {
    MOBILE = 0;
    HOME = 1;
    WORK = 2;
  }
 
  message PhoneNumber {
    string number = 1;
    PhoneType type = 2;
  }
 
  repeated PhoneNumber phones = 4;
}
 
// Our address book file is just one of these.
message AddressBook {
  repeated Person people = 1;
}
// [END messages]

Sau khi đã có file .proto, chúng ta có thể build thành các file tương ứng, dưới đây mình build cho java và js.

  • protoc -I=C:\protoc-3.3.0-win32\bin\source —java_out=build C:\protoc-3.3.0-win32\bin\source\addressbook.proto
  • protoc -I=C:\protoc-3.3.0-win32\bin\source —js_out=library=AddressBook,binary:. C:\protoc-3.3.0-win32\bin\source\addressbook.proto

Vì mình không xét CLASS_PATH cho protoc nên mình phải truyền đường dẫn tuyệt đối cho file input. Các bạn có thể đọc thêm để hiểu cú pháp generate file này.

Kiểm tra thư mục C:\protoc-3.3.0-win32\bin\source, giờ thì các bạn đã có các file Java và JS để có thể serialize và deserialize object. Các bạn có thể tham khảo cách sử dụng cách sử dụng probuf object cho Java và JS tại đây.

Kết

Tuần vừa rồi thì mình có làm ứng dụng web chat (360live.vn/live) có sử dụng probufer, thật sự thì mình thấy việc trao đổi dữ liệu giữa server và client thông qua probufer rất dễ dàng và nhanh. Hy vọng bài viết của mình sẽ giúp các bạn tiếp cận nhanh hơn với protobufer…

Mọi thắc mắc, góp ý vui lòng comment bên dưới. Xin cảm ơn và hẹn gặp lại các bạn ở các bài viết sau.

Tham khảo thêm:

https://developers.google.com/protocol-buffers/docs/overview

https://github.com/google/protobuf/tree/master/js

https://developers.google.com/protocol-buffers/docs/javatutorial

Clean Code

Bất kỳ kẻ ngu ngốc nào cũng có thể viết code mà máy tính có thể hiểu

Lập trình viên giỏi là người viết code để con người có thể hiểu.

Martin Fowler, 2008

Chào mừng các bạn đã quay trở lại với thachleblog. Bài viết hôm nay mình sẽ nói về chủ đề Clean Code trong Java. Clean Code là chủ đề tuy không mới nhưng sẽ không bao giờ là cũ. Đối với mỗi người, chắc hẳn ai cũng có lúc “cảm thấy tự hào” với những dòng code của mình. Tuy nhiên, sau một thời gian vài tháng đến một năm, phần lớn khi đọc lại, chúng ta sẽ cảm thấy cái thứ mà mình tự hào trước kia giờ như đống shi* :))).

Do đó, bài viết hôm này mình mong muốn chia sẻ với các bạn 1 vài kinh nghiệm đã học được và áp dụng để code rõ ràng và dễ đọc hơn. Tất nhiên, sẽ rất thiếu sót, do đó, cũng rất mong các bạn cùng chia sẻ để mình cập nhật thêm. Nào, chúng ta cùng bắt đầu nhé.

Nói về lợi ích của Clean Code, rất đơn giản. Code sẽ dễ đọc, ít khả năng gây ra bug và dễ bảo trì, nâng cấp hơn. Vậy làm thế nào để code trở nên “clean”? Dưới đây là vài điều mình đã học được trong cuốn “Clean Code” và trong quá trình làm việc:

– Đặt tên

+ Class, Object nên là danh từ hoặc cụm danh từ

+ Method nên sử dụng động từ hoặc cụm động từ

Class, object, variable, method tốt nhất sẽ cần trả lời được 3 câu hỏi: nó là cái gì (what), nó để làm gì (why) và dùng như thế nào (how).

Tên rất quan trọng, tên rõ ràng sẽ giúp chúng ta hiểu được business của method, class, module một cách dễ dàng. Cùng xem ví dụ sau:

public List<int[]> getThem() {
	List<int[]> list1 = new ArrayList<int[]>();
	for (int[] x : theList)
		if (x[0] == 4)
		list1.add(x);
		return list1;
}

Giả sử bạn debug đến đoạn code này, bạn sẽ nghĩ gì? Các cái tên getThem(), x, list1 củ chuối rồi, còn thêm cái số 4 “huyền bí”, sao lại là “4”? Sẽ mất thời gian để hiểu logic của method trên.
Chúng ta đến với đoạn code khác:

public List<int[]> getFlaggedCells() {
	List<int[]> flaggedCells = new ArrayList<int[]>();
	for (int[] cell : gameBoard)
		if (cell[STATUS_VALUE] == FLAGGED)
		flaggedCells.add(cell);
		return flaggedCells;
}

Đoạn code này có gì khác biệt? Những cái tên rõ ràng hơn, method sẽ có chức năng lấy danh sách những “Cell” được đánh dấu (flagged). Đoạn for thì ra là duyệt tất cả các cell trên gameBoard nếu status là “flagged” thì sẽ “get”. Có vẻ rõ ràng và dễ hiểu hơn. Like!

Tuy nhiên vẫn còn chỗ có thể làm tốt hơn, ta cùng xem đoạn code sau

public List<Cell> getFlaggedCells() {
	List<Cell> flaggedCells = new ArrayList<Cell>();
	for (Cell cell : gameBoard)
		if (cell.isFlagged())
		flaggedCells.add(cell);
		return flaggedCells;
}

Đoạn code sẽ rõ ràng hơn khi ta tạo class Cell thay cho int[].

Chúng ta qua phần tiếp theo

– Không return null

List<Employee> employees = getEmployees();
	if (employees != null) {
		for(Employee e : employees) {
			totalPay += e.getPay();
		}
}

Đối với đoạn code trên, để code “clean” hơn và giảm khả năng xảy ra NullPointerException, chúng ta cần trị ở “gốc”, tức là sẽ không bao giờ return về 1 giá trị null.

Đoạn code getEmployees() sẽ có đoạn như sau:

public List<Employee> getEmployees() {
	if( .. there are no employees .. )
	return Collections.emptyList();
}

– Sử dụng các thư viện

Sử dụng các thư viện (libs) có sẵn NumberUtils, StringUtils, IOUtils, CollectionUtils…. sẽ giúp chúng ta giảm thiểu thời gian code và debug vì đối với libs tốt thì khả năng xảy ra lỗi là rất hiếm. Cùng xem ví dụ đơn giản sau:

 NumberUtils.toInt(studentId, 0)

Đoạn code trên sẽ trả về giá trị mặc định là 0 nếu studentId là null, empty hoặc không hợp lệ. Nếu tự viết, chúng ta sẽ mất thời gian để xử lý những điều trên và đôi khi phát sinh lỗi không đáng có.

– Một vài lưu ý khác

– Sử dụng properties hoặc final variable cho các instant

– Clean đúng nghĩa đen: xóa các packages, classes, methods, fields, parameters, variables không sử dụng. (tránh comment để đó, nhìn rất “gai” ^.^)

– Chia nhỏ method nhất có thể (mỗi method chỉ thể hiện 1 chức năng)

– Viết các method thường được sử dụng thành class Utils để sử dụng lại code, tránh trùng lặp code

Sẽ cập nhật thêm ….

Hẹn gặp lại các bạn ở các bài viết sau.

Tham khảo thêm: Clean Code – Robert C.Martin