![]() |
Стиль реализации статического класса
Вариант 1:
Есть статик класс: Код AS3:
Как видно getLocal() вызывается в каждой статической функции. Что, наверное тратит лишние производительные ресурсы. Вариант 2: можно сделать статическую переменную static var sharedObject:SharedObject; и один раз получить куки, а далее использовать ее во всех статик функциях. Код AS3:
Вариант 3: при объявлении статической переменной, сразу же ее инициализировать Код AS3:
Какой вариант правильнее всего выбрать? |
Цитата:
|
может проще синглтон использовать?
|
Синглтон?
Я бы сделал еще статический метод init(), в который передавал SharedObject.getLocal(Constant.SHARED_OBJECT_NAME). |
Терпеть не могу статику. Мне кажется лучший вариант от maxkar.
Статику можно использовать исключительно в качестве хэлперов. |
Код AS3:
Код AS3:
|
maxkar
>>правильнее всего сделать методы в Profile не статическими, создавать один его экземпляр при старте >>приложения Согласен, к этому и стараюсь идти, чтобы не плодить глобал переменные, но порой очень не удобно передавать экземпляр внутрь иерархической структуры классов. КорДум Я бы сделал еще статический метод init(), в который передавал SharedObject.getLocal(Constant.SHARED_OBJECT_NAME). Не очень хорошо, когда в статик классе нельзя пользоваться другими статик функциями, пока не вызвать статик ф-ю init. В этом и изначальная загвоздка была. dsQuadro Замечательное решение к данной задаче: - глобал доступ - создание экземпляра идет не при запуске программы, а в том месте, где в первый раз воспользовались функцией, это супер! - минимум статик функций - появилась возможность только один раз вызвать ф-ю getLocal в конструкторе и передать SharedObject приватной переменной, которая далее используется в функциях класса. - решилась проблема с первоочередностью вызова init - такую функцию вообще вырезаем. Ага спасибо за пример , реализация заготовки синглтона у меня была: Код AS3:
|
Цитата:
Исключением является "крупномодульное" взаимодействие (плагины и т.п., получающие набор классов среды выполнения). Но там подобная передача ограничивается тем же одним уровнем, код внутри плагина точно так же собирается "от меньшего к большему". Так что "далеких" передач объектов нигде нет, есть только последовательность создания модуля/приложения. При использовании inversion-of-control контейнера там не линейная, а древовидная схема получается, но это не принципиально. |
Цитата:
У flashdynamix есть в утилитах SWFProfiler со статическим методом init(), который принимает ссылку на stage. Ну и я делал как-то похожее. Синглтон, в общем, нужен. |
maxkar
>>что где-то не до конца вынесены зависимости Для снижения связей и зависимостей между классами в древовидной иерархии, я стараюсь максимально применить композицию построенную на ее принципе и интерфейсах. Тем не менее, никогда не задумывался и не придерживался правилу "Вся программа при инициализации собирается "снизу вверх"". Как только узнаешь это правило, тут же всплывают все приемущества такого подхода, при том что я очень люблю композицию. Спасибо за совет, буду больше думать об этом! Действительно, если упрощенно говорить, то передача класса по дочерним классам, может быть выстроена почти на одном уровне вложенности. Кстати, посоветуйте какие книжки можно почитать по архетиктуре ПО? Т.е. к примеру по паттернам проектирования материал читаю, также стараюсь использовать правила SOLID и пр. |
Это не правило, это наблюдение того, что получается на практике :)
По архитектуре нужно скорее не читать, а писать. Основное, что определяет архитектура - набор абстракций. Абстракции лучше всего записывать человеческим языком, так как "названия класса" мало для описания абстракции. Отсюда вывод - нужно писать документацию (asdoc). Во время написания такой документации как раз могут всплывать ошибки архитектуры. Так, если параметр метода или конструктора плохо согласутеся с абcтракцией, выражаемой классом, значит, вероятно, нужно вынести дополнительный уровень абстракции (вместо параметра передавать уже созданный класс, например). Большой объем документации может свидетельствовать о том, что нарушен SRP. Обычно достаточно нескольких (1-5) предложений для хорошего описания. Конечно, встречаются и случаи, когда документации нужно действительно больше. Далее. Нужно освоить полиморфизм и инкапсуляцию. И то, и другое ортогонально ООП (например, прекрасно выражается в ФП). Вообще, и то, и другое, связано с абстракцией. Полиморфизм - возможность описывать одной абстракцией различные детали поведения. Инкапсуляция - отсутствие "не соответствующих абстракции" деталей реализации. По данным аспектам книг не посоветую - не знаю. Еще очень полезно освоить понятия coupling и cohesion. а также то, какие типы cohesion лучше и хуже. Здесь можно почитать "Совершенный код" Стива Макконела ("Code Complete"), глава 5 "Design In Construction". Там как раз описан coupling. Еще стоит посмотреть на главы 6.2 ("Good Class Interfaces") и 7.2 ("Design at the Routine Level"). Первая - про абстракции, вторая - про cohesion. Желательно попробовать что-нибудь функциональное (lisp (не углубляясь в метапрограммирование), scheme, ml (ocaml/sml), haskell (хотя там уже уклон в сторону типов)). Практика написания на них закрепляет навыки функциональной декомпозиции (именно функциональной!) да и инкапсуляцию/полиморфизм демонстрирует в новом свете. Еще могу порекомендовать "Practical API Design Confessions of a Java Framework Architect". Автор пишет о немного специфичной области, но много и общеприменимых идей. Для архитектуры особое внимание стоит обратить на различие "provides" и "requires". Отличие принципиальное и очень помогает в разработке. Обычно любой класс пишется либо для удовлетворения "requires" (и проектируется от требований в конкретном месте), либо "provides" - библиотечный класс, который предоставляет функции с широкой обсластью применимости. Двум сразу сценариям один и тот же класс удовлетворять не должен. На практике обычно большинство классов реализуются путем уточнения и написания "requires" (дизайн сверху вниз, пишется высокоуровневый код, затем реализуются его зависимости, для них реализуются их зависимости и т.п.). Потом уже выделяются библиотеки ("provides") которые с помощью адаптеров (разработанных от "requires") используются при решении задачи. Еще у того же Макконела в "Совершенном коде" можно прочитать про метафоры программирования. Особое внимание стоит обратить "toolbox metaphor", это нужно для того, чтобы критично относиться к рекламе различных методологий. Ну а после этого нужно писать дальше. Заниматься декомпозицией. На уровне кода. На старте приводит к большому количеству интерфейсов и классов, но дает достаточно много возможностей замены реализации. На уровне библиотек. У вас одна большая "стандартная библиотека" в компании или много маленьких? Если одна большая - распилить на много маленьких, но с хорошей функциональной cohesion. Например, библиотеки UI, функции работы с коллекциями, функции для работы с функциями, несколько библиотек работы с сетью (на разных уровнях абстракции). Освоить бранчевание кода (в version control)) и не бояться экспериментировать. С большим количеством небольших библиотек экспериментировать проще, чем с одной монолитной - гораздо точнее ясны требования к библиотеке и сама библиотека для переделки изолирована. Также нужно следить и за своим ощущением о "качестве" текущей архитектуры. Это удобство ее использования в самом широком смысле (необходимость писать лишний код только для удволетворения нужд фреймворка, неудачные абстракции, сложность модификации под другие задачи и т.п.). А практически все остальные принципы следуют из уже сказанного выше. Тот же SOLID. SRP - это чистота абстракции и удобство полиморфизма. Open/Closed principle автоматически работает при разделении на дизайн от "requires" и "provides". Там же и его ограничения всплывают. Очевино, что "provides" для введения новой функциональности менять не стоит. А вот классы, созданные от "requires" как раз вполне можно (такие классы без их пользователя обычно имеют мало смысла). LSP - хорошее правило для работы с абстракциями. ISP - частный случай SRP на самом деле. Ну и плюс следствие "requires" и полиморфизма по каждому независимому аспекту (именно так и реализуется хорошее разбиение). Dependency Injection - еще одна реализация SRP, где разделяются ответственности за создание объектов и выполнение его функций. В общем, архитектура - это больше практическая дисциплина. В ней мало теоретических работ. Так что фундаментального читать практически нечего. Но очень полезно читать всевозможные описания существующих проектов. Например, блоги разработчиков. Там описаны проблемы, варианты их решения и результаты примененеия решений. Полезно знать возникающие вопросы, последствия различных решений. При этом совершенно не обязательно соглашаться с самими решениями! Достаточно считать, что автор провел эксперимент и получил определенные результаты. Как их трактовать, решаете уже вы сами. |
Есть такой способ принятия решений известный как Five Whys или Root Cause. Про него писал менеджер компании Toyota Шоичи Оно. Это способ как принятия решений, так и анализа случившихся событий, как правило, негативно повлиявших на исход.
Собственно, ничего нового в этом нет, но как и с любыми простыми вещами, когда они случаются в комбинации с другими простыми вещами иногда можно потеряться :) Смысл анализа заключается в том, чтобы последовательно спросить "почему" пять или больше раз (как правило, больше уже не нужно). В вашей ситуации, ход размышлений мог бы быть следующим: - Почему я делаю одну и ту же операцию много раз? - Потому, что я не хочу создавать экземпляр SharedObject до того, как будет вызван один из методов, но я не знаю, какой из методов будет вызван первым. - Почему существует неопределенность, какой из методов будет вызван первым? - Потому что все методы статические, и я не могу прямо повлиять на порядок вызова - Я не могу обязать какой-то из методов быть вызванным раньше остальных, т.как контекст в котором создаются методы мной не управляется. - Почему я не могу управлять контекстом, в котором существуют нужные мне методы? - Потому, что методы статические, и неуправляемость присуща именно таким методам. На этом этапе уже можно сделать вывод, что делать методы статическими - плохая идея т.как если бы вы сделали их методами класса, то, например, в конструкторе класса вы могли бы создать нужный вам SharedObject и, таким образом, решить начальную проблему. |
maxkar
Спасибо, за столь интересный и развернутый ответ! Я недавно почти прочитал, как мне кажется очень полезную книжку ActionScript 3.0: Design Patterns Она доставила мне уйму удовольствия, стараюсь применять шаблоны проектирования на практике, где это требуется. Кстати, что касается одиночки, жаль что нельзя создать базовый класс и от него наследовать функционал одиночки: переменные и ф-ю getInstance(), т.к. она статическая и ее унаследовать нельзя. Приходится в каждом новом классе заново создавать копировать код функционала одиночки. |
Кстати, интересный момент. Шаблоны проектирования, это как раз противоположность анализа. Т.е. шаблон, это способ избежать анализа, и, основываясь на интуитивном предположении о желаемой структуре проекта, реализовать ее по уже готовому образцу. С практической точки зрения, это более выгодный способ, но он чем-то сродни методу Монте Карло. Т.е. он допускает, что будет принято ошибочное решение, т.как "инуиция подвела". Зато, он дает результат гораздо быстрее, чем детерминистский анализ.
Ваш пример тому подтверждение. Вы интуитивно решили, что шаблон "одиночка" является решением вашей проблемы, в то время как нет никакой практической необходимости в том, чтобы SharedObject был создан в единственном экземпляре, или, по крайней мере, это не следует из вашей постановки задачи. |
wvxvw
Интересно пишете, а так да, обычно решения принимаются или списком "за и против" или интуитивно на базе шаблонов. В данном случае класс Profile является надстройкой над SharedObject, и подохдт больше под сервисный класс, экземпляр которого создается один раз. >>в то время как нет никакой практической необходимости в том, чтобы SharedObject был создан в >>единственном экземпляре Можно использовать SharedObject вызвав его в любом месте программы, но как мне кажется это внесет разрозненность в логическую структуру, т.е. я стараюсь каждый отдельный функционал ( в данном случае одиночка Profile инструмент сохранения/загрузки данных игры из куки ), как можно больше локализировать, чтобы была более читаемая и узнаваемая структура кода (системы). Когда проект разростается, очень важно, чтобы он разбивался на кучу логических частей (за каждой закреплена своя узкая задача), при том взаимозаменяемых и свободно расширяемых (модульность). |
А вы не сможете избежать того, чтобы SharedObject был создан в нескольких экземплярах: например, пользователь открыл вашу страницу в нескольких закладках, в нескольких браузерах, даже разных версиях плеера и т.п. Т.е. то, что вы пытаетесь сделать на уровне приложения будет вас только вводить в заблуждение относительно того, как оно будет по-настоящему работать.
|
По сути so[name].data это константа.
Код AS3:
Цитата:
|
объясните пожалуйста доступно чем плохо использование статики... спасибо
|
Вроде ничем не плохо. Скорость доступа, правда, страдает. Если у вас цикл из 100к итераций, то скопируйте поле в локальную переменную.
|
Статики это может быть даже очень хорошо - зависит от того, что вам нужно. В большинстве случаев, статическая функция это такая функция, которая не нуждается в "состоянии" т.е. на нее не влияет текущее состояние приложения и она сама не влияет на текущее состояние приложения. Еще такие функции называют "чистыми". Только не потому, что они часто моются, а потому, что они сильно упрощают тестирование приложения, т.как не нужно проверять работу функции в разных ситуациях. Например, сложение - чистая функция, т.как не зависимо от никаких внешних факторов, вы получите результат основанных только на параметрах переданных в функцию.
Есть языки, которые стараются использовать только чистые функции, но зачастую это оказывается очень непрактичным, например, вы не захотите устанавливать соединение с сервером баз данных всякий раз, как вам нужно будет послать запрос - напротив, вы захотите хранить подключенное состояние сервера. Функции которые специализируются на объекте какого-то типа зависят от состояния этого объекта, это может приводить к разным негативным последствиям, например, невозможности математически описать систему в которой работает функция (а следовательно, невозможности сделать вывод о ее полезности). Это так же может привести к ситуации, в которой функция неадекватно отреагирует на состояние объекта на котором она специализируется. Но как правило, с точки зрения эффективности, такие функции имеют преимущество т.как им не нужно вычислять все операции, которые приведут объект с которым они работают в нужное состояние. Я бы считал хорошей практикой состояние кода когда в нем все, что только возможно сделать статически, без ущерба для программы, делается статически, и только в местах, где производительность обязывает использовать методы объектов их использовать. К сожалению, такой подход оказывается непрактичным в языках типа AS потому, что очень часто программисту нужно наперед планировать совместимость. Это становится возможным если использовать интерфейсы т.как они не предписывают конкретную реализацию. Но отдельные (статические) функции не могут реализовывать интерфейсы, и поэтому часто есть смысл использовать метод объекта там, где хотелось бы использовать статическую функцию. |
Цитата:
Добавлено через 13 минут Цитата:
Код AS3:
Код AS3:
Добавлено через 1 час 10 минут Цитата:
|
| Часовой пояс GMT +4, время: 12:12. |
Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.