2009-10-11 16 views
5

Czy są jakieś sprawdzone metody zwracania różnych typów zwracania na przeciążonych metodach? Na przykład, jeśli mam metodę ładowania w moim DAL, chcę załadować pojedynczy element lub kilka elementów. Wiem, że mogę korzystać z wielu metod:Czy powinienem używać różnych typów zwrotu na przeciążonych metodach?

Załaduj jeden obiekt

MyBusinessObject LoadOne(int id) 
{ 
} 

Ładowanie wielu obiektów

MyBusinessObject[] LoadMany(params int[] ids) 
{ 
} 

Teraz coś wiem może zrobić, to przeciążenie jednej metody i mają różne typy zwrotu. Tak:

MyBusinessObject Load(int id) 
{ 
} 

I

MyBusinessObject[] Load(params int[] ids) 
{ 
} 

Choć wydaje się, nie ma nic, aby zatrzymać mnie w ten sposób, a to sprawia, że ​​coś schludne z perspektywy API, czy to wydawać się dobrym pomysłem? Natknąłem się na niego wczoraj wieczorem i część mnie myśli, że nie powinienem tego robić z powodu konieczności dopasowywania typów powrotu dla przeciążonej metody.

Mogę również mieć metodę Load (int id) zwracającą kolekcję, która zawiera tylko jeden przedmiot. Wydaje mi się, że narusza to zasadę najmniejszego zaskoczenia, ponieważ jeśli spodziewasz się zwrotu jednego elementu, powinieneś zwrócić ten przedmiot, nie powinieneś zwracać listy zawierającej pojedynczy przedmiot.

Więc tutaj są moje myśli na otaczające te pomysły:

  • Przeciążone metody powinno wszystko wrócić tego samego typu.
  • Jeśli metody robią to samo, nie nadawaj im kilku różnych nazw, przeciąż tę samą nazwę metody. Ułatwia to pracę z perspektywy użytkownika API, nie musi przeszukiwać wielu różnych metod, które zasadniczo robią to samo, ale z różnymi parametrami.
  • Zwróć najbardziej oczywisty typ metody, tj. Jeśli użytkownik prawdopodobnie oczekuje kolekcji przedmiotów, zwróć kolekcję przedmiotów, jeśli najprawdopodobniej spodziewają się jednego przedmiotu, zwróć pojedynczy przedmiot.

Dwie ostatnie myśli przeważają nad pierwszą, ale jednocześnie pierwsza myśl wydaje się być programową najlepszą praktyką.

Czy istnieją najlepsze praktyki dotyczące tej praktyki? Byłbym zainteresowany wysłuchaniem myśli innych na ten temat.

+0

W każdym przypadku rozważ proszę zwrócić 'IEnumerable ' zamiast tablicy. Eric Lippert ma świetny post na blogu na ten temat. –

+0

wystarczy zwrócić tablicę, aby podświetlić scenariusz. Zwróciłbym IEnumerable w moim rzeczywistym kodzie. – BenAlabaster

+0

Okay, fajnie. Tak długo, jak jesteście świadomi. –

Odpowiedz

8

I może być skłonny do API wyraźne i używać wielu w nazwach:

Customer LoadCustomer(int id) {...} 
Customer[] LoadCustomers(params int[] id) {...} 

Właściwie params jest rzadko przydatna tutaj - nie wiem, identyfikatory zwykle w czasie kompilacji.

+0

W odniesieniu do params, rozumiem twój punkt widzenia, ale podkreślałem pojęcie zamiast rzeczywistej ścieżki kodu. Wyobrażam sobie, że w prawdziwym scenariuszu przekazywałbym informacje filtrujące, które zwróciłyby potencjalnie listę przedmiotów, a nie pojedynczy przedmiot. Podoba mi się idea mnogości, z pewnością utrzymałaby wiele metod w intellisense. – BenAlabaster

0

Mój osobisty pomysł jest taki, że ta ostatnia metoda wydaje się bardziej zrozumiała z punktu widzenia API-użytkownika.

3

Wystarczy spojrzeć na istniejące interfejsy API. Weźmy na przykład LINQ, ma metodę "Select", która zwraca wiele encji, a także metodę "Single", która zwraca tylko jedną encję. Większość istniejących interfejsów API ma dwie różne metody, a nie przeładowane i uważam, że jest to logiczne i bardziej czytelne.

+0

Ale oznacza to również, że twój interfejs API jest zaśmiecony wieloma metodami, które robią to samo. – BenAlabaster

+0

Poza tym, naśladowanie API innych osób jako przykładu nie pomaga w zrozumieniu ich procesów myślowych za zaprojektowanie tego w ten sposób. Wolałbym zobaczyć pół tuzina różnych przykładów * z * procesami myślowymi niż bez API. W ten sposób mogę podjąć świadomą decyzję, zamiast ślepo podążać za czyimś przykładem. – BenAlabaster

+0

Nie jestem ślepym naśladowcą =) Napisałem swoją opinię, a wiodące technologie zasługują na moją uwagę jako minimum. Nawiasem mówiąc, zdobycie jednego bytu i uzyskanie wielu podmiotów nie jest tym samym. – Restuta

2

Mam tendencję do podążania za pierwszym punktem na liście "myślami stanowiącymi ten pomysł", który mówi "przeciążenia powinny powrócić tego samego typu".

ale można wtedy przeciążać "LoadMany" kilkoma różnymi scenariuszami;

public Customer Load(int id) 
{ 
    // return just one customer 
} 

public List<Customer> LoadMany() 
{ 
    // return every single customer 
} 

public List<Customer> LoadMany(int statusFilter) 
{ 
    // return a filtered list of customers 
} 

public List<Customer> LoadMany(DateTime InitialContactFrom) 
{ 
    // return a filtered list of customers 
} 

public List<Customer> LoadMany(DateTime InitialContactFrom, DateTime InitialContactBefore) 
{ 
    // return a filtered list of customers 
} 

... dowolne potrzebne kombinacje można oczywiście dodać, ale na końcu LoadMany zwraca listę, a Load zwraca jeden obiekt.

3

Są prawdopodobnie wyjątki, ale jeśli nie masz naprawdę dobrego powodu, aby zwracać różne typy, funkcja i jej przeciążenia powinny zwracać ten sam typ, aby nie doprowadzać innych deweloperów do szaleństwa.

Na przykład:

var a = MyFunc("Some text"); 

i

var a = MyFunc(1); 

zarówno wyglądają jak powinny one rozwiązać var ​​do tego samego typu do mnie. Zanim zrezygnowałem z tego, że wszystkie przeciążenia zwracają ten sam typ, upewniłem się, że mam bardzo solidny powód do zwrócenia różnych typów.

+0

Fajnie, nie brałem pod uwagę perspektywy var, która w rzeczywistości narusza moją zasadę, aby każda linia była jak najbardziej zrozumiała w odniesieniu do jak najmniejszego innego kodu. – BenAlabaster

Powiązane problemy