Я только что натолкнулся на этот старый вопрос, спрашивающий, что же такого плохого в глобальном состоянии, и принятый верхний ответ утверждает, что вы не можете доверять ни одному коду, который работает с глобальными переменными, потому что какой-то другой код где-то еще может прийти и изменить значение, а затем вы не знаете, каким будет поведение вашего кода, потому что данные разные! Но когда я смотрю на это, я не могу не думать, что это действительно слабое объяснение, потому что чем это отличается от работы с данными, хранящимися в базе данных?
Когда ваша программа работает с данными из базы данных, вам все равно, изменяет ли ее другой код в вашей системе, или даже если в этом отношении ее изменяет совершенно другая программа. Вам все равно, что это за данные; вот и весь смысл. Все, что имеет значение, это то, что ваш код правильно обрабатывает данные, с которыми он сталкивается. (Очевидно, что я закрываю часто острую проблему кеширования здесь, но давайте пока проигнорируем это.)
Но если данные, с которыми вы работаете, поступают из внешнего источника, который не контролируется вашим кодом, например, из базы данных (или пользовательского ввода, или сетевого сокета, или файла и т. Д.), И в этом нет ничего плохого с этим, тогда как глобальные данные в самом коде - над которым ваша программа имеет гораздо большую степень контроля - каким-то образом плохая вещь, когда она, очевидно, намного менее плоха, чем совершенно нормальные вещи, которые никто не считает проблемой?
Ответы:
Во-первых, я бы сказал, что ответ, на который вы ссылаетесь, преувеличивает эту конкретную проблему, и что основное зло глобального состояния заключается в том, что оно вводит непредсказуемое взаимодействие, которое может затруднить изменение поведения вашей системы в будущем.
Но углубившись в эту проблему, есть различия между глобальным состоянием в типичном объектно-ориентированном приложении и состоянием, которое хранится в базе данных. Вкратце, наиболее важными из них являются:
Объектно-ориентированные системы позволяют заменять объект другим классом объекта, если он является подтипом исходного типа. Это позволяет изменять поведение , а не только данные .
Глобальное состояние в приложении, как правило, не обеспечивает строгой согласованности, гарантирующей выполнение базы данных - нет транзакций, во время которых вы видите для нее согласованное состояние, нет атомарных обновлений и т. Д.
Кроме того, мы можем видеть состояние базы данных как необходимое зло; невозможно исключить это из наших систем. Глобальное состояние, однако, не нужно. Мы можем полностью устранить это. Таким образом, даже если проблемы с базой данных столь же плохи, мы все равно можем устранить некоторые потенциальные проблемы, и частичное решение лучше, чем отсутствие решения.
источник
Во-первых, каковы проблемы с глобальными переменными, основанные на принятом ответе на вопрос, который вы связали?
Базы данных в большинстве случаев совместимы с ACID. ACID специально решает основные проблемы, которые делают хранилище данных непредсказуемым или ненадежным.
Это связано с тем, что глобальные переменные существуют в области, далекой от их использования, возможно, даже в другом файле. При использовании базы данных вы используете набор записей или объект ORM, который является локальным по отношению к коду, который вы читаете (или должен быть).
Драйверы базы данных обычно предоставляют согласованный, понятный интерфейс для доступа к данным, одинаковым независимо от проблемной области. Когда вы получаете данные из базы данных, ваша программа имеет копию данных. Обновления атомарны. В отличие от глобальных переменных, где несколько потоков или методов могут работать с одним и тем же фрагментом данных без атомарности, если вы не добавите синхронизацию самостоятельно. Обновления данных непредсказуемы и их сложно отследить. Обновления могут чередоваться, приводя к стандартным болотным примерам примеров многопоточного повреждения данных (например, чередующиеся приращения).
Как правило, базы данных моделируют данные, отличные от глобальных переменных, но на мгновение оставим это в стороне, базы данных с самого начала разрабатываются как совместимое с ACID хранилище данных, которое устраняет многие проблемы, связанные с глобальными переменными.
источник
Я бы предложил несколько наблюдений:
Да, база данных - это глобальное состояние.
На самом деле, это суперглобальное состояние, как вы указали. Это универсально! Сфера его применение влечет за собой ничего или кого - либо , который подключается к базе данных. И я подозреваю, что многие люди с многолетним опытом могут рассказать вам ужасные истории о том, как «странные вещи» в данных привели к «неожиданному поведению» в одном или нескольких соответствующих приложениях ...
Одним из потенциальных последствий использования глобальной переменной является то, что два разных «модуля» будут использовать эту переменную для своих собственных разных целей. И в этом смысле таблица базы данных ничем не отличается. Это может стать жертвой той же проблемы.
Хм ... вот в чем дело:
Если модуль каким-то образом не работает внешне, он ничего не делает.
Полезному модулю могут быть даны данные или он может их найти . И он может возвращать данные или может изменять состояние. Но если он не взаимодействует с внешним миром каким-либо образом, он может ничего не делать.
Теперь мы предпочитаем получать данные и возвращать данные. Большинство модулей проще написать, если их можно писать с полным пренебрежением к тому, что делает внешний мир. Но, в конечном счете, что-то должно найти данные и изменить это внешнее, глобальное состояние.
Кроме того, в реальных приложениях данные существуют для того, чтобы их можно было читать и обновлять различными операциями. Некоторые проблемы предотвращаются блокировками и транзакциями. Но предотвращение конфликта этих операций в принципе , в конце концов, просто требует тщательного обдумывания. (И ошибаться ...)
Но мы также не работаем напрямую с глобальным государством.
Если приложение не находится на уровне данных (в SQL или чем-то еще), объекты, с которыми работают наши модули, на самом деле являются копиями общего глобального состояния. Мы можем делать все, что захотим, без какого-либо влияния на фактическое общее состояние.
И в тех случаях, когда нам нужно изменить это глобальное состояние, исходя из предположения, что данные, которые мы получили, не изменились, мы обычно можем выполнить такую же блокировку, что и наши локальные глобальные переменные.
И , наконец, мы обычно делаем разные вещи с базами данных , чем мы могли бы с нехорошими глобал.
Непослушный, разбитый глобал выглядит так:
Мы просто не используем базы данных для подобных процессов. И это может быть медленным характером базы данных и относительным удобством простой переменной, которая нас пугает: наше вялое, неуклюжее взаимодействие с базами данных просто делает их плохими кандидатами на многие из ошибок, которые мы исторически совершали с переменными.
источник
Я не согласен с фундаментальным утверждением, что:
Моей первоначальной мыслью было "Вау. Просто вау". Так много времени и усилий уходит на то, чтобы избежать именно этого - и выяснить, какие компромиссы и компромиссы работают для каждого приложения. Просто игнорировать это - рецепт катастрофы.
Но я также диаспра на архитектурном уровне. Глобальная переменная - это не просто глобальное состояние. Это глобальное состояние, которое доступно из любой точки мира прозрачно. В отличие от использования базы данных, вы должны иметь дескриптор к ней - (если вы не храните, чем обрабатываете в глобальной переменной ....)
Например, использование глобальной переменной может выглядеть так
Но делать то же самое с базой данных нужно было бы более четко о том, что она делает
База данных, очевидно, смешивается с базой данных. Если вы хотите не использовать базу данных, вы можете использовать явное состояние, и оно выглядит почти так же, как и в случае с базой данных.
Поэтому я бы сказал, что использование базы данных гораздо больше похоже на использование явного состояния, чем на использование глобальных переменных.
источник
MakeNewThing
зависит от того , использует лиMakeNewThingInDb
мой класс контроллераMakeNewThing
, то из кода в моем контроллере не ясно, что я изменяю базу данных. И что тогда, если я использую другой класс, который фактически передает мою текущую транзакцию в БД? DI делает очень трудным контролировать область объекта.То, что единственная причина, по которой глобальным переменным нельзя доверять, поскольку состояние может быть изменено где-то еще, само по себе не является достаточной причиной, чтобы не использовать их, согласился (хотя это довольно веская причина!). Вероятно, ответ в основном описывал использование, где ограничение доступа переменной только к тем областям кода, к которым она имеет отношение, имело бы больше смысла.
Однако базы данных - это другое дело, потому что они предназначены для того, чтобы к ним обращались, так сказать, «глобально».
Например:
Самое главное, что базы данных служат не для глобальной цели, а для другой цели. Базы данных предназначены для хранения и поиска больших объемов организованных данных, где глобальные переменные служат определенным нишам (когда это оправдано).
источник
Или отличается от работы с интерактивным устройством, с файлом, с общей памятью и т. Д. Программа, которая делает то же самое при каждом запуске, является очень скучной и довольно бесполезной программой. Так что да, это слабый аргумент.
Для меня различие, которое имеет значение в отношении глобальных переменных, состоит в том, что они образуют скрытые и незащищенные линии связи. Чтение с клавиатуры очень очевидно и защищено. Я должен сделать определенный вызов функции, и я не могу получить доступ к драйверу клавиатуры. То же самое относится к доступу к файлам, общей памяти и вашему примеру, базам данных. Для читателя кода очевидно, что эта функция читает с клавиатуры, что эта функция обращается к файлу, какая-то другая функция обращается к разделяемой памяти (и вокруг этого должна быть защита), а какая-то другая функция обращается к базе данных.
С глобальными переменными, с другой стороны, это совсем не очевидно. API говорит, чтобы позвонить
foo(this_argument, that_argument)
. В последовательности вызова нет ничего, что говорило бы, что глобальная переменнаяg_DangerWillRobinson
должна быть установлена в какое-то значение, но перед вызовомfoo
(или проверено после вызоваfoo
).Google запретил использование неконстантных ссылочных аргументов в C ++ прежде всего потому, что читателю кода не очевидно, что
foo(x)
он изменится,x
потому что онfoo
принимает непостоянную ссылку в качестве аргумента. (Сравните с C #, который требует, чтобы и определение функции, и сайт вызова должны квалифицировать ссылочный параметр сref
ключевым словом.) Хотя я не согласен со стандартом Google по этому вопросу, я понимаю их точку зрения.Код пишется один раз и изменяется несколько раз, но если он вообще хорош, его читают много-много раз. Скрытые линии связи - очень плохая карма. Неконстантная ссылка C ++ представляет собой небольшую скрытую линию связи. Хороший API или хорошая IDE покажет мне: «О! Это вызов по ссылке». Глобальные переменные - это огромная скрытая линия связи.
источник
Я думаю, что приведенное объяснение упрощает проблему до такой степени, что рассуждения становятся нелепыми. Конечно, состояние внешней базы данных способствует глобальному состоянию. Важный вопрос, какВаша программа зависит от (изменяемого) глобального состояния. Если библиотечная функция для разделения строк на пустое пространство будет зависеть от промежуточных результатов, хранящихся в базе данных, я бы возражал против этого проекта по крайней мере так же, как и против глобального массива символов, используемого для той же цели. С другой стороны, если вы решите, что вашему приложению не требуется полноценная СУБД для хранения бизнес-данных на данном этапе, и глобальная структура ключ-значение в памяти подойдет, это не обязательно является признаком плохого дизайна. Важно то, что - независимо от того, какое решение вы выберете для хранения своих данных - этот выбор изолирован для очень небольшой части системы, поэтому большинство компонентов могут не зависеть от решения, выбранного для развертывания, и подвергаться модульному тестированию в отдельности и в развертывании. решение может быть изменено позже без особых усилий.
источник
Как инженер-программист, работающий преимущественно со встроенными прошивками, я почти всегда использую глобальные переменные для всего, что происходит между модулями. На самом деле, это лучшая практика для встраивания. Они назначаются статически, поэтому нет риска уничтожения кучи / стека и не требуется дополнительного времени для распределения / очистки стека при входе / выходе функции.
Недостатком этого является то, что мы действительно должны рассмотреть , как используются эти переменные, и много , что сводится к тому же виду , что мысль идет в БД-пререканий. Любое асинхронное чтение / запись переменных ДОЛЖНО быть атомарным. Если переменная может быть записана более чем в одном месте, необходимо подумать о том, чтобы они всегда записывали действительные данные, чтобы предыдущая запись не была произвольно заменена (или что произвольная замена - безопасная вещь). Если одна и та же переменная читается более одного раза, необходимо подумать над тем, что произойдет, если переменная изменяет значение между чтениями, или копия переменной должна быть взята в начале, чтобы обработка выполнялась с использованием согласованного значения, даже если это значение становится устаревшим во время обработки.
(Что касается последнего, в мой самый первый день контракта, работавшего над системой контрмер самолета, настолько связанной с безопасностью, команда разработчиков смотрела на сообщение об ошибке, которое они пытались выяснить в течение недели или около того. У меня было достаточно времени, чтобы загрузить инструменты разработки и копию кода. Я спросил: «Не может ли эта переменная быть обновлена между чтениями и вызвать ее?», Но на самом деле не получил ответа. Эй, что делает В конце концов, новый парень знает? Итак, пока они еще обсуждали это, я добавил защитный код, чтобы атомарно прочитать переменную, сделал локальную сборку и в основном сказал: «Эй, ребята, попробуйте это». Способ доказать, что я стою своего контракта :)
Таким образом, глобальные переменные не являются однозначно плохой вещью, но они оставляют вас открытыми для широкого круга проблем, если вы не думаете о них тщательно.
источник
В зависимости от того, какой аспект вы оцениваете, глобальные переменные и доступ к базе данных могут быть разными, но пока мы оцениваем их как зависимости, они одинаковы.
Давайте рассмотрим в функциональном программировании определение чистой функции, которая гласит, что она должна зависеть исключительно от параметров, которые она принимает в качестве входных данных, создавая детерминированный результат. То есть, учитывая один и тот же набор аргументов дважды, он должен давать одинаковый результат.
Когда функция зависит от глобальной переменной, ее уже нельзя считать чистой, поскольку для одного и того же набора или аргументов она может давать разные выходные данные, поскольку значение глобальной переменной могло изменяться между вызовами.
Однако функцию все еще можно рассматривать как детерминированную, если мы рассматриваем глобальную переменную как часть интерфейса функции, так же как и другие ее аргументы, так что это не проблема. Проблема только в том, что это скрыто до тех пор, пока мы не удивимся неожиданному поведению кажущихся очевидными функций, а затем перейдем к чтению их реализаций, чтобы обнаружить скрытые зависимости .
Эта часть, момент, когда глобальная переменная становится скрытой зависимостью, является тем, что мы, программисты, считаем злом. Это делает код труднее рассуждать, трудно предсказать, как он будет себя вести, трудно повторно использовать, сложно тестировать и, особенно, увеличивает время отладки и исправления при возникновении проблемы.
То же самое происходит, когда мы скрываем зависимость от базы данных. У нас могут быть функции или объекты, выполняющие прямые вызовы к запросам и командам базы данных, скрывающие эти зависимости и вызывающие у нас те же проблемы, что и глобальные переменные; или мы можем сделать их явными, что, как оказывается, считается лучшей практикой, которая идет под многими именами, такими как шаблон репозитория, хранилище данных, шлюз и т. д.
PS: Есть и другие аспекты, которые важны для этого сравнения, например, задействован ли параллелизм, но этот момент освещается здесь другими ответами.
источник
Хорошо, начнем с исторической точки.
Мы находимся в старом приложении, написанном на вашем типичном соединении ассемблера и C. Там нет функций, только процедуры . Когда вы хотите передать аргумент или возвращаемое значение из процедуры, вы используете глобальную переменную. Излишне говорить, что это довольно сложно отследить, и в целом каждая процедура может делать с любой глобальной переменной все, что захочет. Неудивительно, что люди обратились к передаче аргументов и возвращению значений по-другому, как только это стало возможным (если только это не было критично для производительности - например, посмотрите на исходный код Build Engine (Duke 3D)). Здесь родилась ненависть к глобальным переменным - вы очень мало представляли, какую часть глобального состояния каждая процедура будет читать и изменять, и вы не могли действительно безопасно вкладывать вызовы процедур.
Означает ли это, что глобальная переменная ненависть ушла в прошлое? Не совсем.
Во-первых, я должен отметить, что я видел точно такой же подход к передаче аргументов в проекте, над которым я сейчас работаю. Для передачи двух экземпляров ссылочного типа в C # в проекте, которому около 10 лет. Буквально нет веской причины делать это так, и, скорее всего, он был рожден либо из-за груза, либо из-за полного недопонимания того, как работает C #.
Еще важнее то, что, добавляя глобальные переменные, вы расширяете область действия каждого отдельного фрагмента кода, который имеет доступ к этой глобальной переменной. Помните все эти рекомендации, как «держать ваши методы короткими»? Если у вас есть 600 глобальных переменных (опять же, пример из реального мира: /), все области ваших методов неявно расширяются этими 600 глобальными переменными, и нет простого способа отследить, кто к чему имеет доступ.
Если все сделано неправильно (обычным способом :)), глобальные переменные могут иметь связь между собой. Но вы понятия не имеете, как они связаны, и нет механизма, который бы гарантировал постоянство глобального состояния. Даже если вы введете критические разделы, чтобы попытаться сохранить последовательность, вы обнаружите, что она плохо сравнивается с правильной базой данных ACID:
Возможно ли решить эти проблемы? На самом деле, нет. Вам нужна инкапсуляция, чтобы справиться с этим, или действительно строгая дисциплина. Трудно сделать все правильно, и это, как правило, не очень хороший рецепт для успеха в разработке программного обеспечения :)
Меньшая область действия делает код легче рассуждать. Глобальные переменные позволяют даже самым простым фрагментам кода включать огромные области видимости.
Конечно, это не значит, что глобальная сфера действия - это зло. Это просто не должно быть первое решение, к которому вы стремитесь - это типичный пример «простой в реализации, сложный в обслуживании».
источник
Глобальная переменная - это инструмент, его можно использовать для добра и зла.
База данных - это инструмент, его можно использовать во благо и во зло.
Как отмечает оригинальный автор, разница не так уж велика.
Неопытные студенты часто думают, что ошибки - это то, что случается с другими людьми. Учителя используют «Глобальные переменные - зло» как упрощенную причину наказания за плохой дизайн. Студенты, как правило, не понимают, что их программа из 100 строк не содержит ошибок, но это не означает, что те же методы можно использовать для программ из 10000 строк.
Когда вы работаете с базами данных, вы не можете просто запретить глобальное состояние, поскольку именно в этом и заключается программа. Вместо этого вы получите более подробные рекомендации, такие как ACID и Normal Forms и так далее.
Если бы люди использовали подход ACID к глобальным переменным, они не были бы такими плохими.
С другой стороны, если вы плохо проектируете базы данных, это может стать кошмаром.
источник
Для меня главное зло в том, что у глобалов нет защиты от проблем параллелизма. Вы можете добавить механизмы для решения таких проблем с Globals, но вы обнаружите, что чем больше проблем с параллелизмом вы решаете, тем больше ваши Globals начинают имитировать базу данных. Вторичное зло - это не контракт на использование.
источник
errno
в C.Некоторые другие ответы пытаются объяснить, почему использование базы данных хорошо. Они не правы! База данных является глобальным состоянием и, как таковая, является таким же злом, как синглтон или глобальная переменная. Использование базы данных очень неправильно, если вместо этого вы можете просто использовать локальную карту или массив!
Глобальные переменные допускают глобальный доступ, что сопряжено с риском злоупотребления. Глобальные переменные также имеют свои плюсы. Обычно говорят, что глобальные переменные - это то, чего вам следует избегать, а не то , что вы никогда не должны использовать. Если вы можете легко избежать их, вы должны избегать их. Но если преимущества перевешивают недостатки, конечно, вы должны их использовать! *
Точно то же самое ** относится к базам данных, которые имеют глобальное состояние - так же, как глобальные переменные. Если вы можете обойтись без доступа к базе данных, а полученная логика делает все, что вам нужно, и в равной степени сложна, использование базы данных увеличивает риск для вашего проекта без какой-либо соответствующей выгоды.
В реальной жизни многим приложениям требуется глобальное состояние, иногда даже постоянное глобальное состояние, поэтому у нас есть файлы, базы данных и т. Д.
* Исключение составляют студенты. Имеет смысл запретить учащимся использовать глобальные переменные, чтобы они могли узнать, какие есть альтернативы.
** Некоторые ответы неверно утверждают, что базы данных как-то лучше защищены, чем другие формы глобального состояния (вопрос явно о глобальном состоянии , а не только о глобальных переменных). Это чепуха. Основная защита, предлагаемая в сценарии базы данных, по соглашению, которая точно такая же для любого другого глобального состояния. Большинство языков также предоставляют много дополнительной защиты для глобального состояния в форме
const
классов, которые просто не позволяют изменять свое состояние после того, как оно было установлено в конструкторе, или методов получения и установки, которые могут принимать во внимание информацию о потоке или состояние программы.источник
В некотором смысле, различие между глобальными переменными и базой данных похоже на различие между частными и открытыми членами объекта (при условии, что кто-то все еще использует открытые поля). Если вы рассматриваете всю программу как объект, то глобальные переменные являются частными переменными, а база данных - открытыми полями.
Ключевым отличием здесь является взятие на себя ответственности.
Когда вы пишете объект, предполагается, что любой, кто поддерживает методы-члены, будет следить за тем, чтобы приватные поля оставались в хорошем состоянии. Но вы уже отказываетесь от каких-либо предположений о состоянии публичных полей и относитесь к ним с особой тщательностью.
То же самое предположение применяется на более широком уровне к базе данных globals v / s. Кроме того, язык / экосистема программирования гарантирует ограничения доступа к частным v / s public так же, как он применяет их к (не разделяемой памяти) глобальным базам данных v / s.
Когда многопоточность вступает в игру, концепция частной v / s публичной v / s глобальной v / s базы данных - это просто различия по спектру.
источник
База данных может быть глобальным состоянием, но это не обязательно должно быть постоянно. Я не согласен с предположением, что у вас нет контроля. Одним из способов управления этим является блокировка и безопасность. Это может быть сделано в записи, таблице или всей базе данных. Другой подход заключается в том, чтобы иметь какое-то поле версии, которое предотвратит изменение записи, если данные устарели.
Как и глобальная переменная, значения в базе данных могут быть изменены после их разблокировки, но есть много способов контроля доступа (Не давайте всем разработчикам пароль для учетной записи, которой разрешено изменять данные.). Если у вас есть переменная с ограниченным доступом, она не очень глобальная.
источник
Есть несколько отличий:
Значение базы данных может быть изменено на лету. С другой стороны, значение глобальной переменной, заданной в коде, не может быть изменено, если вы повторно не развернете свое приложение и не измените свой код. На самом деле это намеренно. База данных предназначена для значений, которые могут изменяться с течением времени, но глобальные переменные должны использоваться только для вещей, которые никогда не изменятся, и когда они не содержат фактических данных.
Значение базы данных (строка, столбец) имеет контекст и реляционное отображение в базе данных. Это отношение можно легко извлечь и проанализировать с помощью таких инструментов, как Jailer (например). Глобальная переменная, с другой стороны, немного отличается. Вы можете найти все способы использования, но вы не сможете рассказать мне обо всех способах взаимодействия переменной с остальным миром.
Глобальные переменные быстрее . Чтобы получить что-то из базы данных, необходимо установить соединение с базой данных, выполнить команду select, а затем соединение с базой данных должно быть закрыто. Любые преобразования типов, которые вам могут понадобиться, идут поверх этого. Сравните это с глобальным доступом в вашем коде.
Это единственное, о чем я могу думать прямо сейчас, но я уверен, что есть и другие. Проще говоря, это две разные вещи и должны использоваться для разных целей .
источник
Конечно, глобальные не всегда неуместны. Они существуют, потому что имеют законное использование. Основная проблема с глобальными переменными и основным источником предупреждения о том, что их следует избегать, заключается в том, что код, использующий глобальные переменные, привязан к этому единственному глобальному.
Например, рассмотрим HTTP-сервер, хранящий имя сервера.
Если вы храните имя сервера в глобальном, то процесс не может одновременно запустить логику для двух разных имен серверов. Возможно, оригинальный дизайн никогда не предусматривал запуск более одного экземпляра сервера одновременно, но если вы позже решите, что хотите это сделать, вы просто не сможете, если имя сервера находится в глобальном.
Напротив, если имя сервера находится в базе данных, проблем нет. Вы можете просто создать один экземпляр этой базы данных для каждого экземпляра HTTP-сервера. Поскольку каждый экземпляр сервера имеет свой собственный экземпляр базы данных, он может иметь свое собственное имя сервера.
Таким образом, основное возражение против глобальных переменных может быть только одно значение для всего кода, который обращается к этому глобальному, не относится к записям базы данных. Один и тот же код может легко получить доступ к отдельным экземплярам базы данных, которые имеют разные значения для конкретной записи.
источник
Я думаю, что это интересный вопрос, но на него немного сложно ответить, потому что есть два основных вопроса, которые соотносятся с термином «глобальное состояние». Первое - это понятие «глобальная связь». Доказательством этого является то, что альтернатива для глобального состояния - это внедрение зависимостей. Дело в том, что DI не обязательно устраняет глобальное состояние. То есть абсолютно возможно и обычно вводить зависимости от глобального состояния. Что делает DI, так это удаляет связь, которая идет с глобальными переменными и обычно используемым шаблоном Singleton. Помимо немного менее очевидного дизайна, есть очень мало недостатков в устранении этого вида связи, и выгоды от устранения связи возрастают экспоненциально с числом зависимостей от этих глобальных переменных.
Другим аспектом этого является общее состояние. Я не уверен, существует ли действительно четкое различие между глобально разделяемым состоянием и общим состоянием в целом, но затраты и выгоды гораздо более нюансированы. Проще говоря, существуют бесчисленные программные системы, которые требуют общего состояния, чтобы быть полезным. Биткойн, например, является очень умным способом децентрализованного разделения государства на глобальном уровне (в буквальном смысле). Правильно разделить изменяемое состояние без создания огромных узких мест сложно, но полезно. Поэтому, если вам действительно не нужно это делать, вы можете упростить свое приложение, минимизировав общее изменяемое состояние.
Таким образом, вопрос о том, чем базы данных отличаются от глобальных, также раздваивается между этими двумя аспектами. Они вводят связь? Да, они могут, но это во многом зависит от того, как разрабатывается приложение и как создается база данных. Существует слишком много факторов, чтобы однозначно ответить на вопрос, вводят ли базы данных глобальную связь без подробных сведений о структуре. Что касается того, вводят ли они совместное использование состояния, ну, это своего рода основной пункт базы данных. Вопрос в том, хорошо ли они это делают. Опять же, я думаю, что это слишком сложно, чтобы ответить без большого количества другой информации, такой как альтернативы и многие другие компромиссы.
источник
Я бы подумал об этом немного по-другому: поведение, подобное «глобальной переменной», - это цена, которую платят администраторы баз данных (DBA), потому что это необходимое зло для выполнения их работы.
Проблема с глобальными переменными, как указали несколько других, не является произвольной. Проблема в том, что их использование делает поведение вашей программы все менее и менее предсказуемым, поскольку становится все труднее определить, кто использует переменную и каким образом. Это большая проблема для современного программного обеспечения, потому что от современного программного обеспечения обычно требуется много гибких вещей. Это может сделать миллиарды или даже триллионы сложных государственных манипуляций в ходе бега. Возможность доказать истинные утверждения о том, что будет делать это программное обеспечение в этих миллиардах или триллионах операций, чрезвычайно важна.
В случае современного программного обеспечения все наши языки предоставляют инструменты для помощи в этом, такие как инкапсуляция. Выбор не использовать его не нужен, что приводит к менталитету «глобалы - зло». Во многих регионах в области разработки программного обеспечения единственными, кто их использует, являются люди, которые не знают, как лучше кодировать. Это означает, что они не только напрямую создают проблемы, но и косвенно предполагают, что разработчик не знал, что делал. В других регионах вы обнаружите, что глобальные переменные абсолютно нормальны (в частности, встроенное программное обеспечение любит глобальные переменные, частично потому, что они хорошо работают с ISR). Тем не менее, среди многих разработчиков программного обеспечения они являются голосом меньшинства, поэтому единственный голос, который вы слышите, - «глобальные злые».
Разработка баз данных - одна из тех голосовых ситуаций меньшинства. Инструменты, необходимые для работы DBA, очень мощные, и их теория не основана на инкапсуляции. Чтобы извлекать из своих баз данных каждый скачок производительности, им нужен полный беспрепятственный доступ ко всему, подобно глобальным. Используйте одну из их огромных 100 миллионов строк (или больше!) Баз данных, и вы поймете, почему они не позволяют своему движку БД выдерживать любые удары.
Они платят за это дорогую цену. Администраторы баз данных вынуждены быть почти патологичными с их вниманием к деталям, потому что их инструменты не защищают их. Лучшее, что у них есть в способе защиты - это ACID или, возможно, внешние ключи. Те, кто не патологичен, оказываются в полном беспорядке таблиц, которые совершенно непригодны или даже повреждены.
Это не редкость, когда у вас есть 100 000 линейных программных пакетов. Теоретически, любая строка в программном обеспечении может влиять на любой глобал в любой момент времени. В администраторах баз данных вы никогда не найдете 100 000 различных запросов, которые могут изменить базу данных. Это было бы неразумно поддерживать с вниманием к деталям, необходимым для защиты вас от себя. Если у администратора базы данных есть что-то подобное, он намеренно инкапсулирует свою базу данных, используя средства доступа, обходя проблемы «глобального подобия», и затем выполняет столько работы, сколько возможно, с помощью этого «более безопасного» механизма. Таким образом, когда дело доходит до толчка, даже пользователи базы данных избегают глобальных изменений. Они просто приходят с большой опасностью, и есть альтернативы, которые такие же сильные, но не такие опасные.
Вы бы предпочли прогуляться по битому стеклу или по красиво подметенным тротуарам, если все остальные вещи равны? Да, вы можете ходить по битому стеклу. Да, некоторые люди даже зарабатывают на жизнь этим. Но все же, просто позвольте им подметать тротуар и двигаться дальше!
источник
Я думаю, что предпосылка ложна. Нет причин, по которым база данных должна быть «глобальным состоянием», а не (очень большим) контекстным объектом. Если вы привязываетесь к конкретной базе данных, которую ваш код использует через глобальные переменные или фиксированные глобальные параметры подключения к базе данных, это ничем не отличается и не менее вредно, чем любое другое глобальное состояние. С другой стороны, если вы правильно передаете объект контекста для соединения с базой данных, это просто большое (и широко используемое) контекстное состояние, а не глобальное состояние.
Измерение разницы легко: вы могли бы запустить два экземпляра логики вашей программы, каждый из которых использует свою собственную базу данных, в одной программе / процессе без внесения инвазивных изменений в код? Если это так, ваша база данных не является «глобальным состоянием».
источник
Глобалы не являются злом; они просто инструмент. НЕДОСТАТОЧНО глобальных проблем, как и злоупотребление любой другой функцией программирования.
Моя общая рекомендация заключается в том, что глобальные переменные должны использоваться только в ситуациях, которые хорошо поняты и продуманы, где другие решения менее оптимальны. Самое главное, вы хотите убедиться, что вы хорошо документировали, где это глобальное значение может быть изменено, и, если вы работаете в многопоточном режиме, вы гарантируете, что глобальные и любые совместно зависимые глобальные переменные имеют доступ транзакционным способом.
источник
Шаблон только для чтения, и предположите, что ваши данные не обновлены при печати. Очередь пишет или обрабатывает конфликты другим способом. Добро пожаловать в ад, дьявол, вы используете глобальный дБ.
источник