Jak już wspomniano, istnieją dwie szkoły myślenia na ten temat.
1) Zadeklaruj wszystko u góry funkcji, ponieważ jest rok 1987.
2) Zadeklaruj jak najbliżej pierwszego użycia i w możliwie najmniejszym zakresie.
Moja odpowiedź na to brzmi: ZRÓB OBIEG! Pozwól mi wyjaśnić:
W przypadku długich funkcji 1) sprawia, że refaktoryzacja jest bardzo trudna. Jeśli pracujesz w bazie kodu, w której programiści sprzeciwiają się idei podprogramów, będziesz mieć 50 deklaracji zmiennych na początku funkcji, a niektóre z nich mogą być po prostu „i” dla pętli for, która jest na samym początku dół funkcji.
Dlatego opracowałem na podstawie tego deklarację na szczycie PTSD i próbowałem zrobić opcję 2) religijnie.
Wróciłem do opcji pierwszej z jednego powodu: krótkich funkcji. Jeśli twoje funkcje są wystarczająco krótkie, będziesz mieć kilka zmiennych lokalnych, a ponieważ funkcja jest krótka, jeśli umieścisz je na górze funkcji, nadal będą blisko pierwszego użycia.
Również anty-wzorzec „deklaruj i ustaw na NULL”, gdy chcesz zadeklarować na górze, ale nie wykonałeś pewnych obliczeń niezbędnych do inicjalizacji, został rozwiązany, ponieważ rzeczy, które musisz zainicjować, zostaną prawdopodobnie odebrane jako argumenty.
Więc teraz myślę, że powinieneś zadeklarować na górze funkcji i jak najbliżej pierwszego użycia. Więc obie! A sposobem na to są dobrze podzielone podprogramy.
Ale jeśli pracujesz nad długą funkcją, zastosuj rzeczy najbliższe do pierwszego użycia, ponieważ w ten sposób łatwiej będzie wyodrębnić metody.
Mój przepis jest taki. Dla wszystkich zmiennych lokalnych weź zmienną i przenieś jej deklarację na dół, skompiluj, a następnie przenieś deklarację tuż przed błędem kompilacji. To jest pierwsze użycie. Zrób to dla wszystkich zmiennych lokalnych.
int foo = 0;
<code that uses foo>
int bar = 1;
<code that uses bar>
<code that uses foo>
Teraz zdefiniuj blok zakresu, który zaczyna się przed deklaracją i przesuń koniec do momentu kompilacji programu
{
int foo = 0;
<code that uses foo>
}
int bar = 1;
<code that uses bar>
>>> First compilation error here
<code that uses foo>
To się nie kompiluje, ponieważ jest więcej kodu używającego foo. Możemy zauważyć, że kompilator był w stanie przejść przez kod używający bar, ponieważ nie używa foo. W tym momencie są dwie możliwości. Mechaniczny polega na przesunięciu znaku „}” w dół, aż się skompiluje, a drugim wyborem jest sprawdzenie kodu i ustalenie, czy kolejność można zmienić na:
{
int foo = 0;
<code that uses foo>
}
<code that uses foo>
int bar = 1;
<code that uses bar>
Jeśli kolejność można zmienić, prawdopodobnie tego chcesz, ponieważ skraca to żywotność wartości tymczasowych.
Inną rzeczą wartą uwagi jest to, czy wartość foo musi być zachowana między blokami kodu, które go używają, czy może to być po prostu inne foo w obu. Na przykład
int i;
for(i = 0; i < 8; ++i){
...
}
<some stuff>
for(i = 3; i < 32; ++i){
...
}
Te sytuacje wymagają czegoś więcej niż tylko mojej procedury. Deweloper będzie musiał przeanalizować kod, aby określić, co robić.
Ale pierwszym krokiem jest znalezienie pierwszego zastosowania. Możesz to zrobić wizualnie, ale czasami po prostu łatwiej jest usunąć deklarację, spróbować skompilować i po prostu umieścić ją z powrotem powyżej pierwszego użycia. Jeśli to pierwsze użycie znajduje się wewnątrz instrukcji if, umieść je tam i sprawdź, czy się kompiluje. Kompilator następnie zidentyfikuje inne zastosowania. Spróbuj utworzyć blok zakresu, który obejmuje oba zastosowania.
Po wykonaniu tej części mechanicznej łatwiej jest przeanalizować, gdzie są dane. Jeśli zmienna jest używana w bloku o dużym zasięgu, przeanalizuj sytuację i sprawdź, czy nie używasz tej samej zmiennej do dwóch różnych rzeczy (np. „I”, które jest używane dla dwóch pętli). Jeśli zastosowania są niepowiązane, utwórz nowe zmienne dla każdego z tych niepowiązanych zastosowań.