![]() |
глобальные переменные зло?
Вопрос теоретический, есть программа претендующая на некоторую универсальность. Имхо, удобно создать класс исключительно для хранения настроек - статических переменных, констант и функций. Они доступны везде и всегда. Но, я слышал мнение, что это зло и все чайники через это проходят.
Почему это плохо? Какова альтернатива? Использовать xml для хранения настроек, имхо, неудобно, его могут изменить/удалить, нужно время чтобы его загрузить. |
Если бы это было зло, никто бы не делал такой возможности. Важно решить какие переменные (или константы), стоит хранить глобально, а какие нет.
А хранить глобально можно многое, и зачастую это лучший вариант. |
Цитата:
Вы делаете глобальный класс, кладете туда кучу публичных переменных, которые произвольно меняете в произвольных местах кода. В какой-то момент получаете хороший головняк от того, что приложение работает нештатно из-за того, что эти глобальные переменные имеют неправильное значение, но кто именно их изменил, совершенно непонятно. Соответственно, глобально хранить имеет смысл константы и переменные, которые выставляются один раз при загрузке приложения, а затем исключительно считываются. А, вообще-то, эта тема - злостный баян. Надо в поиск сходить. |
Это такой способ мышления, вариант "организации" порядка.. Типа на вопрос "а где у нас..." ответ готов заранее - в шкафу.
Я лично этой логики никогда не мог понять - почему, с какой стати настройки для, например, кнопки, должны храниться в общественном месте и быть доступны всем - текстовым полям, битмапам и прочим левым сущностям? В самой идее "доступно всем и отовсюду" содержится дьявольское зерно Хаоса и полная бессмыслица. Дело не в том, что кто-то злобно поменяет чего-нибудь в чужих настройках. Дело в том, что контроля просто НЕТ. А это значит, что никакой гарантии отсутствия ошибок нет. Это значит, что программист оставил зияющую дыру в структуре ради того, чтобы не напрячь случайно свой мозг обеспечением иерархии и контроля – тем, что и делает из кучи строчек кода Программу. Я не знаю ни одного случая, когда "зачастую это лучший вариант". |
Wolsh, мысли шире. Допустим есть игра на бокс2д (чисто для примера), в ней тебе постоянно надо переводить пиксели в метры, радианы в градусы и наоборот. Не лучший ли вариант хранить формулы для перевода этих величин в глобальных константах? Вот тебе и один случай
|
filepark
Среди программистов тоже встречаются суеверные, вот они и боятся использовать глобальные переменные :D Я считаю так - если тебе удобно использовать глобальные переменные - используй, чего огород городить? Не удобно, или дядька начальник запрещает - не используй. А если говорить о традициях, то таки да - глобальные переменные - зло!!! |
Цитата:
- например появится 2-я часть системы, которую надо настроить по другому - а конфиг один (не важно xml или статический класс) - замучаетесь менять эти глобальные переменные до теста и после автоматического теста возвращать "как было", хотя, вроде делают так и не жужжат. - если речь идет не просто о постоянных данных конфигурации, а о некоторых параметрах состояния хранящихся глобально - то тут еще возникает путаница "... да ёлы палы, какая сволочь эту переменную меняет, я же выставляю false, а здесь она опять true" Как бороться? - протаскивать параметры - протаскивать объекты с параметрами - протаскивать фабрики, которые правильно параметризуют создаваемые ими объекты - протаскивать фабрики фабрик - использовать IoC-контейнеры - ... но на самом деле, будет только хуже. |
Цитата:
На мой взгляд, тут как всегда, главная часть любого инструмента - голова его владельца. |
goodguy, в моем тексте нет ни слова о константах. Как и в названии темы.
expl, то, что Вы называете "протаскивать", обрисовывает ситуацию, когда архитектура заточена под глобальные переменные, и вдруг Вы решили эти глобальные переменные отменить. А проект уже написан, и Вы начинаете "протаскивать", не спорю. Но когда архитекрура строится изначально иерархически, вложенными модулями, этот процесс естественен и называется настройкой при инициализации. Когда каждому более глубоковложенному модулю передаются все те параметры, которые ему необходимы, чтобы настроить себя и свои составляющие, точно так же при вызове метода (передаче команды этому модулю) ему отдаются необходимые параметры. Это аналог положения метода в классе - Вы можете хранить всё и вся в приватных полях класса, доступных всем методам, и вызывать методы с пустым приемником: foo(); а можете хранить только то, что действительно нужно (например для хендлеров и геттеров/сеттеров), а методы вызывать, передавая им локальные данные: foo(w, h, index); Оба варианта работают, это просто вопрос логики – глупо создавать поле класса лишь для того, чтобы передать данные из одного метода класса в другой, и при этом не быть уверенным, что это значение в поле класса не будет переписано из другого метода до того, как попадет "по назначению". Представьте, что этот класс потребовалось расширить новой функциональностью – где гарантия, что, добавляя новые методы, Вы учтете все связи, что были раньше построены на хранении промежуточных значений в поле класса? И это те же самые архитектуры, на уровне класса показывающие то же, что творится в проекте. ООП предлагает использовать заведомо безопасное решение, чтобы исключить возможность ошибки еще на стадии планирования. Аргументы типа "но я же помню че кого" и "да кому надо там чето менять" выглядят, простите, как детский лепет. Нет смысла задумываться о верной архитектуре, если вы делаете банер. Но если от вашей лени будет зависеть безопасность игроков или денег пользователей, стоит прислушаться к тому, что советуют профессионалы. ООП выглядит смешно и монструозно на проектах "одеть куколку" (привет Сандерсу / Кумаранатунгу). Но когда вы планируете что-то динамическое и развивающееся, от него не скрыться. Цитата:
|
Цитата:
Цитата:
И все равно я не понял, что я выигрываю от того, что протаскиваю по всему приложению ApplicationConfig.appMode и ApplicationConfig.socialNetwork, вместо того, чтобы работать с ними как с глобальными данными. |
Вобщем, я так понял, никто не считает проблемой наличие никому не нужных данных или данных, доступных всем, кому они не нужны. "Разумно" - не то слово, которое приходит мне на ум, ну да ладно. "Лишь бы работало!" - так ведь? Я сбоку постою, не люблю демонстрации.
|
Глобальная доступность константы Math.PI не очень смущает?
|
Цитата:
|
Цитата:
Разные валюты, разные размеры фото, разный функционал. Но все равно, мы приходим к единственному аргументу: "ApplicationConfig.socialNetwork - плохо, потому что общедоступно". Других аргументов я что-то не вижу. :) Но я его, собственно, и задумал как общедоступный, чтобы он всегда был под рукой. |
mikhailk, Вам тоже стоит вступить в клуб "я читаю название топика, прежде чем участвовать в споре". И все же отвечу - нет, не смущает меня константа Math.PI, зашитая в плеере еще со времен МХ наверное, когда об ООП в ActionScript только мечтали. Ее использование не создает сильной связности. Если я когда-нибудь допишу свою графическую библиотеку, использующую класс Math направо и налево, и Вы ее скачаете, Вам не придется бегать по всему интернету в поисках этого класса. Но я не смогу воспользоваться вашим классом, которому для работы кровь из носу нужен другой класс – ApplicationConfig, а не простые настройки инициализации.
Приведите аргумент какой-нибудь, а то я уже не понимаю с чем спорю. "ApplicationConfig.socialNetwork - хорошо, потому что общедоступно". Это всё? А есть какое-нибудь объяснение, почему "общедоступно – это хорошо"? Так сказать, по сути спора? |
Цитата:
Мое мнение по теме. Если есть возможность (разумная) избавиться от глобальности - к этому нужно стремиться. Как уже было сказано выше, многое при этом решается еще на этапе проектирования. Как уже было сказано выше, публичные переменные доступны всем, бери - не хочу, делай что хочешь. Другое дело геттеры/сеттеры, даже скорее только геттеры - показать покажу, а испортить не дам. Это инкапсуляция, это ООП. Если же нужно что-то супер-глобальное, почему бы не использовать статику? Но это уже другая тема. |
Вобщем-то, спора никакого нет.
Я так сделал для собственного удобства. Наличие статического класса ApplicationConfig и публичной переменной socialNetwork позволяет мне при необходимости сделать быструю доводку интерфейса под конкретную сеть, в т.ч., в тех классах, которые изначально не планировались к настройке под сеть, т.е. параметры соцсети в них изначально не передаются, а значит надо их тащить туда дополнительно. Где-то через конструкторы, где-то через дополнительные методы. Соответственно, мой аргумент прост как 5 копеек: удобство за счет незначительного послабления в части строгости ООП. Добавлено через 3 минуты Цитата:
Если бы над проектом работала группа программистов, я бы реализовал через сеттер/геттер. В момент загрузки клиента вычислялся бы параметр сети, который потом де-факто становился бы константой. |
Я говорил не о программистах. Скорее о человеческом факторе. Но когда работаешь один, действительно, многие проблемы кажутся... Кажется что их нет. Проект при этом может быть успешным и различные доработки нисколько не напрягают (в контексте темы) единственного кодера.
|
Ладно, немного сбавим градусы.
Мне просто интересно, в практическом смысле, вот Вы создали скажем класс, способный выводить сообщение юзера с его фотографией, датой и прочим. И Вам не жалко сделать его инвалидом, хватающимся за некий левый ApplicationConfig с набором стилей? Ведь это не позволяет Вам использовать этот классик повторно в другом проекте as is. Как Вы с этим живете? |
Цитата:
|
Цитата:
Но в промежуточных по иерархии классах может появляется код который только передает общие объекты к младшим. Вот эти младшие ссылались бы на глобальный синглтон, например. Тут все определяется уверенностью в том что, не потребуется 2-й логгер, например(их обычно глобальными делают, хотя даже логгер мне таки потребовался второй на текущем проекте) На самом деле я не фанат глобальных вещей. Потому что в один прекрасный момент младшему объекту потребуется передать параметр в зависимости от того, кому он принадлежит - всё! Глобальные точки доступа можно выкидывать и чесать репу. |
Очередная тема, которая приведет к холивару )
Вообще не понимаю тех, кто утверждает что глобальные переменные приводят к связанности, и тут же говорят, что нужно протягивать свойства до нужного места. Вот это, по-моему, как раз и есть связанность, ведущая к полнейшей неразберихе. |
здесь под связанностью имеется в виду зависимость объекта не от непосредственного класса его содержащего или манипулирующего им, а опосредованная зависимость от классов уровня приложения.
То есть объект получается связанным, сросшимся с конкретным приложением, его конкр. структурой. Вот это - не комильфо. |
Честно, ничего не понял из вышесказанного )
Цитата:
|
Цитата:
При "каскадной" инициализации Вы передаете экземпляру только то, что нужно конкретно ему (естественно, включая то, что нужно для инициализации его детей-составляющих, если они есть). Класс ни к чему не привязан. Он не требует наличия команды поддержки. В этом смысл "абстракции"/самодостаточности и "инкапсуляции". Да, он тоже требует параметров для настройки. Но, в отличие от штабиста, он требует ТОЛЬКО то, что ему нужно, и не требует ИСТОЧНИКА, а только сами данные. Поэтому неважно, в каком проекте он используется, ему надо только размеры, стиль, текст и картинку, но не структуру, отдающую эти данные. Вам не надо городить для него специальных точек доступа ВЫШЕ этого класса, выискивая в его коде, кого и за какие сиськи он будет дергать во время работы, вам надо передать нужные настройки в публичные точки доступа самого этого класса, и все. Это "универсальность" и "повторное использование". Почитайте уже ООП. Пора. |
Смотрю, флейм никак не остановится. :)
Давайте уж говорить конкретно - не только про выигрыш, но и про затраты. В условиях, когда приложение развивается по диздоку, который пересматривается постоянно (конкуренты, желания пользователей, тестирование игровых технологий и пр.), мы не знаем заранее, где и когда нам потребуется что-то настраивать в зависимости от параметров приложения, поэтому, если хотим остаться в рамках корректного ООП (т.е., отдаем всем объектам только то, что им положено знать), мы влетаем в очень большие издержки по модификации кода каждый раз, как только появляется необходимость передать новый параметр сверху в самый низ. Вариант с объектом-оберткой для всех параметров AppSettings (или как-то так), который мы закладываем на этапе проектирования и передаем всем сверху вниз через конструкторы, позволяет минимизировать затраты по доработке, но нарушает правило, что каждый получает только то, что должен, значит корректным признан быть так же не может. ЗЫ. По поводу реиспользования кода - мне искренне хотелось бы посмотреть на реиспользование окна банковских операций по переводу валюты соцсети в игровую валюту в приложениях, не связанных с социальными сетями. Но это так, реплика из зала. |
mikhailk, goodguy, вы просто не постигли Дао
|
Цитата:
|
Аа, так вон оно в чем дело :D
Не, а по большому счету я согласен с Wolsh'ем, и сам использую иногда глобальные переменные только из лени ) В серьеных проектах всегда исползьзую подход описаный Волшем |
Мне кажется все зависит от проекта, ведь реализовать любой проект можно по разному, в зависимости от нужд и удобства.
Вот например, недавно делал приложение, показывающее некие списки, данные в которых постоянно меняются с сервера. Ну и более в приложении ничего небыло. Так вот сами списки - есть ни что иное как нарисованная кодом графика, и тут я использую класс глобальный переменных, - зачем? Ну захотелось мне сменить ширину блока, высоту, или просто цвет,( градиентный например ), с одной стороны - можно и в коде поменять, да фигня, а с другой стороны если graphics идет следующим образом типа moveTo, lineTo и т.д. раз 100 ( ну красивую я фигуру рисую - ок ) , то проще изначально поменять внутри этих мувов и лайнов, на глоб константу, и теперь в любой момент я получу нужный мне скин сменив только 2 строчки, не гробя весь код, с другой стороны эти переменные можно и в классах зашивать и там уже тоже менять по 2 строки да и все. Ну а если у нас несколько не взаимосвязанных классов, которые реализуют графику приложения ? В каждый класс лезть , искать и править по 2 строчки, когда проще открыть конфиг файл и в нем все сразу и поправить? Имхо - тема холиварная, из оперы - МВС или не МВС, каждый пишет как ему удобнее, главное чтобы это конкретно не было Быдлокодством, ну а чуть чуть можно :D |
Глобальным в принципе может быть то, что не нужно менять (т.е. не переменные), а функции, например, которые не зависят от контекста (parseInt - в любом месте программы должна делать одно и то же и всегда вернет один и тот же результат, буде один и тот же ввод). Цифры :) символы строк, элементы энумераторов и т.п. могут быть глобальными т.как нет смысла делать 2 разных. Там, где в принципе может быть два разных, глобальные лучше не делать.
Если вы хотите немного глубже понять проблему - есть такой тезис, что переменные, вообще, как таковые - один из главных источников ошибок программ. Т.о. существует понятие программ без побочных эффектов - очень грубо говоря, программ, в которых переменные не используются в принципе (в теории, так можно действительно написать любую программу, но это очень непрактично). В любом случае, количество переменных нужно стараться сводить к минимуму т.как переменные хранят состояние, а это значит, что функции становятся зависимыми от состояния и на ваши плечи ложится ответсвенность за то, чтобы протестировать функции во всех возможных состояниях, что, очень часто не возможно в принципе. Но вы можете с этим бороться сводя область использования каждой конкретной переменной к минимуму - таким образом уменьшая количество вариантов, которые нужно тестировать, и, таким образом, вы пишете более надежный код. |
Цитата:
Код AS3:
|
Уже пошло as-кунг-фу. :D
Например функцию вычисления факториала, можно написать без переменных? |
Да не ну бред яж сказал) Просто wvxvw товаришь начитанный, умный, давно на форуме, и как говорится не лыком шыт, но в данный момент - его слова стоят под глубочайшим сомнением))) Хотя меня коробит слово в ТЕОРИИ , может он и хотел сказать , что в теории и бог существует, только его никто не видел
|
Господа. Может, всё таки, потрудитесь открыть новую тему для выяснения этого вопроса? Вы название темы то читали?
@wvxvw. Не уверен, что всё понял. То есть ты считаешь, что контекстная зависимость объектов, в случае с глобальными полями, и "мусор" в родительских объектах при протаскивании данных в дочерние - это вопросы "десятые", так? Главное - сохранять контроль над изменением значений переменных (параметризующих приложение, например)? |
Цитата:
Функция принимает одни параметры и возвращает другие. Переменных в языке нет вообще - только константы. Цитата:
Код AS3:
Код AS3:
|
Да, это в принципе особенность всех декларативных языков такого плана, Erlang, ML (и наследники CaML / Obj-CamML), Scheme и т.п. в них не используются переменные. Если вы будете размышлять логично, то значение любой вашей переменной вычисляется (т.е. его можно описать функцией), либо задается один раз (константа). Проблема которую решают переменные заключается в том, что иногда не практично много раз вызывать функцию (т.как результат уже один раз был получен). Но, хороший код старается избегать повторных вызовов функций (конечно, иногда это неизбежно), но, тем не менее, к этому нужно стремится :)
fish_r: Это теория немного другого плана, отношение к глобальным переменным в ней - это следствие (одно из). Следуя ей, естесственным образом не будет возникать проблем с глобальными переменными т.как контекст переменной будет всегда определятся областью, в которой она может быть только одна, и, естесственным образом же, не будет возможных конфликтов, когда `кто-то неизвестный меняет значение'. Но это теория, а не практическое руководство к действию. Ее нужно осознать и сделать максимально похоже :) |
Цитата:
Вот сдесь: Код AS3:
|
Цитата:
От параметра зависит результат работы функции, но сам он остается неизменным. |
carrotoff да ну нафиг?
Код AS3:
|
| Часовой пояс GMT +4, время: 04:37. |
Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.