Чи погані глобальні змінні? [зачинено]


247

Чи глобальні змінні в C / C ++ такі погані, як вважає мій професор?


17
Я кусаю на випадок, якщо він намагається розповісти жарт ... "як вони погані"?
Зак Скривена

13
Я думаю, що це питання було досить цікавим! Розробка програмного забезпечення все ще стикається з тими ж старими підводними каменями з самого початку, і програмісти часто все ще не знають, що використання глобальних змінних, gotos, короткої названої змінної НЕ проблема. Неправильний код пишеться щодня без їх використання. +1
Сільвейн Родріг

69
Як ми можемо відповісти? Він не сказав нам, як погано вважає їх професор. :)
Стів Фаллоуз

9
@Juan Mendes Я на 100% з вами згоден! Проблему, про яку я говорив, полягає в тому, що багато розробників знають, що вони не повинні використовувати глобальні змінні, але вони просто НЕ знають, чому! І, таким чином, я бачив багато великих програмних програм, де кожна функція отримувала однакову мегаструктуру, що містить +100 полів - дивіться мамо, глобальних змінних немає! Та сама проблема, як і так звана "хороша практика": вони є хорошими методами у деяких контекстах, а не у всіх контекстах. Використовуючи їх, МОЖЕ створити немислимий код. Ура.
Сільвен Родріг

3
Глобальних змінних дуже мало. Одним із можливих, але дискусійних застосувань буде глобальний об’єкт "конфігурації", який читає у конфігураційному файлі один раз при запуску.
Силер

Відповіді:


257

Проблема глобальних змінних полягає в тому, що оскільки кожна функція має доступ до них, стає важче зрозуміти, які функції насправді читають і записують ці змінні.

Щоб зрозуміти, як працює програма, вам доведеться враховувати кожну функцію, яка модифікує глобальний стан. Це можна зробити, але в міру того, як додаток зростає, це стає важче до практично неможливого (або, принаймні, повної трати часу).

Якщо ви не покладаєтесь на глобальні змінні, ви можете переходити стан між різними функціями за потребою. Таким чином, ви маєте набагато більше шансів зрозуміти, що робить кожна функція, оскільки вам не потрібно враховувати глобальну державу.


10
Ця відповідь справді гарна. У поєднанні з «мінімізації змінної сфери» відповідь stackoverflow.com/questions/357187 / ...
bobobobo

17
Замініть "class" на "application" та "object object" на "global state", і ви зробите точно такий же аргумент, щоб не використовувати змінні елементи (ака поля) в класах. Справжня відповідь - використовувати їх, коли це доречно.
Ян Голдбі

2
Небагато (можливо, нерозумних) питань: 1) Якщо ви хочете знати, які функції читають і записують ці змінні, ви не могли б просто скористатися функцією "знайти" в редакторі, щоб помітити випадки, коли значення цих змінних змінюються? 2) "Це можна зробити, ... повна марна трата часу". Чи можете ви навести приклад? 3) "Якщо ви не покладаєтесь на глобальні змінні, ... вам не потрібно брати до уваги глобальний стан." Я не розумію, як це є перевагою. Можливо, приклад цього міг би працювати для мене.
Андрій

2
@bobobobo непрацююче посилання, чи можемо ми отримати скриншот від вас, користувача 10k +?
noɥʇʎԀʎzɐɹƆ

3
@ noɥʇʎԀʎzɐɹƆ Отож! i.imgur.com/RwRgJLZ.jpg
Mateen Ulhaq

85

Важливо - пам’ятати загальну мету: чіткість

Правило "без глобальних змінних" існує тому, що більшість часу глобальні змінні роблять значення коду менш зрозумілим.

Однак, як і багато правил, люди пам’ятають правило, а не те, що було призначено.

Я бачив програми, які, здається, подвоюють розмір коду, передаючи величезну кількість параметрів навколо, щоб уникнути зла глобальних змінних. Зрештою, використання глобальних програм зробило б програму зрозумілішою для тих, хто її читає. Нерозумно дотримуючись слова правила, початковий програміст провалив наміри правила.

Так, так, глобалісти часто погані. Але якщо ви відчуваєте, що зрештою, наміри програміста з’ясуються зрозумілішими завдяки використанню глобальних змінних, тоді йдіть далі. Однак пам’ятайте про падіння чіткості, яке автоматично настає, коли ви змушуєте когось отримати доступ до другого фрагмента коду (глобальних), щоб зрозуміти, як працює перший фрагмент.


8
Запропонувати використання глобальної системи замість передачі змінних - це рецепт для того, щоб зробити ваш код не багаторазовим і небезпечним для багатопотокової передачі
Хуан Мендес

16
Запропонувати глобальний досвід у правильних обставинах - це рецепт більш чіткого та високоефективного коду. "Передача" вимагає постійного динамічного розподілу пам'яті стека, і це було б нерозумно для чогось, що повинно бути глобальним, наприклад глобального буфера для вхідних даних сокета. Наприклад, якщо у вас є функція, яка читає Winsock recv (), чому постійно створювати та розміщувати цей буфер під час кожного дзвінка? Зробити буфер глобальним. Кілька ниток не будуть читати його все одно.
Джеймс

Цікаво, яка програма подвоює розмір коду, передаючи параметри навколо, щоб уникнути глобальних змінних? На мій досвід, використання глобальних змінних може вирішити проблеми із викриттям даних, але зазвичай є додаткова складна логіка, яку потрібно додати, щоб переконатися, що ці магічні змінні поводяться належним чином.
користувач2167582

3
Якщо хтось передає близько 100 змінних, вони не дізналися, що таке об'єкт. Використання посилання на цей об'єкт в гіршому випадку проходить навколо вказівника. Я б сказав, що правило - це не просто ясність, але й доказовість - і використання неглобальних тенденцій робить тести набагато простішими.
UKMonkey

2
"Якщо хтось передає близько 100 змінних, вони не дізналися, що таке об'єкт." Погоджено, але не весь світ об'єктно-орієнтований. Моїм особистим прикладом подвоєння розміру коду була велика програма Fortran, приблизно в 1986 році. Як новий співробітник університету, я "покращив" його, додавши до кожного дзвінка близько 30 параметрів, усуваючи всі глобальні точки. Потім розв’язав своє поліпшення, коли зрозумів, що зробив.
Том Уест,

64

Мій професор казав щось на кшталт: використання глобальних змінних добре, якщо ви правильно їх використовуєте. Я не думаю, що я коли-небудь добре отримував їх від використання правильно, тому рідко їх взагалі використовував.


25
Такий справжній. Вони схожі на готос, якщо ви не знаєте, коли ними користуватися, то ніколи цього не робите.
Девід Холм

5
У моїй теперішній компанії вони багато використовують staticглобальні змінні, мова - це C. Отримавши обмеження на відносно невеликі одиниці перекладу, вони починають нагадувати змінні класи об’єктів C ++.
Vorac

1
Статичні змінні @Vorac не є глобальними змінними, вони є локальними змінними. Глобальна змінна - це змінна, доступна всюди в програмі (звідси "глобальна", так). Не слід плутати змінні області файлу , що є змінними, оголошеними поза будь-якої функції. Статична змінна область файлу не є глобальною змінною.
Лундін

1
Для того, щоб виправити себе, program lifetime, file scope variables. І вони стають досить глобальними, як тільки ви переходите вказівник на змінну до зовнішнього світу (що неможливо з автоматичними змінними) ..
Vorac

@Lundin Я погоджуюся, staticглобальні змінні обмежують сферу застосування однією і тією ж одиницею перекладу. Але вони мають життя до кінця програми, як будь-яка глобальна змінна.
akhilesh1988

38

Глобальні змінні слід використовувати лише тоді, коли у вас немає альтернативи. І так, сюди входить Сінглтон. У 90% часу глобальні змінні вводяться для економії витрат на проходження параметра. І тоді відбувається багатопотокове тестування / тестування / кодування технічного обслуговування, і у вас є проблеми.

Так, так, у 90% ситуацій глобальні змінні є поганими. Винятки, швидше за все, ви не побачите у студентські роки. Один виняток, про який я можу придумати верхню частину голови, - це робота з суттєво глобальними об'єктами, такими як таблиці переривань. Такі речі, як підключення до БД, здаються глобальними, але ні.


2
Єдиним винятком, який я бачив у роки навчання в коледжі, були функції зворотного виклику графіки. У XWindows миша-зворотні виклики не мають недійсні аргументи * дані , які дозволили вам обійти довільні шматки стану програми ... (не те що в кінцевому підсумку бути набагато краще , ніж в глобальному так чи інакше ...)
Брайан Postow

10
+1 для "Такі речі, як з'єднання з БД, здаються глобальними, але не є."
R .. GitHub СТОП ДОПОМОГАЙТЕ

1
Таблиці переривань не є глобальними, є одна на кожен процесор, але також є один екземпляр вашої програми на процесор, і він "скасовується".
користувач253751

1
Чи може хто-небудь просвітити мене, чому з'єднання БД не є глобальними (і що було б хорошою альтернативою)? Я завжди вважав зв'язки як один з рідкісних випадків, коли глобальні точки були прийнятними.
Флоелла

33

Проблема, яку створюють глобальні змінні для програміста, полягає в тому, що він розширює міжкомпонентну поверхню зв'язку між різними компонентами, які використовують глобальні змінні. Це означає, що зі збільшенням кількості компонентів, що використовують глобальну змінну, складність взаємодій також може зростати. Таке посилене з'єднання, як правило, полегшує введення дефектів у систему під час внесення змін, а також ускладнює діагностику та виправлення дефектів. Це збільшення зв'язку також може зменшити кількість доступних варіантів при внесенні змін, і це може збільшити зусилля, необхідні для змін, оскільки часто потрібно простежити різні модулі, які також використовують глобальну змінну, щоб визначити наслідки змін.

Метою інкапсуляції , яка в основному є протилежною використанню глобальних змінних, є зменшення зв'язку, щоб зробити розуміння та зміну джерела простішим, безпечнішим та легшим для перевірки. Набагато простіше використовувати тестування одиниць, коли глобальні змінні не використовуються.

Наприклад, якщо у вас є проста глобальна ціла змінна, яка використовується в якості перерахованого індикатора, який різні компоненти використовують як машину стану, а ви потім вносите зміни, додаючи новий стан для нового компонента, ви повинні простежити всі інші компоненти, щоб гарантувати, що зміни не торкнуться їх. Прикладом можливої ​​проблеми може стати те, що в різних місцях використовується switchоператор для перевірки значення глобальної змінної перерахунку з caseоператорами для кожного з поточних значень, і так трапляється, що в деяких з switchоператорів немає defaultсправи для обробки несподіване значення для глобального раптом у вас не визначене поведінка, що стосується програми.

З іншого боку, використання спільної області даних може бути використано, щоб містити набір глобальних параметрів, на які посилається у всій програмі. Цей підхід часто використовується для вбудованих додатків з невеликими розмірами пам'яті.

При використанні глобальних змінних у подібних додатках, як правило, відповідальність за запис у область даних покладається на один компонент, а всі інші компоненти бачать область як constта прочитану з неї, ніколи не пишучи на неї. Такий підхід обмежує проблеми, які можуть розвиватися.

Кілька проблем із глобальних змінних, над якими потрібно вирішити

Коли джерело для такої глобальної змінної, як структура, модифікується, все, що використовується, повинно бути перекомпільовано, щоб все, що використовувало змінну, знало її справжній розмір і шаблон пам'яті.

Якщо більш ніж один компонент може змінити глобальну змінну, ви можете зіткнутися з проблемами з непослідовними даними, що знаходяться в глобальній змінній. За допомогою програми з багатопотоковою передачею вам, ймовірно, потрібно буде додати якусь блокувальну чи критичну область, щоб забезпечити спосіб, щоб лише один потік одночасно міг змінити глобальну змінну, і коли потік змінює змінну, усі зміни завершені і зроблено раніше, ніж інші потоки можуть запитувати змінну або змінювати її.

Налагодження багатопотокової програми, яка використовує глобальну змінну, може бути складніше. Ви можете зіткнутися з умовами перегонів, які можуть створити дефекти, які важко повторити. Коли декілька компонентів спілкуються через глобальну змінну, особливо в багатопотоковому додатку, бути в змозі зрозуміти, який компонент змінює змінну, коли і як вона змінює змінну, може бути дуже важко зрозуміти.

Зіткнення імен може бути проблемою при використанні глобальних змінних. Локальна змінна, яка має те саме ім'я, що і глобальна змінна, може приховати глобальну змінну. Ви також стикаєтеся з проблемою з умовами іменування під час використання мови програмування C. Робота полягає в тому, щоб розділити систему на підсистеми з глобальними змінними для певної підсистеми, починаючи з тих самих перших трьох літер (див. Це на вирішенні зіткнень простору імен у цілі C ). C ++ надає простори імен, і за допомогою C ви можете обійти це, створивши глобально видиму структуру, членами якої є різні елементи даних та покажчики на дані та функції, які надаються у файл як статичний, а також видимість файлу лише для того, щоб на них можна було посилатися лише через глобально видима структура.

У деяких випадках вихідний намір програми змінюється таким чином, що глобальні змінні, що забезпечували стан для одного потоку, змінюються, щоб дозволити запускати декілька повторюваних потоків. Прикладом може бути проста програма, призначена для одного користувача, що використовує глобальні змінні для стану, а потім від управління надходить запит на додавання інтерфейсу REST, щоб віддалені програми могли діяти як віртуальні користувачі. Отже, тепер у вас виникає необхідність дублювати глобальні змінні та інформацію про їх стан, щоб у одного користувача, а також у кожного віртуального користувача з віддалених додатків був свій унікальний набір глобальних змінних.

Використання C ++ namespaceта structметодики C

Для мови програмування C ++ ця namespaceдиректива є величезною допомогою для зменшення шансів зіткнення імені. namespaceпоряд із classрізними ключовими словами доступу ( private, protectedі public) надають більшість інструментів, необхідних для інкапсуляції змінних. Однак мова програмування на C не дає цієї директиви. Ця публікація stackoverflow, простори імен у C , пропонує деякі методи для C.

Корисна методика полягає в тому, щоб мати єдину область даних резидентної пам’яті, яка визначається як a, structяка має глобальну видимість, і всередині цього structє вказівниками на різні глобальні змінні та функції, які піддаються впливу. Фактичні визначення глобальних змінних задаються обсягом файлів за допомогою staticключового слова. Якщо ви використовуєте constключове слово, щоб вказати лише те, що читаються, компілятор може допомогти вам застосувати доступ лише для читання.

Використання structметодики також може інкапсулювати глобальний, щоб він став своєрідним пакетом або компонентом, який, як правило, є глобальним. Маючи такий компонент, стає легше керувати змінами, які впливають на глобальний та функціональний за допомогою глобального.

Однак в той час namespaceабо structметод може допомогти управляти конфліктом імен, що лежить в основі проблема межкомпонентное зв'язку яких використання глобал вводять особливо в сучасних багатопотокових застосуваннях, все ще існує.


Це найкраще пояснення руки вниз, пояснює все, що там є. Кудо!
johndoevodka

У вашій мові має бути правило коду, щоб запобігти використанню занадто великої кількості класів.
Мельбурнський розробник

19

Так, але ви не несете вартості глобальних змінних, поки не перестанете працювати в коді, який використовує глобальні змінні, і не почнете писати щось інше, що використовує код, який використовує глобальні змінні. Але вартість все ж є.

Іншими словами, це довгострокова непряма вартість, і тому такі люди вважають, що це не погано.


19

Якщо можливо, ваш код буде піддаватися інтенсивному перегляду під час судового розгляду у Верховному суді , тоді ви хочете уникнути глобальних змінних.

Дивіться цю статтю: Код повітряного дихального засобу Баггі відображає важливість огляду джерела

Були деякі проблеми зі стилем коду, які були визначені обома дослідженнями. Одним із стилістичних питань, що хвилювали рецензентів, було широке використання незахищених глобальних змінних . Це вважається поганою формою, оскільки це збільшує ризик того, що стан програми стане непослідовним, або що значення будуть ненавмисно змінені або перезаписані. Дослідники також висловили певне занепокоєння з приводу того, що десяткова точність не підтримується послідовно у всьому коді.

Людина, я думаю, що розробники хочуть, щоб вони не використовували глобальні змінні!


6
Це був найкращий сміх, який я мав за деякий час. Справжній приклад того, чому розвиток закритого джерела для отримання прибутку є поганим, а хороший приклад глобальних змін пішов не так!
Evil Spork

Тут встановлено, що глобальні змінні переглядаються з презирством. Тут немає нічого, що свідчить про те, що глобальні змінні були справжньою проблемою в коді. SysTest заявив, що, хоча код "не був написаний таким чином, що відповідає звичним передовим практикам розробки програмного забезпечення", він все ще "надійно дасть послідовні результати тестів". Тож ніякої шкоди від глобалістів насправді не було зафіксовано. Як я бачу, вони щойно встановили, що "Ну, ці деви не практикують таку ж релігію кодування, що й решта мейнстріму".
LionKimbro

19

Глобальні змінні настільки ж погані, як і ти їх робиш, не менше.

Якщо ви створюєте повністю капсульовану програму, ви можете використовувати глобальні програми. Користуватися глобальними гріхами - це "гріх", але програмування гріхів є філософською філософією.

Якщо ви перевірите L.in.oleum , ви побачите мову, змінні якої є виключно глобальними. Це неможливо, тому що всі бібліотеки не мають іншого вибору, крім використання глобальних.

Однак, якщо у вас є вибір і ви можете ігнорувати філософію програміста, глобалісти не все так погано.

Ні Готос, ні якщо ви правильно їх використовуєте.

Велика "погана" проблема полягає в тому, що, якщо ви їх неправильно використовуєте, люди кричать, марсовий земля розбивається, і світ вибухає .... або щось подібне.


17
Зниження проблем використання глобалів для заплутаного студента - це не дуже гарна ідея ІМО.
ГЕОЧЕТ

3
Філософія дизайну не є об'єктивною. Не в останню чергу. Тільки тому, що більшості програмістів щось не подобається, це не означає, що ніколи не слід вдивлятися в це щось. Легко загальнокористуватися глобальними мережами без кінця світу. Дозвольте йому це зробити, боротися (знаючи, що буде), і навчитися як.
користувач54650

7
Річ прав. Ця відповідь нічого не говорить про те, що є / не погано (або як глобально можна використовувати безпечно), лише те, що "вони не такі погані, як усе це. Як таке, це лише применшує проблеми.
jalf

4
Я не погоджуюся з тим, що глобальні змінні є такими ж «поганими, як ти їх робиш». Я думаю, що однією з головних проблем, особливо в цьому взаємозалежному світі з багатьма розробниками, який більшість з нас живе, працює і програмує, є те, що глобальні змінні дають комусь ELSE можливість зробити ваш код поганим.
gariepy

@gariepy, поки не знаю, що, хоча, мова йде про статику: D нормально, так це ... і в моєму додатку є лише одна або дві глобальні змінні, це одна з Visual Studio, DEBUG і TRACE, які ми зазвичай не використовуємо: D
мертвийManN

17

Я відповів би на це запитання ще одним питанням: Чи використовуєте Ви сінгелтони / Чи сингелтони погані?

Тому що (майже все) використання сингелтону - це прославлена ​​глобальна змінна.


11
Я збирався опублікувати розумний коментар, в якому сказали: "Вони погані лише, якщо ти називаєш їх глобалами замість синглів", але ти побив мене до цього.
смо

Я все ще намагаюся розібратися, що за пекло синглів є LOL.
ДжеффріF67

1
@Geoffrey: ось деякі хороші опису SO - stackoverflow.com/questions/11831 / ... і для деяких хороших посилань: stackoverflow.com/questions/11831 / ...
Gavin Miller

10
Для запису синглтон - це глобальна змінна з прославленим іменем Шаблони дизайну (tm) (lol), щоб це звучало законно. Це однаково погано з тих же причин.
R .. GitHub СТОП ДОПОМОГАТИ ВІД

@GavinMiller Ви кажете, що це нормально, якщо ви використовуєте симптон ... ооопс, одиночний евфемізм?
Хуан Мендес

14

Справа менше в тому, що вони погані , і тим більше, що вони небезпечні . У них є свої плюси і мінуси, і бувають ситуації, коли вони є найбільш ефективним або єдиним способом досягнення певного завдання. Однак їх дуже легко зловживати, навіть якщо ви вживаєте заходів, щоб завжди правильно їх використовувати.

Кілька плюсів:

  • Доступ можна отримати з будь-якої функції.
  • Доступ можна отримати з декількох потоків.
  • Ніколи не вийде із сфери застосування, поки програма не закінчиться.

Кілька мінусів:

  • Доступ можна отримати з будь-якої функції, не потребуючи явного перетягування в якості параметра та / або документування.
  • Не безпечно для ниток.
  • Забруднює глобальний простір імен і потенційно спричиняє зіткнення імен, якщо не буде вжито заходів для запобігання цьому.

Зауважте, якщо ви хочете, що перші два плюси та перші два мінуси, які я перерахував, - це абсолютно те саме, лише з різними формулюваннями. Це тому, що особливості глобальної змінної дійсно можуть бути корисними, але самі функції, які роблять їх корисними, є джерелом усіх їхніх проблем.

Кілька потенційних варіантів вирішення деяких проблем:

  • Поміркуйте, чи є вони насправді найкращим чи найефективнішим рішенням проблеми. Якщо є якісь кращі рішення, використовуйте це замість цього.
  • Помістіть їх у простір імен [C ++] або singleton structure [C, C ++] з унікальним іменем (хорошим прикладом може бути Globalsабо GlobalVars) або використовувати стандартизовану конвенцію іменування глобальних змінних (наприклад, global_[name]або g_module_varNameStyle(як зазначено underscore_d у коментарях) )). Це одночасно документує їх використання (ви можете знайти код, який використовує глобальні змінні, шукаючи простір імен / ім’я структури) та мінімізуючи вплив на глобальний простір імен.
  • Для будь-якої функції, яка отримує доступ до глобальних змінних, чітко задокументуйте, які змінні вона читає та які записує. Це полегшить усунення несправностей.
  • Помістіть їх у власний вихідний файл і оголосіть їх externу відповідному заголовку, щоб їх використання могло бути обмежене одиницями компіляції, які потребують доступу до них. Якщо ваш код покладається на безліч глобальних змінних, але кожен блок компіляції потребує доступу лише до декількох файлів, ви можете розглянути їх сортування в декілька вихідних файлів, тому простіше обмежити доступ кожного файлу до глобальних змінних.
  • Налаштуйте механізм їх блокування та розблокування та / або спроектуйте свій код так, щоб якомога менше функцій потребувало фактичної модифікації глобальних змінних. Читати їх набагато безпечніше, ніж писати їх, хоча перегони потоків все ще можуть спричинити проблеми в багатопотокових програмах.
  • В основному, мінімізуйте доступ до них та максимізуйте унікальність імен. Ви хочете уникнути зіткнень з іменами та мати якомога менше функцій, які потенційно можуть змінювати будь-яку задану змінну.

Хороші вони чи погані, залежить від того, як ви їх використовуєте. Більшість, як правило, погано їх використовує, звідси загальна обережність щодо них. Якщо їх правильно використовувати, вони можуть стати головним благом; якщо використовується погано, проте, вони можуть і будуть повертатися , щоб вкусити вас , коли і як ви менше всього цього чекаєте.

Хороший спосіб поглянути на те, що вони самі не погані, але вони дозволяють поганий дизайн і можуть помножувати наслідки поганого дизайну в експоненціальній формі.


Навіть якщо ви не збираєтесь ними користуватися, краще знати, як безпечно ними користуватися, і не бажати, ніж не користуватися ними, оскільки ви не знаєте, як безпечно ними користуватися. Якщо ви коли-небудь опинитесь у ситуації, коли вам потрібно підтримувати наявний код, який спирається на глобальні змінні, ви можете зіткнутися з труднощами, якщо не знаєте, як правильно їх використовувати.


1
+1 за прагматизм. Однотонний часто просто додає панель котлів, щоб зробити екземпляр і рефактор членами, і ви отримаєте ... глобальні змінні, що просто маскуються під іншою назвою. Навіщо турбуватися, окрім як уникнути Гріха Глобалів просто технічно? Простори імен - це як бар'єр, але я вважаю простий g_module_varNameStyleідеально розбірливим. Щоб було зрозуміло, я не використовую глобалістів, якщо я можу це легко уникнути - ключове слово легко , тому що, оскільки я перестала вірити, що їх треба уникати - а точніше - заплутано - будь-якою ціною, я проводжу набагато кращий час, і мій code is (shock!) набагато акуратніше
underscore_d

@underscore_d Це, головним чином, просто мати спосіб розмежувати глобальні та локальні змінні легше, а також спростити пошук глобальних змінних під час пошуку вашого коду, з метою запобігання плутанини щодо того, чи є змінна глобальною чи локальною / параметр / член / і т.д. Редагування моєї відповіді стандартною ідеєю конвенції про іменування, дякую.
Час Джастіна - Відновіть Моніку

1
"Для будь-якої функції ... явно документуйте, які змінні" - пам'ятайте, це перехідне відношення. Якщо функція A викликає функції B і C, то вона зчитує і записує змінні, записані обома (плюс ті, що знаходяться безпосередньо в її тілі)
Caleth,

11

Як хтось сказав (я перефразую) в іншій темі "Такі правила не слід порушувати, поки ви повністю не зрозумієте наслідки цього".

Бувають випадки, коли потрібні глобальні змінні або, принаймні, дуже корисні (наприклад, робота із зворотними дзвінками, визначеними системою). З іншого боку, вони також дуже небезпечні з усіх причин, про які вам сказали.

Існує багато аспектів програмування, які, ймовірно, слід залишити експертам. Іноді вам потрібен дуже гострий ніж. Але ви не отримаєте використовувати його, поки не будете готові ...


1
Я погоджуюся, якщо ви розумієте наслідки, це нормально, порушуйте правила, але якщо ви ловите себе це часто, ви робите щось не так
Хуан Мендес

9

Глобальні змінні, як правило, погані, особливо якщо інші люди працюють над тим самим кодом і не хочуть витрачати 20 хвилин на пошук усіх місць, на які вказана змінна. А додавання ниток, що змінюють змінні, приносить абсолютно новий рівень головних болів.

Глобальні константи в анонімному просторі імен, використовуваному в одній одиниці перекладу, є чудовими та всюдисущими в професійних додатках та бібліотеках. Але якщо дані є мутаційними та / або їх потрібно ділити між декількома ТУ, ви можете захопити їх інкапсуляцією - якщо не заради дизайну, то заради налагодження чи роботи з вашим кодом.


9

Використання глобальних змінних на зразок схоже на підмітання бруду під килим. Це швидко виправити та набагато простіше за короткий термін, ніж дістати пилосос або пилосос для його очищення. Однак якщо ви коли-небудь пізніше пересунете килимок, під вами буде великий безлад.


ледача метафора, позбавлена ​​контексту! = відповідь
підкреслити

1
@underscore_d: Я не згоден. Це дискусійне запитання, навіть якщо воно не позначене як таке (можливо, через його вік), і тому відповіді на кшталт цього є абсолютно справедливими, і це означає, що це стосується питання щодо ОП.
gariepy

7

Глобальні змінні погані, якщо вони дозволяють маніпулювати аспектами програми, які слід змінювати лише локально. У OOP глобалісти часто суперечать ідеї інкапсуляції.


7

Я думаю, що ваш професор намагається зупинити шкідливу звичку до того, як вона навіть розпочнеться.

Глобальні змінні мають своє місце, і як багато хто казав, знати, де і коли їх використовувати, може бути складним. Тож я думаю, а не вникати в нітратну глибокість того, чому, як, коли і де глобальних змінних ваш професор вирішив просто заборонити. Хто знає, він може заборонити їх у майбутньому.


7

Абсолютно не. Зловживання ними, хоча ... це погано.

Бездумно їх видаляти заради цього - це просто безглуздо. Якщо ви не знаєте передових і недоліків, найкраще керуватися чітко та робити так, як вас вчили / вчили, але з глобальними змінними немає нічого неявного. Коли ви зрозумієте плюси і мінуси, краще прийміть власне рішення.


3
-1 Існує чимало причин для обережності щодо глобальних змінних: найбільша для мене полягає в тому, що приховані залежності та глобальний процес тестування коду будь-яким передбачуваним способом є надзвичайно важким. Якщо ви не цінуєте можливість тестування свого коду автоматизованим способом, я б припустив, що глобальні змінні не заподіють вам нічого, крім болю. І крім того, у добре структурованій програмі завжди є альтернативи.
jkp

1
те, що ви говорите, - це масштабна надмірна генералізація, ретельне використання глобального стану не перешкоджає автоматизованому тестуванню - адже майже всі програми мають глобальний стан, будь то в обговоренні як динамічно виділених екземплярів добре інкапсульованих об'єктів або статичних даних, які повністю його піддають Концептуально не має значення, все ще існують залежності - мова йде лише про те, як вони закодовані.
jheriko

1
Саме так. Вони не так сильно "погані", як "легко руйнуються", в основному. Якщо ви знаєте, як їх використовувати, не порушуючи нічого, і коли використовувати їх замість альтернативи, вони можуть бути корисними. Інакше ... не так вже й багато.
Час Джастіна - Поновіть Моніку

4

Глобальні змінні чудові в невеликих програмах, але жахливі, якщо використовувати їх однаково у великих.

Це означає, що ви можете легко звикнути ними користуватися під час навчання. Це те, що ваш професор намагається захистити вас.

Коли ти досвідченіший, то буде легше вчитися, коли їм добре.


4

Ні, вони зовсім не погані. Вам потрібно подивитися на (машинний) код, виданий компілятором, щоб зробити це визначення, іноді набагато гірше використовувати локальний, ніж глобальний. Також зауважте, що нанесення "статичного" на локальну змінну в основному робить її глобальною (і створює інші потворні проблеми, які вирішить справжній глобальний). "місцеві глобали" особливо погані.

Глобали дають вам чіткий контроль над використанням пам’яті, що щось набагато складніше зробити з місцевими жителями. Сьогодні це має значення лише у вбудованих середовищах, де пам'ять досить обмежена. Що потрібно знати, перш ніж припустити, що вбудована така ж, як і в інших середовищах, і припустити, що правила програмування є однаковими для всіх.

Добре, що ви ставите під сумнів правила, які навчають, більшість з них не з тих причин, про які вам кажуть. Хоча найважливіший урок - це не те, що це правило, яке потрібно носити з собою назавжди, але це правило, необхідне для шанування, щоб пройти цей клас і рухатися вперед. У житті ви побачите, що для компанії XYZ у вас будуть інші правила програмування, які вам, зрештою, доведеться дотримуватися, щоб продовжувати отримувати зарплату. В обох ситуаціях можна сперечатися з цим правилом, але я думаю, у вас буде набагато більше удачі на роботі, ніж у школі. Ви просто ще один із багатьох студентів, ваше місце буде замінено незабаром, професори не зможуть, на роботі ви є одним з невеликої команди гравців, які повинні переглянути цей продукт до кінця, і в цьому середовищі правила, розроблені, є для вигода членів команди, а також продукту та компанії, тож, якщо всі мають однодумство або якщо для конкретного продукту є вагомі інженерні причини, щоб порушити щось, що ви дізналися в коледжі чи якусь книгу про загальне програмування, тоді продайте свою ідею команді та запишіть її як дійсний, якщо не кращий метод . Все - це чесна гра в реальному світі.

Якщо ви будете дотримуватися всіх правил програмування, викладених вам у школі чи книгах, ваша кар’єра програмування буде вкрай обмеженою. Ви, ймовірно, можете вижити і мати плідну кар’єру, але широта і ширина доступних вам середовищ будуть вкрай обмеженими. Якщо ви знаєте, як і чому це правило існує, і ви можете його захищати, це добре, якщо ви тільки причина "тому, що мій учитель сказав так", то це не так добре.

Зауважте, що такі теми часто сперечаються на робочому місці і надалі залишатимуться, оскільки компілятори та процесори (і мови) розвиваються так, як такі правила і не захищаючи свою позицію і, можливо, викладаєте урок хтось із іншою думкою, яку ви не хочете рухайся вперед.

Тим часом, тоді просто роби все, що каже той, хто говорить найгучніше чи несе найбільшу палицю (до тих пір, поки ти не той, який кричить найгучніший і несе найбільшу палицю).


4
Це лише інший спосіб сказати, що "ніхто ніколи не звільнявся за покупку IBM"?
Гордон Поттер

1
Хороший момент, що для деяких програм, що використовують глобальні змінні, насправді може полегшити роботу. Взагалі використання глобальних змінних є джерелом проблем із прихованими шляхами зв'язку між розділами джерела. Однак наявність спільної області пам’яті, яка посилається на глобальну, використовується для ряду реалізацій, таких як інтерфейси пристроїв або, можливо, глобальна таблиця параметрів, що містить константи різного виду або таблицю стрибків.
Річард Чемберс

4

Я хотів би заперечувати проти того, що в цій нитці висловлюється думка про те, що це робить багатопотокові складніші або неможливіші самі по собі. Глобальні змінні є загальним станом, але альтернативи глобальним (наприклад, передача покажчиків навколо) також можуть поділяти стан. Проблема з багатопотоковою ниткою полягає в тому, як правильно використовувати спільний стан, а не те, чи стане цей стан спільним через глобальну змінну чи щось інше.

Більшу частину часу, коли ви робите багатопотокові, вам потрібно чим-небудь поділитися. Наприклад, у шаблоні виробник-споживач, ви можете поділити певну чергу, безпечну для потоків, яка містить робочі блоки. І вам дозволяється ділитися ним, оскільки ця структура даних є безпечною для потоків. Незалежно від того, чи така черга є глобальною чи ні, це абсолютно не має значення, коли мова йде про безпеку потоку.

Поточна надія, висловлена ​​у цій нитці, що перетворення програми з однопотокової в багатопотокову буде простішою, коли не використовувати глобальні наївні. Так, глобалісти полегшують себе в ногу, але існує маса способів, як стріляти в себе.

Я не виступаю за глобальні передумови, оскільки інші точки все ще стоять, моя думка полягає лише в тому, що кількість потоків у програмі не має нічого спільного із змінною сферою застосування.


3

Так, тому що якщо ви дозволяєте некомпетентним програмістам їх використовувати (читайте 90%, особливо науковці), ви отримуєте 600+ глобальну змінну, що поширюється на 20+ файлів, і проект із 12 000 рядків, де 80% функцій втрачає чинність, повертає недійсність і працює повністю на глобальному стані.

Швидко стає неможливо зрозуміти, що відбувається в будь-який момент, якщо ви не знаєте весь проект.


2

Використання глобальних змінних фактично залежить від вимог. Його перевага полягає в тому, що він скорочує накладні витрати на передачу значень багаторазово.

Але ваш професор має рацію, оскільки він викликає проблеми безпеки, тому слід максимально уникати використання глобальних змінних. Глобальні змінні також створюють проблеми, які іноді важко налагодити .

Наприклад:-

Ситуації, коли значення змінних змінюються під час виконання . На той момент важко визначити, яка частина коду його модифікує та на яких умовах.


2

Глобальні хороші, коли справа стосується конфігурації . Коли ми хочемо, щоб наша конфігурація / зміни мали глобальний вплив на весь проект .

Таким чином, ми можемо змінити одну конфігурацію, і зміни спрямовані на весь проект . Але мушу застерегти, що вам доведеться бути дуже розумними, щоб користуватися глобалами.


1

Рано чи пізно вам потрібно буде змінити спосіб встановлення цієї змінної або що відбувається під час доступу до неї, або вам просто потрібно знайти місце, де вона змінена.

Практично завжди краще не мати глобальних змінних. Просто напишіть способи отримання греблі та встановіть методи, і будьте вам, коли вам знадобляться через день, тиждень чи місяць.


1

Зазвичай я використовую глобалі для значень, які рідко змінюються, як одиночні кнопки або покажчики функцій, на функції в динамічно завантаженій бібліотеці. Використання змінних глобальних мереж у багатопотокових програмах, як правило, призводить до важкої відслідковування помилок, тому я намагаюся уникати цього як загальне правило.

Використання глобального замість передачі аргументу часто швидше, але якщо ви пишете багатопотокове додаток, яке часто робите в наші дні, воно, як правило, не дуже добре (ви можете використовувати нитки-статики, але тоді підвищення продуктивності сумнівний) .


1

У веб-додатках в рамках підприємства можуть використовуватися для проведення сеансу / вікна / потоку / конкретних даних користувача на сервері з міркувань оптимізації та для захисту від втрати роботи, коли з'єднання нестабільне. Як уже згадувалося, гоночні умови потребують поводження. Ми використовуємо один екземпляр класу для цієї інформації, і вона ретельно управляється.


1

Зрештою, програма чи додаток все ще можуть працювати, але справа в тому, щоб бути охайним та мати повне розуміння того, що відбувається. Якщо ви поділите значення змінної між усіма функціями, може бути важко відстежити, яка функція змінює значення (якщо функція робить це) і робить налагодження в мільйон разів складніше


0

безпека менше означає, що будь-хто може маніпулювати змінними, якщо вони оголошені глобальними, для цього можна пояснити, наприклад, якщо у вашій банківській програмі баланс як глобальна змінна, функція користувача може це маніпулювати, а також банківський співробітник також може маніпулювати. у цьому виникає проблема. Тільки користувачеві слід надати лише функцію читання та зняття, але діловод банку може додати суму, коли користувач особисто видає готівку на стіл. Це так, як це працює


-1

У багатопотоковому додатку використовуйте локальні змінні замість глобальних змінних, щоб уникнути перегонів.

Умова перегонів виникає, коли декілька потоків отримують доступ до спільного ресурсу, при цьому щонайменше один потік має доступ для запису до даних. Тоді результат програми не передбачуваний і залежить від порядку доступу до даних різними потоками.

Більше про це тут, https://software.intel.com/en-us/articles/use-intel-parallel-inspector-to-find-race-conditions-in-openmp-based-multithreaded-code


Для нащадків: це частково в кращому випадку правильно. У «локальні змінні» в цій відповіді посилатися на нитку -локальні змінні, а не більш загальних областей застосування локальної змінних , що OP має в увазі. Побічні ефекти модифікації глобальних змінних в небезпечний для потоку спосіб дуже відрізняються від ефектів зміни глобального стану без одночасного.
Жуль
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.