2012-08-12 5 views
5

Moja aplikacja ma InstrumentFactory - jedyne miejsce, w którym utworzę instancję Instrument. Każda instancja instrumentu zawiera kilka pól, takich jak Ticker=MSFT i GateId=1, a także unikatowe Id =1.Kiedy potrzebuję jakiegoś przedmiotu, powinienem zamiast tego użyć jego "int id"?

I teraz zdałem sobie sprawę, że prawie nigdy nie potrzebuję instancji Instrument. W 90% przypadków potrzebuję tylko Id. Na przykład teraz mam taką metodę:

public InstrumentInfo GetInstrumentInfo(Instrument instrument) 
{ 
    return instrumentInfos[instrument.Id]; 
} 

Wiemy, że nie powinniśmy przekazywać parametrów więcej informacji niż jest to wymagane. Więc ten kod prawdopodobnie należy refactored:

public InstrumentInfo GetInstrumentInfo(int instrumentId) 
{ 
    return instrumentInfos[instrumentId]; 
} 

90% mojego kodu można teraz refactored używać instrumentId zamiast Instrument.

Czy powinienem to zrobić? Zmiana wszędzie Instrument na instrumentId sprawi, że będzie to trudne (każdy Instrument powinien mieć dokładnie jeden unikalny identyfikator). Ale jakie korzyści będę miał? W zamian za "twarde wymagania" chcę mieć jakieś zalety ... (szybkość, czytelność?) Ale ich nie widzę.

+0

Bardzo ładne pytanie. +1 – Mohayemin

+1

A może GetInstrumentInfo powinien być metodą na instrumencie? –

+0

@Peri ma bardzo dobry punkt. A może zdobywca nieruchomości byłby jeszcze lepszy. –

Odpowiedz

4

Używanie identyfikatorów ids wszędzie zamiast obiektów jest błędnym podejściem i jest sprzeczne z duchem OOP.

Istnieją dwie wielkie zalety stosowania samego obiektu:

  1. To typ bezpieczny. Nie możesz przypadkowo przekazać czegoś podobnego do pierwszej wersji, ale możesz przypadkowo przekazać person.Id do drugiej.
  2. Ułatwia modyfikację kodu. Jeśli w przyszłości zdecydujesz, że potrzebujesz long ids, lub w inny sposób, aby zidentyfikować unikalny Instrument, nie będziesz musiał zmieniać kodu wywołującego.

Prawdopodobnie powinieneś również zmienić słownik, powinien on być czymś w rodzaju Dictionary<Instrument, InstrumentInfo>, a nie Dictionary<int, InstrumentInfo>, tak jak teraz. W ten sposób uzyskujesz obydwie zalety. Aby to zadziałało, musisz zaimplementować równość w Instrument, co oznacza prawidłowe przesłonięcie Equals() i GetHashCode(), a najlepiej także wdrożenie IEquatable<Instrument>.

+0

Nie używam słownika. Używam tablicy dla celów wydajności. więc uzyskuję do niego dostęp poprzez indeks "int". – javapowered

+0

Czy te powody są prawdziwe? Najpierw powinieneś napisać czysty kod, a jeśli okaże się, że jest zbyt wolny (jak pokazuje profilowanie), to zoptymalizuj go. – svick

+0

w oprogramowaniu HFT powinieneś po prostu najszybszy kod :) – javapowered

1

Zawsze lepiej jest pracować pod względem obiektów niż wartości pierwotne, takie jak liczby całkowite. Jeśli jutro twoje wymagania się zmienią i potrzebujesz czegoś więcej niż tylko ID, możesz je łatwo dodać do obiektu Instrument zamiast zmieniać cały kod.

-1

Można przeciążać każdą funkcję, taki, który bierze instrument i taki, który bierze ID:

public InstrumentInfo GetInstrumentInfo(Instrument instrument) 
{ 
    // call GetInstrumentInfo passing the id of the object 
    return GetInstrumentInfo[instrument.Id]; 
} 

public InstrumentInfo GetInstrumentInfo(int instrumentId) 
{ 
    return instrumentInfos[instrumentId]; 
} 

To daje wystarczającą elastyczność, tak że podczas przechodzenia przez miejsca, które nazywa GetInstrumentInfo go zmienić pass id, bieżący kod będzie nadal działać.

Od tego, czy "powinieneś", czy nie, zależy wyłącznie od Ciebie. Trzeba by rozważyć, ile czasu zajmie zmienienie go w porównaniu z korzyścią wprowadzenia zmiany w kodzie.

+0

Jakieś wyjaśnienie sprawy w dół? –

1
GetInstrumentInfo(int instrumentId); 

To prawdopodobnie oznacza, że ​​kod klienta musi mieć:

GetInstrumentInfo(instrument.Id); 

Nie pozwól użytkownikom metody swojej martwić o drobne szczegóły, jak to. Pozwól im po prostu przekazać cały obiekt i pozwól swojej metodzie wykonać pracę.

Nie widać żadnych poważnych wad wydajności. Niezależnie od tego, czy przekazujesz Int, czy odwołanie do rzeczywistego obiektu.

Załóżmy, że chcesz stworzyć GetInstrumentInfo nieco bardziej, łatwiej jest uzyskać dostęp do całego obiektu niż tylko Int.

1

Pierwszą rzeczą, którą trzeba sobie zadać to:

„Jeśli mam dwa instrumenty z id == 53, wtedy to znaczy są one zdecydowanie ten sam dokument, bez względu na to co i czy istnieje? znaczący przypadek, w którym mogłyby być inne? "

Zakładając, że odpowiedź brzmi: "oba są takie same: jeśli jakakolwiek inna właściwość jest różna, oznacza to albo błąd, albo ponieważ jeden taki obiekt został uzyskany za drugim, i że sam się wkrótce rozwiąże (kiedy dowolny wątek przetwarzania jest używając starszego instrumentu, przestaje go używać) "następnie:

Po pierwsze, po prostu użyj tego, co znajdziesz pod ręką. Najprawdopodobniej okaże się, że ma to być cały czas przez int, chociaż masz pewne bezpieczeństwo typu od nalegania, aby Instrument został przekazany do metody. Jest to szczególnie ważne, jeśli cała konstrukcja Instrument dzieje się z konstruktora internal lub private dostępnego za pośrednictwem metod fabrycznych, a użytkownik kodu nie może utworzyć fałszywego Instrument z identyfikatorem, który nie pasuje do niczego w systemie.

Definiowanie równości jako takie:

public class Instrument : IEquatable<Instrument> 
{ 
    /* all the useful stuff you already have */ 
    public bool Equals(Instrument other) 
    { 
    return other != null && Id == other.Id; 
    } 
    public override bool Equals(object other) 
    { 
    return Equals(other as Instrument); 
    } 
    public override int GetHashCode() 
    { 
    return Id; 
    } 
} 

Teraz, zwłaszcza gdy weźmiemy pod uwagę, że powyższe jest prawdopodobnie inlined większość czasu, istnieje dość dużo ma różnicy realizacji, czy używamy identyfikatora lub obiekt pod względem równości, a więc także pod względem wykorzystania ich jako klucza.

Teraz można definiować wszystkich metod publicznych w którymkolwiek z następujących środków:

public InstrumentInfo GetInstrumentInfo(Instrument instrument) 
{ 
    return instrumentInfos[instrument]; 
} 

Lub:

public InstrumentInfo GetInstrumentInfo(Instrument instrument) 
{ 
    return instrumentInfos[instrument.Id]; 
} 

Lub:

public InstrumentInfo GetInstrumentInfo(Instrument instrument) 
{ 
    return GetInstrumentInfo(instrument.Id); 
} 
private InstrumentInfo GetInstrumentInfo(int instrumentID) 
{ 
    return instrumentInfos[instrumentID] 
} 

Wpływ Wydajność być tym samym, niezależnie od tego, do którego się wybierasz. Kod przedstawiony użytkownikom będzie bezpieczny dla typu i zagwarantuje, że nie przekazuje fałszywych wartości. Wybrana implementacja może być po prostu wygodniejsza z innych powodów.

Ponieważ nie będzie cię to już kosztować używanie instrumentu jako klucza wewnętrznie, nadal zalecałbym to (jako pierwszą z trzech powyższych opcji) jako bezpieczeństwo typu i utrudniając przekazanie fałszywych wartości będzie również obowiązywało w twoim wewnętrznym kodzie. Jeśli z drugiej strony okaże się, że zestaw wywołań nadal używa identyfikatora (np.rozmawiają z warstwą bazy danych, której tylko ID oznacza cokolwiek), a następnie zmiana tylko tych miejsc staje się szybka i łatwa dla Ciebie i ukryta przed użytkownikiem.

Dajesz także użytkownikom możliwość użycia obiektu jako klucza i szybkiego porównywania równości, jeśli im to odpowiada.

+0

Posiadam InstrumentFactory, który gwarantuje, że zawsze mam tylko jedną instancję Instrumentu dla każdego Id. Również fabryka ma kilka metod LookUp, takich jak 'public Instrument Lookup (int gateId, string ticker)' – javapowered

+0

Jeśli istnieje gwarantowane pojedyncze wystąpienie globalnie, nie potrzebujesz tego nawet, ponieważ domyślny obiekt równości i kod skrótu będą działać, aby uzyskać '. Instrument "jako klucz". (Jeśli obiekty są zmienne, wątki mogą być trudne). –

Powiązane problemy