Có gì sai khi trả lại hashtable từ phương thức công khai và khi nào thì có ý nghĩa như vậy?


9

Các vấn đề thiết kế trong việc trả lại hashtable từ một phương thức công khai khi bạn muốn trả về nhiều mục thay vì tạo một lớp và trả về đối tượng đó là gì?

Nếu nó có vấn đề thì trong trường hợp nào nó có ý nghĩa để làm như vậy?

Làm thế nào để câu trả lời cho câu hỏi này thay đổi tùy thuộc vào ngôn ngữ có năng động hay không?

Chỉnh sửa: Điều này là để làm rõ rằng các khóa sẽ là hằng số và là một phần của mã, không phải dữ liệu. Một cái gì đó mà chúng ta thường tạo ra một lớp cho. Câu hỏi đặt ra là tại sao việc sử dụng hashtable lại thay vì nếu tạo một lớp thực sự có vẻ là lựa chọn đúng.

Câu trả lời:


11

Sử dụng một lớp được xác định tốt hơn làm kiểu trả về hơn là hàm băm chứa số lượng giá trị tùy ý dưới dạng cặp tên / giá trị.

  1. Điểm quan trọng đầu tiên và quan trọng nhất là - Khả năng bảo trì. Bằng cách nhìn vào mã, một lập trình viên mới không bao giờ có thể nói các giá trị mà phương thức đang trả về là gì. Nếu một người mới không hiểu điều này bằng cách xem mã, mã sẽ không hữu ích và dễ bị lỗi mỗi khi ai đó sẽ thêm nhiều khóa / giá trị vào dữ liệu đó hoặc nâng cao ứng dụng.

  2. Phương thức là hợp đồng giữa người gọi và dịch vụ. Điều quan trọng nhất trong một phương thức là đầu vào và đầu ra của chúng. Đầu vào và đầu ra này phải dễ đọc và dễ hiểu và tự ghi lại. Nếu bạn sử dụng một lớp Người làm giá trị trả về có tên, họ, tuổi - Đó là tài liệu tự. Nếu bạn tạo Javadoc cho việc này, người dùng có thể điều hướng giữa các lớp để hiểu rõ hơn về điều này. Nếu bạn sử dụng hashtable, bạn phải giải thích nó trong các bình luận mà không ai sẽ đọc hoặc cập nhật khi mọi thứ thay đổi.

  3. Bạn không thể sử dụng thuốc generic như HashMap<String,String>trong trường hợp nếu bạn muốn thêm một số (nói tuổi) vào câu lệnh return. Nếu bạn không sử dụng thuốc generic, thì bạn sẽ phải chuyển qua lại giữa đối tượng thành loại thực tế. Bạn có thể lưu điều này nếu bạn sử dụng gõ động.

  4. Ngoài ra có nhiều khả năng thất bại thời gian chạy hơn là bắt các vấn đề trong thời gian biên dịch. ví dụ: nếu ai đó xóa một mục khỏi hashmap và một trong những người gọi cũ đang mong đợi mục đó, thì máy khách bị lỗi trong thời gian chạy. Luôn luôn tốt hơn để nắm bắt vấn đề này trong thời gian biên dịch.

  5. Sẽ rất khó để trả về một loại bất biến nếu bạn muốn sử dụng hàm băm làm kiểu trả về, v.v. Nhưng nếu bạn sử dụng một người dùng xác định loại của riêng bạn, bạn có thể kiểm soát điều này.

Sẽ rất hấp dẫn khi sử dụng hàm băm làm kiểu trả về vì bạn có thể tránh tạo một vài lớp ngay từ đầu nhưng sẽ là một cơn ác mộng khi duy trì mã trong tương lai. Đi hướng đối tượng !!!!


1
Bạn dường như đã hiểu chính xác câu hỏi. Cảm ơn.
Muhammad Hasan Khan

8

Một trong những vấn đề là trong nhiều trường hợp, khóa cho bảng băm sẽ là một chuỗi. Vì vậy, người tiêu dùng của phương pháp sẽ phải biết trước khi sử dụng khóa nào để trích xuất dữ liệu. Điều này sẽ tạo ra khả năng xảy ra lỗi do lỗi chính tả khi truy cập dữ liệu.

Một nhược điểm khác là khả năng tái cấu trúc. Nếu sau đó bạn quyết định thay đổi tên của một thành viên, thì bạn có một chuỗi các chuỗi ma thuật cũng cần phải thay đổi. Việc đổi tên một thành viên trong lớp bằng cách sử dụng các công cụ tái cấu trúc được cung cấp bởi hầu hết các IDE tốt là rất đơn giản. Với bảng băm, bạn có thể phải thực hiện thao tác tìm / thay thế trên tất cả các tệp nguồn có thể có vấn đề.

Cuối cùng, bạn sẽ mất thời gian biên dịch kiểm tra quyền truy cập của thành viên - cả về tên và loại. Điều thứ hai không phải là vấn đề như vậy nếu bảng băm của bạn chỉ chứa một loại obejct, nhưng nếu nó chứa nhiều (ngay cả trong cùng một chuỗi phân cấp), bạn thực sự muốn tận dụng hệ thống loại ngôn ngữ của mình và kiểm tra thời gian biên dịch ở đó. Trong hầu hết các IDE, bạn sẽ có một số loại tính năng intellisense / autocomplete - những tính năng này hoạt động bằng cách xem hệ thống loại, nhưng chúng sẽ không thể giúp bạn với các phím bảng băm.

Đối với lần khi nó sẽ là thích hợp để trả về một bảng băm (hoặc bộ sưu tập ví dụ khác của các cặp giá trị key), bạn sẽ sử dụng điều này khi cả các giá trị và các phím không được biết đến tại thời gian biên dịch. Ví dụ: nếu bạn có một phương pháp phân tích chuỗi truy vấn và trả về các khóa & giá trị tương ứng, thì bảng băm sẽ là một lựa chọn tốt. Trong trường hợp này, bạn cũng sẽ muốn nghĩ về việc trả về một loại bảng băm bất biến hoặc chỉ đọc.

Chỉnh sửa - Hầu hết các điểm nêu trong câu trả lời này sẽ ngừng áp dụng khi bạn nói về ngôn ngữ động :)


Nếu ngôn ngữ là động thì sao?
Muhammad Hasan Khan

Tôi không phải là chuyên gia về ngôn ngữ động nên người khác có thể cung cấp câu trả lời tốt hơn cho điều đó. Nhưng tôi biết rằng các ngôn ngữ động không thực hiện kiểm tra kiểu thời gian. Nhưng trong trường hợp đó, việc trả lại một đối tượng và trả lại bảng băm không quá khác biệt ..
MattDavey

3
@Hasan Khan: Trong trường hợp đó thực sự có thể không có bất kỳ sự khác biệt nào giữa một hashtable và một thể hiện của lớp. Ví dụ: trong Javascript, tất cả các đối tượng đều là hashtables và object.property hoàn toàn giống với đối tượng ['property']
Michael Borgwardt

Với một bảng băm, bạn có thể phải thực hiện thao tác tìm / thay thế trên tất cả các tệp nguồn có thể có vấn đề. Chỉ khi bạn chọn khóa kém và không bao giờ cố gắng tìm ra khóa chuẩn để chúng được xác định ở một nơi thì
Donal Fellows

7

Lập luận quan trọng nhất chống lại điều này sẽ là bạn tiết lộ quá nhiều thông tin cho người tiêu dùng. Mã tiêu thụ chỉ cần biết rằng đó là một bộ sưu tập khóa-giá trị (từ điển) nào đó; cho dù nó được triển khai dưới dạng hashmap, danh sách liên kết, trie hay bất cứ thứ gì, đều tương đối không thú vị. Vì vậy, cách thích hợp sẽ là quay trở lại bởi một giao diện phù hợp ( IDictionaryhoặc bất cứ ngôn ngữ nào bạn chọn sử dụng) thay vì theo loại thực tế.

Tất cả điều này giả sử rằng bạn thực sự cần một từ điển để thể hiện dữ liệu của mình, nghĩa là dữ liệu của bạn bao gồm các cặp khóa / giá trị, trong đó các khóa là duy nhất trong số liệu và không thể được sửa trong thời gian biên dịch. Nếu bạn có các khóa được biết trước, bạn nên tạo một loại thích hợp (hoặc một số, theo yêu cầu) cho dữ liệu của bạn. Nó liên quan đến việc bạn coi các khóa là một phần của dữ liệu hay là một phần của mã.

CHỈNH SỬA :

Để làm rõ, tôi đang sử dụng thuật ngữ từ điển có nghĩa là loại cấu trúc dữ liệu khóa-giá trị chung nhất ở đây; Tôi không có nghĩa là bất kỳ triển khai cụ thể ngôn ngữ như Python's dicthoặc .NET Dictionary.


1
+1 cho "Điều này tùy thuộc vào việc bạn coi chính các khóa là một phần của dữ liệu hay là một phần của mã." - Đó là một cách tốt để đặt nó. Chẳng chắc là thuật ngữ 'từ điển' phổ quát như thế nào trái ngược với 'bản đồ' chẳng hạn.
MattDavey

Trả lại từ điển không có ý định. Các khóa là một phần của mã không phải dữ liệu.
Muhammad Hasan Khan

Câu hỏi thực sự là lý do đằng sau 'Bạn nên tạo ra một loại thích hợp'. Câu hỏi là tại sao?
Muhammad Hasan Khan

2

Một câu hỏi tôi tự hỏi mình là "các phím có thay đổi trong từ điển này không?" Nếu chúng là hằng số thì bạn nên trả về một đối tượng hoặc cấu trúc dữ liệu thích hợp khác. Nếu chúng là động thì bạn có thể muốn trả về một số loại cấu trúc kiểu từ điển. Cuối cùng, nếu có một số khóa sẽ không đổi và một số khóa động không xác định, bạn có thể muốn trả về cấu trúc dữ liệu lai bao gồm một số giá trị cố định và một số loại từ điển cho tràn.


Quả thực lời khuyên của bạn là đúng nhưng câu hỏi đặt ra là có gì sai khi chọn sử dụng hashtable khi lớp là một lựa chọn tốt hơn.
Muhammad Hasan Khan

Nó không phải là / hoặc; một lớp có thể dễ dàng chứa từ điển nếu bạn cần nó.
Wyatt Barnett
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.