Co jest złego w zwracaniu hashtable z metody publicznej i kiedy ma to sens?

9

Jakie są problemy projektowe przy zwracaniu tablicy hasht z publicznej metody, gdy chcesz zwrócić wiele elementów zamiast tworzyć klasę i zwracać jej obiekt?

Jeśli ma problemy, to w jakich okolicznościach ma to sens?

Jak zmienia się odpowiedź na to pytanie w zależności od tego, czy język jest dynamiczny, czy nie?

Edycja: Poprawka ma na celu wyjaśnienie, że klucze byłyby stałe i są częścią kodu, a nie danych. Coś, dla czego zazwyczaj tworzymy klasę. Pytanie brzmi, dlaczego niewłaściwe byłoby używanie hashtable zamiast tego, jeśli tworzenie klasy rzeczywiście wydaje się właściwym wyborem.

Muhammad Hasan Khan
źródło

Odpowiedzi:

11

Użyj lepiej zdefiniowanej klasy jako typu zwracanego niż tablica mieszająca, która przechowuje dowolną liczbę wartości jako pary nazwa / wartość.

  1. Pierwszym i najważniejszym punktem jest - łatwość konserwacji. Patrząc na kod, nowy programista nigdy nie może powiedzieć, jakie wartości zwraca metoda. Jeśli nowa osoba nie zrozumie tego, patrząc na kod, kod nie będzie przydatny i podatny na błędy, ilekroć ktoś doda więcej kluczy / wartości do tych danych lub ulepszy aplikację.

  2. Metody to umowy między dzwoniącym a usługą. Najważniejszą rzeczą w metodzie jest ich wejście i wyjście. Te dane wejściowe i wyjściowe powinny być łatwe do odczytania, zrozumiałe i samok dokumentujące. Jeśli użyjesz klasy Person jako wartości zwracanej, która ma imię, nazwisko, wiek - jest to samo dokumentowanie. Jeśli wygenerujesz Javadoc w tym celu, użytkownik może nawigować między klasami, aby lepiej to zrozumieć. Jeśli używasz hashtable, musisz albo wyjaśnić to w komentarzach, których nikt nie przeczyta ani nie zaktualizuje, gdy coś się zmieni.

  3. Nie możesz używać ogólnych, takich jak HashMap<String,String>w przypadku, gdy chcesz dodać liczbę (powiedzmy wiek) do instrukcji return. Jeśli nie używasz ogólnych, będziesz musiał rzucać w przód iw tył między obiektem do rzeczywistego typu. Możesz to zapisać, jeśli używasz pisania dynamicznego.

  4. Ponadto istnieje większe prawdopodobieństwo awarii środowiska wykonawczego niż wychwycenia problemów w czasie kompilacji. np. jeśli ktoś usunie wpis z mapy skrótów i jeden ze starych dzwoniących oczekuje wpisu, klient zawiedzie podczas działania. Zawsze lepiej jest złapać ten problem w czasie kompilacji.

  5. Zwrócenie niezmiennego typu będzie trudne, jeśli chcesz użyć skrótu jako typu zwrotu i tak dalej. Ale jeśli używasz zdefiniowanego przez użytkownika własnego typu, możesz to kontrolować.

Kuszące będzie użycie skrótu jako typu zwracanego, ponieważ można uniknąć tworzenia kilku klas na początku, ale utrzymanie kodu w przyszłości będzie koszmarem. Idź zorientowany obiektowo !!!!

java_mouse
źródło
1
Wygląda na to, że poprawnie zrozumiałeś pytanie. Dzięki.
Muhammad Hasan Khan
8

Jednym z problemów byłoby to, że w wielu przypadkach kluczem tabeli skrótów byłby ciąg znaków. Dlatego konsumenci tej metody musieliby wiedzieć, jakich kluczy użyć do wyodrębnienia danych. Dałoby to możliwość wystąpienia błędów spowodowanych błędami w pisowni podczas uzyskiwania dostępu do danych.

Kolejną wadą jest zdolność do refaktoryzacji. Jeśli później zdecydujesz się zmienić nazwisko członka, będziesz mieć kilka magicznych ciągów, które również należy zmienić. O wiele łatwiej jest zmienić nazwę członka klasy za pomocą narzędzi do refaktoryzacji dostarczanych przez większość dobrych IDE. W przypadku tabeli skrótów prawdopodobnie będziesz musiał wykonać operację znajdowania / zastępowania wszystkich plików źródłowych, co może być problematyczne.

Na koniec stracisz sprawdzanie czasu kompilacji dostępu członka - zarówno pod względem nazwy, jak i typu. To ostatnie nie stanowi problemu, jeśli twoja tabela skrótów zawiera tylko jeden typ obejct, ale jeśli zawiera wiele (nawet w tym samym łańcuchu hierarchii), naprawdę chcesz wykorzystać system typów swojego języka i sprawdzić tam czas kompilacji. W większości IDE będziesz mieć jakieś funkcje inteligentnego / autouzupełniania - działają one patrząc na system typów, ale nie będą w stanie pomóc ci z kluczami tabeli skrótów.

Jeśli chodzi o czasy, w których wskazane byłoby zwrócenie tabeli skrótów (lub innej takiej kolekcji par wartości klucza), można jej użyć, gdy zarówno wartości, jak i klucze nie są znane w czasie kompilacji. Na przykład, jeśli masz metodę, która analizuje ciąg zapytania i zwraca klucze i odpowiadające im wartości, tabela skrótów byłaby dobrym wyborem. W takim przypadku warto również pomyśleć o zwróceniu pewnego rodzaju niezmiennej lub tylko do odczytu tabeli mieszającej.

Edycja - większość punktów poruszonych w tej odpowiedzi przestaje mieć zastosowanie, gdy mówisz o dynamicznych językach :)

MattDavey
źródło
Co jeśli język jest dynamiczny?
Muhammad Hasan Khan
Nie jestem ekspertem w dziedzinie języków dynamicznych, więc ktoś inny prawdopodobnie udzieli lepszej odpowiedzi na to pytanie. Ale wiem, że języki dynamiczne i tak nie sprawdzają typu czasu kompilacji. Ale w takim przypadku zwracanie obiektu i zwracanie tablicy skrótów nie jest tak odmienne ...
MattDavey 31.01.12
3
@Hasan Khan: W takim przypadku może nie być żadnej różnicy między instancją typu hashtable a instancją klasy. Na przykład w JavaScript wszystkie obiekty tablicami hashtable, a object.property jest dokładnie tym samym, co object ['property']
Michael Borgwardt
„W przypadku tabeli skrótów prawdopodobnie będziesz musiał wykonać operację znajdowania / zastępowania wszystkich plików źródłowych, co może być problematyczne”. Tylko jeśli wybrałeś słabe klucze i nigdy nie próbowałeś rozdzielić standardowych, aby były zdefiniowane w jednym miejscu ...
Donal Fellows
7

Najważniejszym argumentem przeciwko temu byłoby to, że ujawniasz konsumentowi zbyt wiele informacji. Konsumujący kod musi tylko wiedzieć, że jest to pewnego rodzaju kolekcja klucz-wartość (słownik); to, czy jest zaimplementowane jako skrót, lista skojarzeń, trie lub cokolwiek, jest względnie nieciekawe. Zatem właściwym sposobem byłoby zwrócenie odpowiedniego interfejsu ( IDictionarylub dowolnego innego używanego języka) zamiast rzeczywistego typu.

Wszystko to przy założeniu, że faktycznie potrzebujesz słownika do reprezentowania danych, to znaczy, że dane składają się z par klucz / wartość, gdzie klucze są unikalne wśród zestawu danych i nie można ich naprawić w czasie kompilacji. Jeśli masz wcześniej znane klucze, powinieneś utworzyć odpowiedni typ (lub kilka, zależnie od potrzeb) dla swoich danych. Wszystko sprowadza się do tego, czy traktujesz same klucze jako część danych, czy też część kodu.

EDYCJA :

Aby to wyjaśnić, używam terminu słownik, aby oznaczać najbardziej ogólny typ struktury danych klucz-wartość; Nie mam na myśli żadnej implementacji specyficznej dla języka, takiej jak Python dictlub .NET Dictionary.

tdammers
źródło
1
+1 dla „Wszystko sprowadza się do tego, czy traktujesz same klucze jako część danych, czy część kodu”. - To dobry sposób na wyrażenie tego. Nie jestem pewien, na przykład, jak uniwersalny jest termin „słownik”, a nie „mapa”.
MattDavey,
Zwracanie słownika nie było zamierzone. klucze były częścią kodu, a nie danych.
Muhammad Hasan Khan
Prawdziwe pytanie brzmi: „Powinieneś stworzyć odpowiedni typ”. Pytanie dlaczego?
Muhammad Hasan Khan
2

Jedno pytanie, które sobie zadam, brzmi: „czy klucze zmieniają się w tym słowniku?” Jeśli są stałe, powinieneś zwrócić obiekt lub inną odpowiednią strukturę danych. Jeśli są dynamiczne, możesz chcieć zwrócić jakąś strukturę stylu słownika. Wreszcie, jeśli niektóre klucze będą stałe i jakiś nieznany zestaw kluczy dynamicznych, możesz chcieć zwrócić hybrydową strukturę danych, w tym niektóre stałe wartości i pewnego rodzaju słownik przepełnienia.

Wyatt Barnett
źródło
Rzeczywiście, twoja rada jest prawidłowa, ale pytanie brzmi, co jest złego w wyborze hashtable, gdy lepszym wyborem jest klasa.
Muhammad Hasan Khan
To nie jest albo klasa może łatwo zawierać słownik, jeśli jest potrzebny.
Wyatt Barnett