Câu hỏi Biến toàn cục có xấu không? [đã đóng]


Trong C / C ++, các biến toàn cầu có tệ như giáo sư của tôi cho rằng chúng là?


194
2018-01-27 18:35


gốc


Tôi sẽ cắn trong trường hợp anh ta đang cố gắng nói đùa ... "họ xấu đến mức nào"? - Zach Scrivena
Tôi nghĩ rằng câu hỏi này khá thú vị! Phát triển phần mềm vẫn còn phải đối mặt với những cạm bẫy cũ từ khi bắt đầu và các lập trình viên thường không biết rằng việc sử dụng các biến toàn cầu, gotos, biến được đặt tên ngắn KHÔNG phải là vấn đề. Mã lỗi được viết hàng ngày mà không cần sử dụng chúng. +1 - Sylvain Rodrigue
Làm thế nào chúng ta có thể trả lời? Anh ấy không nói với chúng tôi rằng giáo sư của anh ta tệ đến mức nào. :) - Steve Fallows
@Juan Mendes Tôi 100% đồng ý với bạn! Vấn đề tôi đang nói đến là nhiều nhà phát triển biết rằng họ không nên sử dụng các biến toàn cầu nhưng họ chỉ KHÔNG biết tại sao! Và do đó tôi đã thấy nhiều phần mềm lớn, nơi mỗi và mọi chức năng nhận được cùng một cấu trúc lớn chứa +100 trường - Nhìn mẹ, không có biến toàn cầu! Cùng một vấn đề như vậy gọi là "thực hành tốt": chúng là những thực hành tốt trong MỘT SỐ ngữ cảnh, không phải trong mọi ngữ cảnh. Sử dụng chúng CÓ THỂ tạo mã không rõ ràng. Chúc mừng. - Sylvain Rodrigue
Có rất ít sử dụng tốt cho các biến toàn cầu. Một có thể, nhưng việc sử dụng có thể gây tranh cãi, sẽ là một đối tượng "cấu hình" toàn cầu, mà đọc trong một tệp cấu hình khi khởi động. - Siler


Các câu trả lời:


Vấn đề với các biến toàn cục là vì mọi hàm đều có quyền truy cập vào các hàm này, nó trở nên ngày càng khó để tìm ra các hàm thực sự đọc và viết các biến này.

Để hiểu cách ứng dụng hoạt động, bạn cần phải tính đến mọi hàm làm thay đổi trạng thái toàn cầu. Điều đó có thể được thực hiện, nhưng khi ứng dụng phát triển nó sẽ trở nên khó khăn hơn đến mức hầu như không thể (hoặc ít nhất là một sự lãng phí thời gian hoàn toàn).

Nếu bạn không dựa vào các biến toàn cầu, bạn có thể chuyển trạng thái xung quanh giữa các hàm khác nhau nếu cần. Bằng cách đó, bạn có cơ hội hiểu rõ hơn về chức năng của từng chức năng, vì bạn không cần phải tính đến trạng thái toàn cầu.


206
2018-01-27 20:11



Câu trả lời này thực sự tốt. Kết hợp điều này với câu trả lời 'giảm thiểu phạm vi biến' stackoverflow.com/questions/357187/… - bobobobo
Thay thế 'lớp' cho 'ứng dụng' và 'trạng thái đối tượng' cho 'trạng thái toàn cầu' và bạn thực hiện chính xác cùng một đối số cho việc không sử dụng biến thành viên (aka trường) trong lớp. Câu trả lời thực sự là sử dụng chúng khi thích hợp. - Ian Goldby
những người quen với việc viết chương trình cơ sở làm tương tự cho ứng dụng PC không thích hợp. bởi vì firmware thường đơn luồng và đơn giản - linquize
Vài câu hỏi (có lẽ ngớ ngẩn): 1) Nếu bạn muốn biết chức năng nào đọc và ghi các biến này, bạn không thể sử dụng chức năng "tìm" trong trình chỉnh sửa để phát hiện các trường hợp giá trị trong các biến này được sửa đổi? 2) "Điều đó có thể được thực hiện, ... một sự lãng phí thời gian hoàn toàn)." Bạn có thể đưa ra một ví dụ không? 3) "Nếu bạn không dựa vào các biến toàn cầu, ... bạn không cần phải đưa trạng thái toàn cầu vào tài khoản." Tôi không hiểu đó là một lợi thế. Có lẽ một ví dụ về điều đó sẽ làm việc cho tôi. - Andrei
@bobobobo liên kết bị hỏng, chúng tôi có thể nhận được ảnh chụp màn hình từ bạn, một người dùng 10k + không? - noɥʇʎԀʎzɐɹƆ


Điều quan trọng là nhớ mục tiêu tổng thể: sự rõ ràng

Quy tắc "không có biến toàn cầu" có ở đó vì hầu hết thời gian, các biến toàn cầu làm cho ý nghĩa của mã ít rõ ràng hơn.

Tuy nhiên, giống như nhiều quy tắc, mọi người nhớ quy tắc và không phải quy tắc được dự định làm.

Tôi đã nhìn thấy các chương trình mà dường như tăng gấp đôi kích thước của mã bằng cách truyền một số lượng lớn các tham số xung quanh chỉ đơn giản là để tránh cái ác của các biến toàn cầu. Cuối cùng, việc sử dụng các hình cầu sẽ tạo ra chương trình rõ ràng hơn cho những người đọc nó. Bằng cách không ngừng tôn trọng lời của quy tắc, lập trình ban đầu đã thất bại trong ý định của quy tắc.

Vì vậy, có, globals thường là xấu. Nhưng nếu bạn cảm thấy rằng cuối cùng, mục đích của lập trình viên được làm rõ hơn bằng cách sử dụng các biến toàn cầu, sau đó tiếp tục. Tuy nhiên, hãy nhớ sự sụt giảm trong sự rõ ràng tự động xảy ra khi bạn buộc ai đó truy cập một đoạn mã thứ hai (các hình cầu) để hiểu cách tác phẩm đầu tiên hoạt động.


58
2018-02-24 12:19



Đề xuất sử dụng toàn cầu thay vì truyền biến là một công thức để làm cho mã của bạn không thể sử dụng lại và không an toàn cho việc đa luồng - Juan Mendes
Đề xuất các hình cầu trong hoàn cảnh phù hợp là công thức cho mã hoạt động rõ ràng hơn và có hiệu suất cao hơn. "Passing" yêu cầu phân bổ bộ nhớ động stack liên tục, và điều này sẽ là ngớ ngẩn cho một cái gì đó mà nên là một toàn cầu, chẳng hạn như bộ đệm toàn cầu cho dữ liệu ổ cắm đến. Ví dụ, nếu bạn có một chức năng đọc Winsock recv (), tại sao không ngừng tạo và giải quyết bộ đệm này trong mọi cuộc gọi? Làm cho bộ đệm trở thành toàn cầu. Nhiều chủ đề sẽ không được đọc nó anyway. - James
"Mọi người nhớ quy tắc, và không phải là quy tắc được dự định làm". +1 - tmnol
Chỉ cần tò mò, những gì chương trình tăng gấp đôi kích thước của mã bằng cách đi qua các thông số xung quanh để tránh các biến toàn cầu? Theo kinh nghiệm của tôi, việc sử dụng các biến toàn cục có thể giải quyết các vấn đề phơi nhiễm dữ liệu, nhưng thường có thêm logic phức tạp mà bạn cần phải thêm để đảm bảo các biến ma thuật này hoạt động đúng. - user2167582
Nếu ai đó đi qua khoảng 100 biến, sau đó họ đã không học được một đối tượng là gì. Sử dụng tham chiếu đến đối tượng này sau đó là tồi tệ nhất đi qua xung quanh một con trỏ. Tôi muốn nói rằng quy tắc này không chỉ là sự rõ ràng, mà còn là khả năng thử nghiệm - và việc sử dụng phi toàn cầu có xu hướng làm cho mọi việc dễ dàng hơn nhiều để kiểm tra. - UKMonkey


Giáo sư của tôi thường nói một cái gì đó như: sử dụng các biến toàn cầu là okay nếu bạn sử dụng chúng một cách chính xác. Tôi không nghĩ rằng tôi đã từng sử dụng chúng một cách chính xác, vì vậy tôi hiếm khi sử dụng chúng.


50
2018-01-27 18:42



Đúng vậy. Họ giống như gotos, nếu bạn không biết khi nào thì sử dụng chúng thì không bao giờ làm. - David Holm
Tại công ty hiện tại của tôi, họ sử dụng static biến toàn cầu rất nhiều, ngôn ngữ là C. Bị giới hạn trong các đơn vị dịch tương đối nhỏ, chúng bắt đầu giống như các biến lớp của các đối tượng C ++. - Vorac
Các biến tĩnh @Vorac không phải là các biến toàn cầu, chúng là các biến cục bộ. Một biến toàn cầu là một biến có sẵn ở khắp mọi nơi trong chương trình (do đó "toàn cầu", duh). Đừng nhầm lẫn với biến phạm vi tệp, là các biến được khai báo bên ngoài bất kỳ hàm nào. Biến phạm vi tệp tĩnh không phải là biến toàn cầu. - Lundin
Để sửa bản thân mình, program lifetime, file scope variables. Và chúng trở nên khá toàn cầu khi bạn chuyển một con trỏ tới biến số cho thế giới bên ngoài (điều này là không thể với các biến tự động) .. - Vorac
@ Lundin Tôi đồng ý, static Biến toàn cầu có phạm vi giới hạn cho cùng một đơn vị dịch. Nhưng họ có trọn đời cho đến cuối chương trình như bất kỳ biến toàn cầu nào. - akhilesh1988


Biến toàn cầu chỉ nên được sử dụng khi bạn không có thay thế. Và có, bao gồm cả Singletons. 90% thời gian, các biến toàn cầu được giới thiệu để tiết kiệm chi phí đi qua một tham số. Và sau đó đa luồng / kiểm tra đơn vị / bảo trì mã hóa xảy ra, và bạn có một vấn đề.

Vì vậy, có, trong 90% các tình huống biến toàn cầu là xấu. Các trường hợp ngoại lệ không có khả năng được bạn nhìn thấy trong những năm đại học của bạn. Một ngoại lệ tôi có thể nghĩ ra khỏi đầu của tôi là đối phó với các đối tượng toàn cục vốn có như các bảng ngắt. Những thứ như kết nối DB hình như là toàn cầu, nhưng không phải.


33
2018-01-27 20:22



Một ngoại lệ tôi thấy trong những năm đại học của tôi là chức năng gọi lại đồ họa. Trong XWindows, các callbacks của chuột không có các tham số dữ liệu void * cho phép bạn truyền xung quanh các khối tùy ý của trạng thái chương trình ... (không phải là kết thúc tốt hơn MUCH tốt hơn toàn cầu ...) - Brian Postow
+1 cho "Những thứ như kết nối DB hình như là toàn cầu, nhưng không phải. " - R..
Các bảng ngắt không phải là toàn cục, có một bảng cho mỗi bộ xử lý - nhưng cũng có một phiên bản chương trình của bạn trên mỗi bộ xử lý để nó "hủy bỏ". - immibis


Có, nhưng bạn không phải chịu chi phí của các biến toàn cầu cho đến khi bạn ngừng làm việc trong mã sử dụng biến toàn cầu và bắt đầu viết một cái gì đó khác sử dụng mã sử dụng biến toàn cầu. Nhưng chi phí vẫn còn đó.

Nói cách khác, đó là một chi phí gián tiếp dài hạn và như vậy hầu hết mọi người nghĩ rằng nó không phải là xấu.


18
2018-01-27 18:37





Tôi sẽ trả lời câu hỏi này với một câu hỏi khác: Bạn có sử dụng singeltons/ Là singeltons xấu?

Bởi vì (gần như tất cả) việc sử dụng singelton là một biến toàn cầu được vinh danh.


18
2018-01-27 18:46



Tôi sắp viết một bình luận thông minh nói rằng, "Họ chỉ tệ nếu bạn gọi chúng là các hình cầu thay vì những người độc thân", nhưng bạn đã đánh tôi với nó. - smo
Tôi vẫn đang cố gắng tìm ra những cô đơn địa ngục là LOL. - GeoffreyF67
@Geoffrey: đây là một số mô tả SO tốt - stackoverflow.com/questions/11831/…và đối với một số liên kết tốt: stackoverflow.com/questions/11831/… - Gavin Miller
Đối với hồ sơ, một singleton là một biến toàn cầu với một mẫu thiết kế được tôn vinh (tm) (lol) để làm cho nó âm thanh hợp pháp. Nó cũng không kém phần vì tất cả những lý do tương tự. - R..
@GavinMiller Có nói rằng đó là OK nếu bạn sử dụng simpleton ... ooops, singleton euphemism? - Juan Mendes


Nếu có thể, mã của bạn sẽ kết thúc theo đánh giá chuyên sâu trong một Tòa án tối cao dùng thử, sau đó bạn muốn đảm bảo tránh các biến toàn cầu.

Xem bài viết này: Mã Buggy breathalyzer phản ánh tầm quan trọng của việc xem xét nguồn

Có một số vấn đề với   phong cách của mã đã được xác định   bởi cả hai nghiên cứu. Một trong những phong cách   các vấn đề liên quan đến người đánh giá   là việc sử dụng rộng rãi không được bảo vệ   biến toàn cầu. Đây được coi là   hình thức nghèo vì nó làm tăng   rủi ro mà trạng thái chương trình sẽ   trở nên không nhất quán hoặc các giá trị đó   sẽ vô tình bị sửa đổi hoặc   ghi đè. Các nhà nghiên cứu cũng   bày tỏ một số lo ngại về thực tế   độ chính xác thập phân đó không   duy trì liên tục trong suốt   mã.

Người đàn ông, tôi đặt cược những nhà phát triển có nhu cầu họ đã không sử dụng các biến toàn cầu!


18
2018-05-16 23:01



Đó là tiếng cười hay nhất tôi đã có trong một thời gian. Một ví dụ thực sự về lý do tại sao sự phát triển nguồn đóng cho lợi nhuận là xấu, và một ví dụ điển hình về các vars toàn cầu đã biến mất! - Evil Spork


Vấn đề mà các biến toàn cầu tạo ra cho lập trình viên là nó mở rộng -sự ghép liên hợp bề mặt giữa các thành phần khác nhau đang sử dụng các biến toàn cầu. Điều này có nghĩa là khi số lượng các thành phần sử dụng một biến toàn cầu tăng lên, độ phức tạp của các tương tác cũng có thể tăng lên. Khớp nối tăng này thường làm cho các lỗi dễ dàng hơn khi đưa vào hệ thống khi thực hiện các thay đổi và cũng làm cho các lỗi khó chẩn đoán và chính xác hơn. Khớp nối tăng này cũng có thể làm giảm số lượng các tùy chọn sẵn có khi thực hiện thay đổi và có thể tăng nỗ lực cần thiết cho những thay đổi thường xuyên phải theo dõi qua các mô-đun khác nhau cũng đang sử dụng biến toàn cục để xác định hậu quả của thay đổi.

Mục đích của đóng gói, về cơ bản là ngược lại với việc sử dụng các biến toàn cục, là giảm ghép nối để làm cho sự hiểu biết và thay đổi nguồn dễ dàng hơn và an toàn hơn và dễ dàng được kiểm tra hơn. Nó dễ sử dụng hơn nhiều kiểm tra đơn vị khi các biến toàn cục không được sử dụng.

Ví dụ nếu bạn có một biến số nguyên đơn giản được sử dụng như một chỉ báo liệt kê các thành phần khác nhau sử dụng như một máy trạng thái và sau đó bạn thực hiện thay đổi bằng cách thêm một trạng thái mới cho một thành phần mới, bạn phải theo dõi các thành phần để đảm bảo rằng thay đổi sẽ không ảnh hưởng đến chúng. Một ví dụ về một vấn đề có thể là nếu switch câu lệnh để kiểm tra giá trị của biến toàn cục liệt kê với case báo cáo cho mỗi giá trị hiện tại đang được sử dụng ở những nơi khác nhau và điều đó xảy ra là một số switch báo cáo không có default trường hợp để xử lý một giá trị bất ngờ cho toàn cầu đột ngột bạn có hành vi không xác định cho đến nay khi ứng dụng được quan tâm.

Mặt khác, việc sử dụng một vùng dữ liệu chia sẻ có thể được sử dụng để chứa một tập hợp các tham số chung được tham chiếu trong toàn bộ ứng dụng. Cách tiếp cận này thường được sử dụng với các ứng dụng nhúng có dấu chân bộ nhớ nhỏ.

Khi sử dụng các biến toàn cầu trong các loại ứng dụng này thường là trách nhiệm ghi vào vùng dữ liệu được phân bổ cho một thành phần duy nhất và tất cả các thành phần khác nhìn thấy khu vực như const và đọc từ nó, không bao giờ viết cho nó. Sử dụng phương pháp này giới hạn các vấn đề có thể phát triển.

Dưới đây là một số vấn đề với việc sử dụng các biến toàn cầu cần phải được làm việc xung quanh.

Khi nguồn cho một biến toàn cầu chẳng hạn như cấu trúc được sửa đổi, mọi thứ sử dụng nó phải được biên dịch lại để mọi thứ sử dụng biến biết kích thước thật và mẫu bộ nhớ của nó.

Nếu nhiều hơn một thành phần có thể sửa đổi biến toàn cầu, bạn có thể gặp phải các vấn đề với dữ liệu không nhất quán trong biến toàn cầu. Với một ứng dụng đa luồng, bạn có thể cần phải thêm một số loại khóa hoặc vùng quan trọng để cung cấp một cách để chỉ một luồng tại một thời điểm có thể sửa đổi biến toàn cầu và khi một luồng đang sửa đổi biến, tất cả thay đổi được hoàn thành và cam kết trước khi các chủ đề khác có thể truy vấn biến hoặc sửa đổi nó.

Gỡ lỗi một ứng dụng đa luồng sử dụng biến toàn cầu có thể khó khăn hơn. Bạn có thể chạy vào điều kiện chủng tộc có thể tạo ra các khiếm khuyết khó tái tạo. Với một số thành phần giao tiếp thông qua một biến toàn cầu, đặc biệt là trong một ứng dụng đa luồng, có thể biết thành phần nào đang thay đổi biến khi nào và làm thế nào nó thay đổi biến có thể rất khó hiểu.

Tên xung đột có thể là một vấn đề với việc sử dụng các biến toàn cầu. Biến cục bộ có cùng tên với biến toàn cục có thể ẩn biến toàn cầu. Bạn cũng gặp phải vấn đề quy ước đặt tên khi sử dụng ngôn ngữ lập trình C. Một công việc xung quanh là chia hệ thống thành các hệ thống con với các biến toàn cầu cho một hệ thống con cụ thể, tất cả bắt đầu bằng ba chữ cái đầu tiên (xem phần này giải quyết xung đột không gian tên trong mục tiêu C). C ++ cung cấp các không gian tên và với C bạn có thể làm việc xung quanh điều này bằng cách tạo ra một cấu trúc có thể nhìn thấy trên toàn cầu có các thành phần dữ liệu và các con trỏ tới dữ liệu và các hàm được cung cấp trong một tệp như tĩnh. cấu trúc hiển thị trên toàn cầu.

Trong một số trường hợp, ý định ứng dụng ban đầu được thay đổi sao cho các biến toàn cục cung cấp trạng thái cho một luồng đơn được sửa đổi để cho phép một số luồng trùng lặp chạy. Một ví dụ sẽ là một ứng dụng đơn giản được thiết kế cho một người dùng duy nhất sử dụng các biến toàn cầu cho tiểu bang và sau đó một yêu cầu đến từ quản lý để thêm một Giao diện REST cho phép các ứng dụng từ xa hoạt động như người dùng ảo. Vì vậy, bây giờ bạn chạy vào việc phải sao chép các biến toàn cục và thông tin trạng thái của chúng để người dùng đơn lẻ cũng như mỗi người dùng ảo từ các ứng dụng từ xa có bộ biến toàn cầu duy nhất của riêng họ.


18
2017-07-01 02:10



Đây là bàn tay ngoại trừ tốt nhất, giải thích tất cả mọi thứ có nó. Thanh danh! - johndoevodka


Các biến toàn cục cũng xấu như bạn tạo ra, không kém.

Nếu bạn đang tạo một chương trình được đóng gói hoàn toàn, bạn có thể sử dụng các hình cầu. Đó là một "tội lỗi" để sử dụng các hình cầu, nhưng các tội lỗi lập trình là lóng mang triết học.

Nếu bạn kiểm tra L.in.oleum, bạn sẽ thấy một ngôn ngữ có các biến chỉ toàn cục. Nó không thể đánh giá được vì tất cả các thư viện đều không có lựa chọn nào khác ngoài việc sử dụng các hình cầu.

Điều đó nói rằng, nếu bạn có lựa chọn, và có thể bỏ qua triết lý lập trình viên, hình cầu không phải là tất cả những điều xấu.

Không phải là Gotos, nếu bạn sử dụng chúng đúng cách.

Vấn đề lớn "xấu" là, nếu bạn sử dụng chúng sai, mọi người sẽ hét lên, những con quạ bị đổ sập, và thế giới sẽ nổ tung ... hoặc một thứ như thế.


16
2018-01-27 18:44



Downplaying các vấn đề của việc sử dụng globals cho một sinh viên bối rối không phải là một ý tưởng tốt IMO. - GEOCHET
Triết lý thiết kế không phải là khách quan. Không ít nhất. Chỉ vì hầu hết các lập trình viên không thích điều gì đó, không có nghĩa là người lập trình không nên nhìn vào thứ gì đó. Nó rất dễ dàng để sử dụng chung của globals mà không có kết thúc thế giới. Hãy để anh ta làm điều đó, đấu tranh (biết anh ta sẽ), và tìm hiểu làm thế nào. - user54650
Rich là đúng. Câu trả lời này không nói bất cứ điều gì về những gì là / không phải là xấu (hoặc làm thế nào globals có thể được sử dụng một cách an toàn), chỉ rằng "họ không phải là xấu như tất cả điều đó. Như vậy, nó chỉ downplays các vấn đề. - jalf
Tôi không đồng ý rằng các biến toàn cầu chỉ là "xấu khi bạn tạo ra chúng". Tôi nghĩ rằng một trong những vấn đề chính, đặc biệt là trong nhiều nhà phát triển, liên kết với thế giới mà hầu hết chúng ta sống, làm việc và lập trình, là các biến toàn cục giúp cho ELSE có cơ hội làm cho mã của bạn trở nên tồi tệ. - gariepy