Như đã lưu ý, có hai trường phái suy nghĩ về điều này.
1) Khai báo mọi thứ ở đầu các chức năng vì năm là 1987.
2) Khai báo gần nhất với lần sử dụng đầu tiên và trong phạm vi nhỏ nhất có thể.
Câu trả lời của tôi cho điều này là LÀM CẢ! Hãy để tôi giải thích:
Đối với các hàm dài, 1) làm cho việc tái cấu trúc rất khó khăn. Nếu bạn làm việc trong một cơ sở mã nơi các nhà phát triển chống lại ý tưởng về chương trình con, thì bạn sẽ có 50 khai báo biến khi bắt đầu hàm và một số trong số chúng có thể chỉ là "i" cho một vòng lặp for đáy của hàm.
Do đó, tôi đã phát triển khai báo PTSD từ đầu và cố gắng thực hiện tùy chọn 2) một cách tôn giáo.
Tôi quay lại để lựa chọn một vì một điều: các chức năng ngắn. Nếu các hàm của bạn đủ ngắn, thì bạn sẽ có một vài biến cục bộ và vì hàm này ngắn, nếu bạn đặt chúng ở đầu hàm, chúng sẽ vẫn gần với lần sử dụng đầu tiên.
Ngoài ra, mô hình chống "khai báo và đặt thành NULL" khi bạn muốn khai báo ở trên cùng nhưng bạn chưa thực hiện một số tính toán cần thiết cho việc khởi tạo vì những điều bạn cần khởi tạo sẽ có thể được nhận làm đối số.
Vì vậy, bây giờ suy nghĩ của tôi là bạn nên khai báo ở đầu các chức năng và càng gần càng tốt để sử dụng lần đầu tiên. Cả hai! Và cách để làm điều đó là với các chương trình con được phân chia tốt.
Nhưng nếu bạn đang làm việc trên một hàm dài, thì hãy đặt những thứ gần nhất với lần sử dụng đầu tiên bởi vì cách đó sẽ dễ dàng hơn để trích xuất các phương thức.
Công thức của tôi là thế này Đối với tất cả các biến cục bộ, lấy biến đó và di chuyển khai báo xuống dưới cùng, biên dịch, sau đó di chuyển khai báo sang ngay trước lỗi biên dịch. Đó là lần đầu tiên sử dụng. Làm điều này cho tất cả các biến địa phương.
int foo = 0;
<code that uses foo>
int bar = 1;
<code that uses bar>
<code that uses foo>
Bây giờ, xác định một khối phạm vi bắt đầu trước khi khai báo và di chuyển kết thúc cho đến khi chương trình biên dịch
{
int foo = 0;
<code that uses foo>
}
int bar = 1;
<code that uses bar>
>>> First compilation error here
<code that uses foo>
Điều này không biên dịch vì có thêm một số mã sử dụng foo. Chúng ta có thể nhận thấy rằng trình biên dịch đã có thể đi qua mã sử dụng thanh vì nó không sử dụng foo. Tại thời điểm này, có hai sự lựa chọn. Cơ chế là chỉ cần di chuyển "}" xuống dưới cho đến khi nó biên dịch, và lựa chọn khác là kiểm tra mã và xác định xem thứ tự có thể được thay đổi thành:
{
int foo = 0;
<code that uses foo>
}
<code that uses foo>
int bar = 1;
<code that uses bar>
Nếu thứ tự có thể được chuyển đổi, đó có thể là những gì bạn muốn bởi vì nó rút ngắn tuổi thọ của các giá trị tạm thời.
Một điều cần lưu ý, giá trị của foo cần được bảo tồn giữa các khối mã sử dụng nó, hoặc có thể chỉ là một foo khác nhau trong cả hai. Ví dụ
int i;
for(i = 0; i < 8; ++i){
...
}
<some stuff>
for(i = 3; i < 32; ++i){
...
}
Những tình huống này cần nhiều hơn thủ tục của tôi. Nhà phát triển sẽ phải phân tích mã để xác định những việc cần làm.
Nhưng bước đầu tiên là tìm kiếm sử dụng đầu tiên. Bạn có thể thực hiện nó một cách trực quan nhưng đôi khi, việc xóa khai báo sẽ dễ dàng hơn, cố gắng biên dịch và chỉ đưa nó trở lại trên lần sử dụng đầu tiên. Nếu lần sử dụng đầu tiên đó nằm trong câu lệnh if, hãy đặt nó ở đó và kiểm tra xem nó có biên dịch không. Trình biên dịch sau đó sẽ xác định các sử dụng khác. Cố gắng tạo một khối phạm vi bao gồm cả hai cách sử dụng.
Sau khi phần cơ học này được thực hiện, nó sẽ trở nên dễ dàng hơn để phân tích dữ liệu ở đâu. Nếu một biến được sử dụng trong một khối phạm vi lớn, hãy phân tích tình huống và xem liệu bạn có đang sử dụng cùng một biến cho hai thứ khác nhau hay không (như "i" được sử dụng cho hai vòng lặp). Nếu việc sử dụng không liên quan, hãy tạo các biến mới cho mỗi lần sử dụng không liên quan này.