Mam więc usługę internetową, która ma coś w rodzaju miejsca, w getAccount
którym zwróci identyfikator na konto, jeśli go dostanie, w przeciwnym razie zgłasza wyjątek. Klient zawsze będzie chciał założyć konto, jeśli zgłoszony zostanie wyjątek z tymi samymi informacjami, z którymi jest zrobione.
Tworzę wygodną bibliotekę dla klientów, którzy będą obsługiwać wszystkie wywołania usługi internetowej w środku, więc nie będą musieli wiedzieć, jak samodzielnie wykonywać połączenia.
Zastanawiam się w tej bibliotece, gdybym miał utworzyć getAccount(accountName)
konto, które dostanie konto, jeśli istnieje, a jeśli nie utworzy go i nie zwróci informacji, czy to źle? Czy powinienem pozostawić klientowi obsługę wyjątków, czy po prostu nazwać coś takiego jak getOrCreateAccount? Czy to ma znaczenie?
Czy złym zwyczajem jest tworzenie czegoś w operacji get?
źródło
getOrCreateAccount
lub podobnie.acquire
, npacquireAccount
. Nie ma on żadnego znaczenia w żadnym z głównych protokołów, które napotkałem, i ma nadrzędny pierścień, który mu dobrze pasuje. „Rób wszystko, co musisz zrobić, aby zdobyć dla mnie jeden z nich. Poproś o to, zbuduj, udawaj, ukradnij, nie obchodzi mnie to, po prostu weź mnie lub zgiń próbując”.getSomething()
jest przeznaczony dla osób pobierających isetSomething()
ustawiających. Imo nic, że robi coś bardziej intelektualnego musi być nazywany coś innego, to znaczyfetchSomething
,obtainSomething
,computeSomething
, lubdoSomethingElse
itd.Odpowiedzi:
Tak, to ma znaczenie. Moim zdaniem, generalnie złą praktyką jest tworzenie czegoś w procedurze, która nie jest udokumentowana jako posiadająca moc tworzenia. Nazwij procedurę
getOrCreate...
lub miej osobnącreate...
procedurę, a następnie, jeśli naprawdę chcesz, zróbgetOrCreate...
pierwsze próbyget...
, a jeśli to się nie powiedzie, wywoła,create...
a następnie zadzwoniget...
.Użytkownik biblioteki prawdopodobnie nie spodziewa
get...
się utworzenia procedury, jeśli operacja get nie powiedzie się. Jeśli nagle dowiedzą się, że ich wywołania testowe w celuget...
stworzenia całej tony danych, prawdopodobnie będą raczej zaskoczeni. A jak to sprzątają? Co jeśli piszą kod myślenie, że będą się błąd, jeśliget...
nie powiedzie się i chcą obsługiwać że ich sposób?źródło
get...
create...
get...
tylko dwóch pierwszych. Porozmawiam z klientem o tym, czy kiedykolwiek będzie wymagał zdolności, aby po prostu zadzwonić,get
nie chcąc tworzyćcreate
w nazwie, żeby mieć 100% jasności na temat tego, co się dzieje.getOrCreate
ma pierwszeństwo w popularnym frameworku internetowym: docs.djangoproject.com/en/1.10/ref/models/querysets/…Nie, to nie jest „zła praktyka”. Tak długo, jak ty i inni programiści zgadzacie się, że tak właśnie ma działać, jest w porządku. W końcu to zwróci konto, czego właśnie chcesz. Utworzenie konta „pod maską” nie ma znaczenia dla dzwoniącego.
źródło
Jeśli
getAccount()
zawsze można zwrócić konto, to z punktu widzenia dzwoniącego konto istnieje i zawsze istniało. Nie trzebagetAccount()
niczego „tworzyć”. Konto nie musi być nigdzie przechowywane, dopóki nie będzie inne niż konto domyślne.źródło
GetOrCreate
jest zły semantyczny, ale uzyskanie obiektu, który może „logicznie” istnieć, niezależnie od tego, czy istnieje fizycznie, jest w porządku. Na przykład rzadka tablica zmiennych elementów może nie mieć przydzielonej pamięci dla elementu 1 841 533, ale nadal umożliwia „pobranie” tego elementu przez utworzenie nowego obiektu, przechowanie go i zwrócenie referencji.Najbardziej sensowne jest stworzenie 3 metod:
getAccount -> Który właśnie pobiera konto.
createAccount -> Tworzy konto.
getAccountAndCreateIfNeeded -> Wybierz własne nazewnictwo;)
Dlaczego separacja: masz prostą metodę uzyskiwania i tworzenia. Jest to jasna metoda, którą można przetestować w obu przypadkach. W przypadku getAccount nie jest wyjątkiem, że nie można znaleźć konta. Więc po prostu zwróć false lub coś w tym rodzaju, jest to oczekiwane.
Następnie możesz użyć tej wartości zwracanej w funkcji zgrupowanej: getAccountAndCreateIfNeeded, która jest teraz również testowalna, powinna zawsze zwracać konto. Cokolwiek poprosisz.
Wszystkie te 3 metody są jasne, dokładnie wiadomo, co robią i co zwracają. Możesz teraz zawierać porozumienia ze swoim zespołem, ale tego rodzaju wyjątki są straszne na dłuższą metę. Po prostu wyjaśnij je, a nie będziesz mieć problemów.
źródło
getAccountIfExists
która albo założy konto, albo wskaże, że nie istnieje bez utworzenia nowej. SamagetAccount
metoda powinna zakładać, że konto istnieje, i jeśli nie, zgłosić wyjątek.To zależy od okoliczności.
Na przykład możesz go użyć do leniwego ładowania / tworzenia instancji, odraczania ładowania danych lub tworzenia instancji, dopóki nie będzie to faktycznie potrzebne. Jest to zwykle rozsądne, ponieważ oszczędza zasoby, których możesz nie potrzebować (jeśli klasa / dane nigdy nie są potrzebne, to nigdy nie są ładowane).
Jednak w tym konkretnym przypadku powiedziałbym, że posiadanie metody o nazwie getAccount, która utworzyłaby nowe konto, gdyby nie istniało, nie byłaby dobrą praktyką. Jeśli użytkownik podał pewne dane uwierzytelniające w celu zidentyfikowania określonego konta, a konta tego nie można znaleźć, czy to oznacza, że użytkownik nie jest jeszcze klientem i że należy dla niego utworzyć konto, czy oznacza to, że dane logowania zostały błędnie wpisane a użytkownik musi zostać poproszony o sprawdzenie, czy wpisał to, co zamierzał wprowadzić?
Jeśli masz metodę getAccount, która tworzy nowe konto, jeśli nie można go zidentyfikować, oznacza to, że nie masz wyboru. Jeśli podzielisz tworzenie konta i wyodrębnianie konta na osobne metody, masz większą swobodę w podejmowaniu decyzji, co zrobić, gdy próba założenia konta nie powiedzie się.
źródło