Czy ponowne stosowanie parametrów metody jest złą praktyką?

12

Są chwile, kiedy będę musiał zmodyfikować wartość przekazywaną do metody z poziomu samej metody. Przykładem może być tutaj odkażanie łańcucha, takiego jak ta metoda:

void SanitizeName(string Name)
{
    Name = Name.ToUpper();

    //now do something here with name
}

Jest to całkowicie nieszkodliwe, ponieważ Nameargument nie jest przekazywany przez odwołanie. Jeśli jednak z jakiegoś powodu programista w przyszłości zdecyduje się na przekazanie wszystkich wartości przez ref, wszelkie odkażanie łańcucha wpłynie na wartość poza metodą, co może mieć szkodliwe wyniki.

Dlatego zamiast przypisywania samego argumentu zawsze tworzę lokalną kopię w następujący sposób:

void SanitizeName(string Name)
{
    var SanitizedName = Name.ToUpper();

    //now do something here with name
}

Zapewnia to, że zmiana przekazu wartości nigdy nie wpłynie na działania poza metodą, ale zastanawiam się, czy jestem nadmiernie paranoikiem na ten temat.

kretyna oscylacyjna
źródło
1
Tak, to zła praktyka; i nie, to nie jest nieszkodliwe. Wiersz Name = Name.ToUpper();utrudnia śledzenie kodu w głowie, ponieważ wartość Namezmian. Twój drugi przykład jest nie tylko bardziej przyszłościowy, ale łatwiej jest zrozumieć, co robi.
David Arno
2
Ale co z if (param == NULL) param = default_value;?
aragaer
Myślę, że to nie jest tak proste jak tak / nie.
MrSmith42
3
Jeśli „programista w przyszłości zdecyduje się na przekazanie wszystkich wartości przez referen” , prawdopodobnie miałbym argument z tym deweloperem, z włączonym ponownym użyciem parametru, czy nie ;-) Szczerze mówiąc, kiedy ktoś decyduje się przekazać wartość, by refktóra nie została przekazana, że wcześniej, a więc z jakiegoś powodu przekształcając dostęp lokalny na dostęp nielokalny, zawsze musi dokładnie sprawdzić konsekwencje.
Doc Brown
2
Pracuję przede wszystkim w paradygmacie, w którym nigdy nie przypisujemy żadnych zmiennych. Zawsze. Zabawne jest wyobrażenie sobie, że ktoś zmaga się z tym, czy powinien przypisać niewielką mniejszość zmiennych, a potem nie martwić się, że oszaleje z resztą.
Karl Bielefeldt

Odpowiedzi:

10

Myślę, że to zależy od twoich konwencji kodowania w twoim projekcie.

Osobiście pozwalam eclipse automatycznie dodawać finalsłowo kluczowe do każdej zmiennej i parametru. W ten sposób na pierwszy rzut oka widać, czy parametr jest ponownie używany.

W projekcie w moim zadaniu nie zalecamy ponownego użycia parametrów, ale jeśli chcesz tylko wywołać np. .trim()Lub ustawić wartość domyślną w nullprzypadku, to najczęściej używamy parametru ponownie, ponieważ wprowadzenie nowej zmiennej jest w takich przypadkach mniej czytelne niż ponowne użycie parametru.

Naprawdę nie powinieneś ponownie używać parametru do przechowywania bardzo różnych treści, ponieważ nazwa nie będzie już odnosić się do jego zawartości. Ale dotyczy to każdego ponownego przypisania zmiennej i nie ogranicza się do parametrów.

Spotkaj się więc ze swoim zespołem i sformułuj konwencje kodowania dotyczące tej kwestii.

MrSmith42
źródło
0

Jeśli używasz statycznego analizatora kodu ze względów bezpieczeństwa, może się on pomylić i sądzić, że nie sprawdziłeś poprawności lub dezynfekcji zmiennej parametru wejściowego przed użyciem. Jeśli użyjesz Namena przykład zapytania SQL, może ono zawierać lukę w zabezpieczeniach polegającą na wstrzykiwaniu SQL, co może być czasochłonne w wyjaśnieniu. To jest złe. Z drugiej strony, użycie specjalnie nazwanej zmiennej do dezynfekowanego wejścia, bez dezynfekcji danych wejściowych, jest szybkim sposobem na wyciszenie naiwnych analizatorów kodu (wykrywanie podatności na fałszywe negatywne).

Greg
źródło
W większości przypadków można również użyć adnotacji lub specjalnego komentarza, aby wskazać analizatorowi kodu, że jest to zamierzone, a nie niezauważone ryzyko.
MrSmith42
0

Odpowiedź na to pytanie zależy w 100% od tego, kto będzie czytał Twój kod. Jakie style uważają za najbardziej pomocne?

Odkryłem, że najbardziej ogólny przypadek polega na tym, że unika się ponownego przypisywania wartości do argumentów funkcyjnych, ponieważ zbyt wielu programistów ma mentalne modele działania wywołań funkcji, które zakładają, że nigdy tego nie robisz. Ten problem może spotęgować debuggery, które wypisują wartości argumentów, które wywołujesz dla każdej funkcji. Informacje te są technicznie niepoprawne, jeśli edytujesz argumenty, co może prowadzić do dziwnych frustracji.

Biorąc to pod uwagę, zmieniają się modele mentalne. W twoim konkretnym środowisku programistycznym może być pożądane, aby namebyć „najlepszą reprezentacją nazwy w tym momencie”. Może być pożądane wyraźniejsze powiązanie zmiennych, nad którymi pracujesz, z ich argumentami, nawet jeśli po drodze wprowadziłeś pewne modyfikacje ich wartości. Ponowne użycie niektórych określonych zmiennych może być nawet znaczące. W końcu, gdy pracujesz z ciągami 4 GB, miło jest zminimalizować liczbę dodatkowych kopii, które musisz wykonać!

Cort Ammon
źródło
-1

Mam zupełnie inny problem z twoim przykładem kodu:

Twoja metoda nazywa się SanitizeName. W tym przypadku oczekuję, że zdezynfekuje ono imię ; ponieważ to jest to, co mówisz czytelnikowi o swojej funkcji.

Tylko rzeczą, której funkcjonować należy zrobić , jest odkażania daną nazwę . Bez czytania kodu oczekiwałbym:

string SanitizeName(string Name)
{
    //somehow sanitize the name
    return Result;
}

Ale sugerujesz, że twoja metoda robi coś więcej niż tylko dezynfekcję. To zapach kodu i należy go unikać.

Twoje pytanie nie dotyczy: Czy złą praktyką jest ponowne wykorzystywanie parametrów metody? Co więcej: czy skutki uboczne i nieoczekiwane zachowanie są złą praktyką?

Odpowiedź na to pytanie jest jednoznaczna: tak!

Jest to całkowicie nieszkodliwe, ponieważ argument Nazwa nie jest przekazywany przez odwołanie. Jeśli jednak z jakiegoś powodu programista w przyszłości zdecyduje się na przekazanie wszystkich wartości przez ref, wszelkie odkażanie łańcucha wpłynie na wartość poza metodą, co może mieć szkodliwe wyniki

Wprowadzasz czytelnika w błąd, nie zwracając niczego. Twoja nazwa metody wyraźnie wskazuje, że coś robiszName . Gdzie więc powinien iść wynik? Przez twoją funkcję voidczyta podpis, którego używam, Nameale nie wyrządzam żadnej szkody idowi, ani nie mówię ci o wyniku (jawnie). Być może istnieje wyjątek, a może nie; ale Namenie ulega zmianie . Jest to semantyczne przeciwieństwo nazwy twojej metody.

Problemem jest mniejsze ponowne użycie niż skutki uboczne . Aby zapobiec efektom ubocznym , nie używaj ponownie zmiennej. Jeśli nie masz żadnych skutków ubocznych, nie ma problemu.

Thomas Junk
źródło
4
-1 To nie odpowiada na pierwotne pytanie. Podany kod to tylko przykładowy kod do pokazania pytania. Odpowiedz na pytanie, zamiast „atakować” / przeglądać podany przykładowy kod.
Niklas H
1
@NiklasH To doskonale odpowiada na pytanie: jeśli manipulujesz parametrem wewnątrz funkcji i jak wspomniano w TO, przypadkowo pracujesz z referencją zamiast z kopią, powoduje to skutki uboczne (jak powiedziałem) i to jest złe. Aby temu zapobiec, wskaż, że zamierzasz zmienić zmienną, ostrożnie wybierając nazwę metody (pomyśl o Ruby '!') I / lub wybierając typ zwracany. Jeśli nie zmienisz zmiennej, pracuj tylko z kopiami.
Thomas Junk