Procedury mogą mieć parametry, to nie jest żadna wiadomość. Możesz zdefiniować tyle parametrów, ile potrzebujesz, ale zbyt wiele z nich utrudni zrozumienie i utrzymanie rutyny.
Oczywiście można zastosować zmienną strukturalną jako obejście: umieszczając wszystkie te zmienne w jednej strukturze i przekazując je do procedury. W rzeczywistości stosowanie struktur w celu uproszczenia list parametrów jest jedną z technik opisanych przez Steve'a McConnella w Code Complete . Ale jak mówi:
Ostrożni programiści unikają łączenia danych bardziej niż jest to logicznie konieczne.
Więc jeśli twoja procedura ma zbyt wiele parametrów lub używasz struktury do ukrywania dużej listy parametrów, prawdopodobnie robisz coś złego. Oznacza to, że nie utrzymujesz luźnego połączenia.
Moje pytanie brzmi: kiedy mogę uznać listę parametrów za zbyt dużą? Myślę, że ponad 5 parametrów to za dużo. Co myślisz?
Odpowiedzi:
Kiedy coś uważa się za tak nieprzyzwoite, że może być regulowane pomimo gwarancji 1. poprawki do wolności słowa? Według Justice Potter Stewart: „Wiem, kiedy to widzę”. To samo dotyczy tutaj.
Nienawidzę takich twardych i szybkich reguł, ponieważ odpowiedź zmienia się nie tylko w zależności od wielkości i zakresu twojego projektu, ale myślę, że zmienia się nawet do poziomu modułu. W zależności od tego, co robi twoja metoda lub co ma reprezentować klasa, całkiem możliwe, że 2 argumenty to za dużo i jest to objaw zbyt dużego sprzężenia.
Sugerowałbym, że zadając to pytanie i kwalifikując je tak samo jak Ty, naprawdę to wszystko wiesz. Najlepszym rozwiązaniem nie jest poleganie na twardej i szybkiej liczbie, ale zamiast tego przeglądaj projekty i recenzje kodu wśród swoich rówieśników, aby zidentyfikować obszary, w których masz niską spójność i ścisłe połączenie.
Nigdy nie bój się pokazywać swoim kolegom swojej pracy. Jeśli się boisz, to prawdopodobnie większy znak, że coś jest nie tak z twoim kodem i że już o tym wiesz .
źródło
Funkcja może mieć zbyt wiele parametrów tylko wtedy, gdy niektóre parametry są nadmiarowe. Jeśli wszystkie parametry są używane, funkcja musi mieć poprawną liczbę parametrów. Weź tę często używaną funkcję:
To 12 parametrów (9, jeśli pakiet x, y, wih jest prostokątem), a także parametry wyprowadzone z nazwy klasy. Jak byś to zmniejszył? Czy chcesz jeszcze bardziej zmniejszyć liczbę?
Nie przejmuj się liczbą parametrów, po prostu upewnij się, że jest logiczna i dobrze udokumentowana, a Intellisense * ci pomoże.
* Inni asystenci kodowania są dostępni!
źródło
W Clean Code Robert C. Martin poświęcił temu tematowi cztery strony. Oto sedno:
źródło
<algorithm>
, działałbym na obiekcie zasięgu. Kolekcje byłyby zakresami, ale nie wszystkie zakresy byłyby kolekcjami. I rzeczywiście, boost już to zrobił. W każdym razie, chodzi mi o to, że masowo powszechnie używane biblioteki ignoruje tę radę, więc najgorsze co jest gwarantowane , aby się z tobą, jeśli nie za to, że wiele swoich milionów użytkowników będzie majstrować przy niewielkich uproszczeń do interfejsu ;-)Niektóre kody, z którymi pracowałem w przeszłości, używały zmiennych globalnych tylko po to, aby uniknąć przekazywania zbyt wielu parametrów.
Proszę nie rób tego!
(Zazwyczaj.)
źródło
Jeśli zaczniesz odliczać w myślach parametry w podpisie i dopasować je do połączenia, czas na refaktoryzację!
źródło
Dziękuję bardzo za wszystkie odpowiedzi:
To było trochę zaskakujące, aby znaleźć ludzi, którzy również myślą (tak jak ja), że 5 parametrów jest dobrym ograniczeniem dla rozsądku kodu.
Ogólnie rzecz biorąc, ludzie zgadzają się, że granica między 3 a 4 jest dobrą regułą. Jest to uzasadnione, ponieważ ludzie zwykle mają zły czas licząc więcej niż 4 rzeczy.
Jak wskazuje Milan , średnio ludzie mogą mieć w głowie mniej więcej 7 rzeczy na raz. Myślę jednak, że nie możesz zapomnieć, że projektując / utrzymując / studiując rutynę, musisz pamiętać o więcej niż tylko parametrach.
Niektórzy uważają, że procedura powinna zawierać tyle argumentów, ile potrzeba. Zgadzam się, ale tylko w kilku konkretnych przypadkach (wywołania interfejsów API systemu operacyjnego, procedury, w których ważna jest optymalizacja itp.). Sugeruję, aby ukryć złożoność tych procedur, dodając warstwę abstrakcji tuż nad tymi wywołaniami, gdy tylko jest to możliwe.
Nick ma na ten temat ciekawe przemyślenia . Jeśli nie chcesz czytać jego komentarzy, podsumowuję dla ciebie: w skrócie, to zależy :
Morał nie polega na tym, że nie obawiasz się pokazywać kodu swoim rówieśnikom, dyskutować z nimi i próbować „zidentyfikować obszary, w których masz niską spójność i ścisłe powiązanie” .
Wreszcie myślę, że wnoise bardzo zgadza się z Nickiem i kończy swój satyryczny wkład tą poetycką wizją sztuki programowania (patrz komentarze poniżej):
źródło
Ta odpowiedź zakłada język OO. Jeśli nie używasz jednego - pomiń tę odpowiedź (innymi słowy, nie jest to odpowiedź zależna od języka.
Jeśli przekazujesz więcej niż 3 parametry (szczególnie wewnętrzne typy / obiekty), to nie jest tak, że to „Zbyt wiele”, ale możesz stracić szansę na utworzenie nowego obiektu.
Poszukaj grup parametrów, które są przekazywane do więcej niż jednej metody - nawet grupa przekazana do dwóch metod prawie gwarantuje, że powinieneś mieć tam nowy obiekt.
Następnie przekształcasz funkcjonalność w nowy obiekt i nie uwierzyłbyś, jak bardzo pomaga to zarówno Twojemu kodowi, jak i zrozumieniu programowania OO.
źródło
Wygląda na to, że istnieją inne względy niż zwykła liczba, oto kilka, które przychodzą na myśl:
logiczna relacja do głównego celu funkcji a ustawienia jednorazowe
Jeśli są to tylko flagi środowiska, tworzenie pakietów może być bardzo przydatne
źródło
Jeden z dobrze znanych epigramów programistycznych Alana Perlisa (opisany w ACM SIGPLAN Notices 17 (9), wrzesień 1982)) stwierdza, że „Jeśli masz procedurę z 10 parametrami, pewnie coś przegapiłeś”.
źródło
Według Steve'a McConnella w Code Complete powinieneś
źródło
Dla mnie, gdy lista przecina jeden wiersz w moim IDE, to jest o jeden parametr za dużo. Chcę zobaczyć wszystkie parametry w jednej linii bez przerywania kontaktu wzrokowego. Ale to tylko moje osobiste preferencje.
źródło
Generalnie zgadzam się z 5, jednak jeśli jest sytuacja, w której potrzebuję więcej i jest to najwyraźniejszy sposób rozwiązania problemu, wtedy użyłbym więcej.
źródło
Siedem rzeczy w pamięci krótkoterminowej?
źródło
W Najgorszych 5 fragmentach kodu zaznacz drugi „Czy to konstruktor”. Ma ponad 37 ⋅ 4 ≈ 150 parametrów:
źródło
Jeden więcej niż to konieczne. Nie chcę być glibem, ale jest kilka funkcji, które niekoniecznie wymagają sporo opcji. Na przykład:
Jest 6 argumentów i każdy z nich jest niezbędny. Co więcej, nie ma wspólnego łącza między nimi, aby uzasadnić ich połączenie. Może mógłbyś zdefiniować „struct mmapargs”, ale byłoby to gorsze.
źródło
prot
iflags
można by go zrolować, gdyby projektant uznał, że 5 jest w pewnym sensie magiczną liczbą, która jest znacznie lepsza niż 6. Trochę jak sposób, któryopen
łączy tryb odczytu / zapisu ze wszystkimi innymi flagami. A może i ty mógł pozbyćoffset
poprzez określenie, że odwzorowane rozpoczyna rozdział na obecnym szukać pozycjifiledes
. Nie wiem, czy są jakieś sytuacje, w których możeszmmap
stworzyć region, do którego nie jesteś zdolnylseek
, ale jeśli nie, to nie jest to absolutnie konieczne.mmap
to dobra ilustracja tego, że niektórzy projektanci i użytkownicy wolą długą długą listę parametrów, podczas gdy inni wolą przejść kilka kroków, przygotowując mniejszą liczbę parametrów przed wykonaniem połączenia.Według najlepszych praktyk Perla , 3 jest w porządku, 4 to za dużo. To tylko wskazówka, ale w naszym sklepie staramy się tego trzymać.
źródło
Sam wyznaczam limit funkcji publicznych przy 5 parametrach.
IMHO, długie listy parametrów są akceptowane tylko w prywatnych / lokalnych funkcjach pomocniczych, które mają być wywoływane tylko z kilku określonych miejsc w kodzie. W takich przypadkach może być konieczne przekazanie wielu informacji o stanie, ale czytelność nie jest tak dużym problemem, ponieważ tylko Ty (lub ktoś, kto będzie utrzymywał twój kod i powinien zrozumieć podstawy Twojego modułu), musisz się tym przejmować wywołanie tej funkcji.
źródło
Powiązane pytanie, które należy rozważyć, to jak spójność rutyny. Duża liczba parametrów może być zapachem, który mówi ci, że sama procedura próbuje zrobić zbyt wiele, a zatem jej spójność jest podejrzana. Zgadzam się, że twarda i szybka liczba parametrów jest prawdopodobnie niemożliwa, ale zgaduję, że rutyna wysokiej kohezji oznaczałaby małą liczbę parametrów.
źródło
97 brzmi właściwie.
Tym bardziej tracisz elastyczność.
źródło
Zatrzymuję się na trzech parametrach jako ogólna zasada. Teraz już czas, aby zamiast tego przekazać tablicę parametrów lub obiekt konfiguracyjny, co pozwala również na dodawanie przyszłych parametrów bez zmiany interfejsu API.
źródło
Ograniczenie długości na liście parametrów to tylko jedno ograniczenie. A ograniczenie oznacza stosowaną przemoc. Brzmi zabawnie, ale możesz być bez przemocy, nawet podczas programowania. Niech kod dyktuje reguły. Oczywiste jest, że jeśli masz wiele parametrów, treść metody funkcja / klasa będzie wystarczająco duża, aby z nich skorzystać. Fragmenty dużego kodu zwykle można ponownie przetworzyć i podzielić na mniejsze fragmenty. Otrzymujesz więc rozwiązanie zapobiegające posiadaniu wielu parametrów jako darmowego bonusu, ponieważ są one podzielone na mniejsze, zrekonstruowane fragmenty kodu.
źródło
Z perspektywy wydajności chciałbym zwrócić uwagę na to, że w zależności od tego, jak przekazujesz parametry do metody, przekazywanie wielu parametrów według wartości spowolni program, ponieważ każdy parametr musi zostać skopiowany, a następnie umieszczony na stosie.
Zastosowanie jednej klasy do objęcia wszystkich parametrów działałoby lepiej, ponieważ pojedynczy parametr przekazywany przez referencję byłby elegancki, czystszy i szybszy!
źródło
Według mnie mogą zdarzyć się przypadki, w których przekroczysz 4 lub jakiś ustalony numer. Rzeczy, na które trzeba uważać
Z punktu widzenia łatwości użycia lub łatwości czytania kodu, myślę, że kiedy trzeba trochę „zawinąć słowo” swój podpis metody, powinno to sprawić, że przestaniesz i pomyślisz, chyba że czujesz się bezradny, a wszelkie wysiłki zmierzające do zmniejszenia podpisu prowadzą do brak wyników. Niektóre bardzo dobre biblioteki w przeszłości i obecnie używają ponad 4-5 wózków dziecięcych.
źródło
Moją ogólną zasadą jest to, że muszę być w stanie zapamiętać parametry wystarczająco długo, aby spojrzeć na połączenie i powiedzieć, co robi. Więc jeśli nie mogę spojrzeć na metodę, a następnie przejść do wywołania metody i zapamiętać, który parametr robi to, co jest za dużo.
Dla mnie to równa się około 5, ale nie jestem taki bystry. Twój przebieg może się różnić.
Możesz utworzyć obiekt z właściwościami do przechowywania parametrów i przekazania go, jeśli przekroczysz ustawiony limit. Zobacz książkę refaktoryzacji Martina Fowlera i rozdział dotyczący uproszczenia wywołań metod.
źródło
Zależy to w dużej mierze od środowiska, w którym pracujesz. Weźmy na przykład javascript. W javascript najlepszym sposobem na przekazanie parametrów jest użycie obiektów z parami klucz / wartość, co w praktyce oznacza, że masz tylko jeden parametr. W innych systemach słaby punkt będzie miał trzy lub cztery.
Ostatecznie wszystko sprowadza się do osobistego gustu.
źródło
Zgadzam się z 3 jest w porządku, 4 to zbyt wiele jako wskazówka. Przy więcej niż 3 parametrach nieuchronnie wykonujesz więcej niż jedno zadanie. Więcej niż jedno zadanie należy podzielić na osobne metody.
Jednak gdybym spojrzał na najnowszy projekt, nad którym pracowałem, byłyby wyjątki i większość przypadków trudno byłoby sprowadzić do 3 parametrów.
źródło
Jeśli mam 7-10 parametrów w jednej procedurze, patrzę na łączenie ich w nową klasę, ale nie, jeśli klasa ta byłaby niczym innym jak zbiorem pól z modułami pobierającymi i ustawiającymi - nowa klasa musi robić coś innego niż tasowanie wartości w i na zewnątrz. W przeciwnym razie wolę pogodzić się z długą listą parametrów.
źródło
Jest to znany fakt, że średnio ludzie mogą przechowywać 7 +/- 2 rzeczy na raz. Lubię używać tej zasady z parametrami. Zakładając, że wszyscy programiści są ponadprzeciętnymi inteligentnymi ludźmi, powiedziałbym, że wszystko 10+ to za dużo.
BTW, jeśli parametry są w jakikolwiek sposób podobne, umieściłbym je w wektorze lub liście zamiast w struct lub klasie.
źródło
Oparłbym swoją odpowiedź na częstotliwości wywoływania tej funkcji.
Jeśli jest to funkcja inicjująca, która jest wywoływana tylko raz, niech bierze 10 parmsów lub więcej, kogo to obchodzi.
Jeśli nazywa się to kilka razy na klatkę, to zwykle tworzę strukturę i po prostu przekazuję do niej wskaźnik, ponieważ zwykle jest to szybsze (zakładając, że za każdym razem nie przebudowujesz struktury).
źródło
Według Jeffa Bezosa ze sławy Amazona, nie więcej niż dwie karmy :
źródło