Jak podano w tytule, czy parametry opcjonalne, takie jak te używane w języku C #, są pomocne, czy stanowią przeszkodę w utrzymaniu aplikacji i należy ich unikać, ponieważ mogą utrudnić zrozumienie kodu?
Jak podano w tytule, czy parametry opcjonalne, takie jak te używane w języku C #, są pomocne, czy stanowią przeszkodę w utrzymaniu aplikacji i należy ich unikać, ponieważ mogą utrudnić zrozumienie kodu?
Odpowiedzi:
Opcjonalne parametry, z mojego doświadczenia, były dobrą rzeczą. Nigdy nie uważałem ich za mylące (przynajmniej nie bardziej mylące niż rzeczywista funkcja), ponieważ zawsze mogę uzyskać wartości domyślne i wiedzieć, co się nazywa.
Jednym z nich jest to, że muszę dodać kolejny parametr do funkcji, która jest już w powszechnym użyciu lub przynajmniej w interfejsie publicznym. Bez nich musiałbym powtórzyć oryginalną funkcję, aby wywołać funkcję, która ma inny argument, i która może się naprawdę zestarzeć, jeśli skończę dodawać argumenty więcej niż raz.
new Circle(size, color, filled, ellipseProportions)
Gdzie size
i color
są wymagane, a reszta jest domyślna.
Ogólnie rzecz biorąc, jeśli często potrzebujesz wielu / opcjonalnych parametrów, twoje funkcje robią za dużo i powinny zostać zepsute. Prawdopodobnie łamiesz SRP (zasada pojedynczej odpowiedzialności).
Poszukaj parametrów, które można grupować, np. (Xiy stają się punktem).
Czy te opcjonalne parametry flagi mają wartość domyślną? Jeśli używasz flag, funkcja powinna zostać podzielona.
Nie oznacza to, że nigdy nie powinieneś mieć parametrów opcjonalnych, ale ogólnie więcej niż jeden lub dwa parametry sugerują zapach kodu.
Może to być również wskazówka, że funkcja powinna być klasą, z opcjonalnymi parametrami zmienionymi na właściwości i wymaganymi parametrami części konstruktora.
Parametry opcjonalne są w porządku
Zazwyczaj uzasadnia się to tym, że: a) wiesz, że masz wiele możliwych argumentów dla swojej metody, ale nie chcesz przeciążać z obawy przed zaśmieceniem interfejsu API, lub b) gdy nie znasz wszystkich możliwych argumentów, ale nie chcę zmuszać użytkownika do zapewnienia tablicy. W każdym przypadku na ratunek przychodzą opcjonalne parametry w zgrabny i elegancki sposób.
Oto kilka przykładów:
1. Chcesz uniknąć przeciążenia i nie chcesz określać tablicy
Spójrz na printf () z C, Perl, Java itp. To świetny przykład potęgi parametrów opcjonalnych.
Na przykład:
printf("I want %d %s %s",1,"chocolate","biccies");
printf("I want %d banana",1);
Bez przeładowania, bez tablic, proste i intuicyjne (po opanowaniu standardowych kodów formatu ciągów). Niektóre IDE powiedzą ci nawet, czy łańcuch formatu nie pasuje do opcjonalnych parametrów.
2. Chcesz zezwolić na użycie ustawień domyślnych i ukryć je przed użytkownikiem metody
sendEmail („test@example.org”);
Metoda sendEmail wykrywa brak różnych istotnych wartości i wypełnia je przy użyciu zdefiniowanych wartości domyślnych (podmiot, treść, DW, UDW itp.). Interfejs API jest czysty, ale elastyczny.
Uwaga na zbyt wiele parametrów
Jednak, jak stwierdzili inni, posiadanie zbyt wielu parametrów obowiązkowych w stosunku do metody wskazuje, że prawdopodobnie masz coś złego w swoim projekcie. Jest to szczególnie prawdziwe, jeśli mają ten sam typ, ponieważ mogą zostać przypadkowo przełączone przez programistę, co prowadzi do dziwnych wyników w czasie wykonywania:
String myMethod(String x, String y, String z, String a, int b, String c, int d) {}
jest idealnym kandydatem do utworzenia refaktoryzacji obiektu parametrów parametru
String myMethod(ParameterObject po) {}
class ParameterObject {
// Left as public for clarity
public String x;
public String y;
... etc
}
To z kolei może prowadzić do lepszego projektu opartego na wzorcu fabrycznym z dostarczoną specyfikacją jako obiektem parametru.
Jednym z problemów z domyślnymi parametrami w C # (myślę, że void DoSomething (int x = 1)) jest to, że są one stałe. Oznacza to, że jeśli zmienisz ustawienie domyślne, będziesz musiał ponownie skompilować wszystkich odbiorców tego wywołania metody. Chociaż jest to dość łatwe, zdarzają się sytuacje, w których jest to niebezpieczne.
To zależy od tego, co robi twój kod. Jeśli istnieją rozsądne wartości domyślne, powinieneś użyć parametrów opcjonalnych, ale jeśli nie ma żadnych sensownych wartości domyślnych, dodanie parametrów opcjonalnych sprawi, że kod będzie bardziej skomplikowany. W wielu przypadkach opcjonalne parametry są dobrym sposobem na ominięcie kontroli zerowych i wycięcie logiki rozgałęziania. JavaScript nie ma parametrów opcjonalnych, ale istnieje sposób na ich emulację za pomocą || (logiczne lub) i używam go cały czas podczas robienia rzeczy związanych z bazą danych, ponieważ jeśli użytkownik nie poda żadnej wartości, wówczas podstawiam własne wartości za pomocą || co oszczędza mi kłopotów z pisaniem całego zestawu instrukcji if if.
Parametry opcjonalne to świetny sposób, aby proste rzeczy były proste, a skomplikowane rzeczy możliwe jednocześnie. Jeśli istnieje wyraźna rozsądna wartość domyślna, której większość użytkowników będzie chciała, przynajmniej w szybkich i brudnych przypadkach użycia, nie powinni oni musieć pisać schematu, aby ręcznie określać to za każdym razem, gdy wywołują twoją funkcję. Z drugiej strony, jeśli ludzie mogą mieć dobry powód, aby chcieć to zmienić, należy to ujawnić.
Korzystanie z klasy jest IMHO okropnym rozwiązaniem, ponieważ jest pełne, nieefektywne i niezgodne z typowym modelem mentalnym tego, co robi klasa. Funkcja jest idealną abstrakcją czasownika, tzn. Robienia czegoś i powrotu. Klasa jest właściwą abstrakcją dla rzeczownika, tzn. Czymś, co ma stan i można nim manipulować na kilka sposobów. Jeśli ten pierwszy powinien być modelem mentalnym użytkownika API, nie rób z niego klasy.
Problem z opcjonalnymi argumentami polega na tym, że ludzie mają tendencję do wkładania coraz większej liczby (i więcej) argumentów do funkcji zamiast wydobywania odpowiedniego kodu do nowej funkcji. To jest doprowadzone do skrajności w php . Na przykład:
bool array_multisort ( array &$arr [, mixed $arg = SORT_ASC
[, mixed $arg = SORT_REGULAR [, mixed $... ]]] )
Początkowo podobała mi się ta funkcja w Pythonie i wykorzystałem ją do „rozszerzenia” już używanych metod. I wyglądało to ładnie i łatwo, ale wkrótce się ugryzło; ponieważ kiedy dodałem parametr opcjonalny, modyfikowało to zachowanie istniejącej metody, na której polegał stary klient, w sposób, który nie został przechwycony przez istniejące przypadki testów jednostkowych. Zasadniczo robi to łamanie otwartej zasady zamkniętej; kod jest otwarty do rozszerzenia, ale zamknięty do modyfikacji. Uważam więc, że użycie tej funkcji do modyfikacji istniejącego kodu nie jest dobrym pomysłem; ale w porządku, jeśli jest używany od samego początku
Wydaje mi się, że lepiej byłoby przeciążić funkcję innymi podpisami (tj. Parametrami) niż użyć parametrów opcjonalnych.