Czy istnieją obiektywne, obsługiwane argumenty inżynierii oprogramowania przemawiające za lub przeciw modyfikowaniu wartości parametrów według wartości w treści funkcji?
Powtarzający się splot (głównie w dobrej zabawie) w moim zespole polega na tym, czy parametry przekazywane przez wartość powinny być modyfikowane. Kilku członków zespołu jest przekonanych, że nigdy nie należy przypisywać parametrów, tak aby wartość pierwotnie przekazana do funkcji zawsze mogła zostać zapytana. Nie zgadzam się i utrzymuję, że parametry są niczym więcej jak lokalnymi zmiennymi inicjowanymi przez składnię wywołania metody; jeśli oryginalna wartość parametru według wartości jest ważna, to można zadeklarować, aby zmienna lokalna wyraźnie zapisała tę wartość. Nie jestem pewien, czy którekolwiek z nas ma bardzo dobre poparcie dla naszej pozycji.
Czy jest to nierozwiązywalny konflikt religijny, czy też istnieją dobre, obiektywne powody inżynierii oprogramowania w obu kierunkach?
Uwaga: Kwestia zasady pozostaje bez względu na szczegóły implementacyjne danego języka. Na przykład w JavaScript, gdzie lista argumentów jest zawsze dynamiczna, parametry można traktować jako cukier składniowy do inicjalizacji zmiennych lokalnych z arguments
obiektu. Mimo to można traktować identyfikatory zadeklarowane jako „specjalne”, ponieważ nadal przechwytują przekazywanie informacji od osoby dzwoniącej do odbiorcy.
źródło
Odpowiedzi:
Przyjmuję trzecią pozycję: parametry są jak zmienne lokalne: oba powinny być domyślnie traktowane jako niezmienne. Tak więc zmienne są przypisywane raz, a następnie tylko odczytywane, a nie zmieniane. W przypadku pętli
for each (x in ...)
zmienna jest niezmienna w kontekście każdej iteracji. Przyczyny tego są następujące:W obliczu metody z grupą zmiennych, które są przypisane, a następnie się nie zmieniają, mogę skupić się na czytaniu kodu, zamiast próbować zapamiętać bieżącą wartość każdej z tych zmiennych.
W obliczu tej samej metody, tym razem z mniejszymi zmiennymi, ale ciągle zmieniającymi wartość, muszę teraz pamiętać aktualny stan tych zmiennych, a także pracować nad tym, co robi kod.
Z mojego doświadczenia wynika, że ten pierwszy jest znacznie łatwiejszy dla mojego biednego mózgu. Inni, mądrzejsi, ludowi ode mnie mogą nie mieć tego problemu, ale mi to pomaga.
Jeśli chodzi o drugi punkt:
przeciw
Wymyślone przykłady, ale moim zdaniem jest o wiele bardziej jasne, co dzieje się w drugim przykładzie ze względu na nazwy zmiennych: przekazują one czytelnikowi znacznie więcej informacji niż ta masa
r
w pierwszym przykładzie.źródło
for
Pętle z niezmiennymi zmiennymi są dość trudne . Hermetyzacja zmiennej w funkcji nie jest dla Ciebie wystarczająca? Jeśli masz problem ze śledzeniem zmiennych w zwykłej funkcji, być może twoje funkcje są za długie.for (const auto thing : things)
jest pętlą for, a zmienna, którą wprowadza, jest (lokalnie) niezmienna.for i, thing in enumerate(things):
również nieTo jedna rzecz, którą bardzo lubię w (dobrze napisanym) języku C ++: możesz zobaczyć, czego się spodziewać.
const string& x1
jest stałym odniesieniem,string x2
jest kopią iconst string x3
jest stałą kopią. Ja wiem , co się wydarzy w tej funkcji.x2
zostaną zmienione, ponieważ gdyby tak nie było, nie byłoby powodu, aby uczynić to non-const.Więc jeśli masz język, który na to pozwala , zadeklaruj, co zamierzasz zrobić z parametrami. To powinien być najlepszy wybór dla wszystkich zaangażowanych.
Jeśli twój język na to nie pozwala, obawiam się, że nie ma srebrnego rozwiązania. Oba są możliwe. Jedyną wskazówką jest zasada najmniejszego zaskoczenia. Wybierz jedno podejście i używaj go w całej swojej bazie kodu, nie mieszaj go.
źródło
int f(const T x)
iint f(T x)
różnią się tylko w funkcji-ciele.const int x
po prostu wyczyścić x nie jest zmieniana w środku? Wygląda mi na bardzo dziwny styl.const
go z listy parametrów, jeśli przeszkadza mu to. Więc nie sądzę, że to odpowiada na pytanie.Tak, jest to „konflikt religijny”, z wyjątkiem tego, że Bóg nie czyta programów (o ile mi wiadomo), więc został obniżony do konfliktu czytelności, który staje się kwestią osobistej oceny. I z pewnością to zrobiłem i widziałem, że zrobiono to na dwa sposoby. Na przykład,
Więc tutaj, tylko ze względu na nazwę argumentu t0 , prawdopodobnie nie zmienię jego wartości. Załóżmy jednak, że po prostu zmieniliśmy nazwę tego argumentu na tNow lub coś w tym rodzaju. Wtedy o wiele bardziej niż prawdopodobne zapomniałem o lokalnej kopii i po prostu napisałem tNow + = dt; dla tego ostatniego stwierdzenia.
Ale przeciwnie, załóżmy, że wiedziałem, że klient, dla którego program został napisany, ma zamiar zatrudnić nowych programistów z bardzo małym doświadczeniem, którzy czytaliby i pracowali nad tym kodem. Wtedy prawdopodobnie martwiłbym się pomyleniem ich z wartościami referencyjnymi i referencyjnymi, podczas gdy ich umysły są w 100% zajęte próbą przyswojenia całej logiki biznesowej. W takim przypadku zawsze deklaruję lokalną kopię każdego argumentu, który zostanie zmieniony, niezależnie od tego, czy jest dla mnie mniej lub bardziej czytelny.
Odpowiedzi na tego rodzaju pytania dotyczące stylu pojawiają się z doświadczeniem i rzadko mają kanoniczną odpowiedź religijną. Każdy, kto myśli, że jest jedna i tylko jedna odpowiedź (i że wie o tym :) prawdopodobnie potrzebuje więcej doświadczenia.
źródło