Hôm nay đồng nghiệp hỏi câu này: Tại sao nên viết như #a thay vì #b?

Tôi mở rộng câu hỏi thành: Sắp xếp các cách viết sau theo thứ tự “tốt dần”.

Khá khó để nói #3 và #4, cách nào tốt hơn; nhưng có thể dễ dàng khẳng định #1 và #2 không tốt bằng #3, #4. Tại sao?

Nguyên tắc chung của lập trình hướng đối tượng là trừu tượng hoá và cố gắng tối đa việc trừu tượng hoá. Trừu tượng (không phải là giải pháp toàn vẹn nhưng) là một phần trong cách tư duy về Open / Closed principle. #1 rất trực quan và dễ hiểu: tạo một danh sách lưu trữ sách dưới dạng ArrayList. Nhưng những thứ cụ thể rất khó để sửa đổi và thay thế. Ví dụ, sau khi implement, chúng ta phát hiện ra đoạn code phía sau sử dụng rất nhiều thao tác thêm phần tử vào list thay vì lấy phần tử ra; do đó lưu trữ dưới dạng Stack cho hiệu suất tốt hơn; chúng ta phải sửa đổi các đoạn code phía dưới với implement cụ thể của Stack (thay cho ArrayList). Một thời gian sau, nhu cầu lấy phần tử từ list đủ nhiều để sử dụng ArrayList cho hiệu suất tốt hơn, chúng ta phải sửa lại đoạn code phía dưới với implement cụ thể của ArrayList. (Tham khảo: hiệu suất các implement của List). Khổ chưa?

Một cách thông minh hơn là sử dụng #3, khi đó, đoạn code phía dưới chỉ sử dụng những method được định nghĩa cho interface List. Khi cần thay đổi implement cụ thể thành Stack, LinkedList…, chúng ta chỉ đơn giản thay new List<Book>() bởi new Stack<Book>() hay new LinkedList<Book>(). 

Và theo cách tư duy đó, #4 tốt hơn #3? Không hẳn, nếu chúng ta đã xác định list chỉ chứa Book, việc khai báo list chứa Object khiến chúng ta có thể mất công cast những object này trong trường hợp sử dụng những method cụ thể của Book (và thường là vậy). Nên dùng #4 thường là bất lợi hơn #3 (trừ trường hợp list chữa những object khác ngoài Book).

Do đó, sử dụng #3 (khai báo interface và khởi tạo bằng class (đương nhiên)) thường là cách viết nên được “quen tay”.

Thật ra #3 còn nên viết theo 1 cách khác tốt hơn như sau. Tại sao nhỉ?

490 total views, no views today

In my opinion, iterating through a collection is very basic and simple thing because it appears in any developer’s code everyday (of course in the languages support collection).

It’s normally my simplest question to start the interview to warmup and make the candidate more confident. But I’m wrong. I’m so surprised that 90% of our candidates, who have been (senior) developers for 2-3 years, cannot give the right answer:

Let say I have a collection LinkedList<int> list. What are differences between 2 types of iterating through list:

and

Most of answer I got is “we can have the index by #1 code that we cannot have in #2 code. The performance are the same.”. But it’s incorrect, #1 is really bad code in performance wise.

The performance are the same in the index-based collection, like array or ArrayList. But #1 code is very slow in other collection like LinkedList. The reason is for getting the item at index i (by calling get(i) method), LinkedList needs to iterate from the first item with the counter set to 0, increase it in each step and stop when the counter reach to i. So while the notation of #1 code is O(N2), the notation of #2 code is O(N).

#2 code actually works as

#3 code is exactly the way #2 code works before Java introduced for each syntax.

The best solution is always use #2 code for iterating through any collection. If you are worry about the index, another code would be:

Java is just a used language here but I believe this way works in any language today. Whatever the technology you are chasing, let start from the basic things, language and data structure.

515 total views, 1 views today