![]() |
Модераторы: Sardar, Aliance |
![]() ![]() ![]() |
|
Се ля ви |
|
|||
![]() Java/SOAрхитектор ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 2016 Регистрация: 5.6.2004 Где: place without tim e and space Репутация: 5 Всего: 127 |
Я описывал чуть выше - весь мой опыт работы в крупных проектах свидетельствует, что без разделения кода на зоны ответственности эффективная кооперация большого количества разработчиков практически невозможна. В итоге максимум, на что можно рассчитывать - это код, который пишут 2-3 человека, из которых один главный, а эффективность работы остальных сильно снижена из-за того, что они должны постоянно разбираться в коде первого что бы что-то к нему добавлять. Как раз на разделение зон ответственности направлен ряд приёмов в Java, которые я и хочу сюда привнести. К сожалению, я не могу с вами согласиться. Т.е. если это и сделают, то очень не скоро их использование станет стандартом де-факто. Да за примером далеко ходить не надо - вы же сами пишете: значит, вы занимались PHP, а какой, позвольте спросить, версии? Ваш переход на Python состоялся до или после выхода PHP 5, в котором появились довольно-таки хорошие ОО-средства работы с кодом? Я, конечно, не в курсе ваших мотивов, но, к сожалению, Python тоже пока весьма слабый игрок на поле крупных корпоративных приложений (хотя многие надеются, что со временем станет) - и брать с него пример по-этому в таких вещах несколько преждевременно - он ещё не настолько успел себя зарекомендовать. Так же и с JS 2.0 - у меня большие сомнения, что его моментально реализуют и он моментально распространится по 90-95% аудитории интернет-пользователей. А пока не настанет такой момент, его использование будет просто забавой программистов на досуге - не более того, ибо ни один денежный заказчик с этими технологиями связываться не рискнёт. По моим прогнозам, после принятия этого стандарта до этого момента пройдёт года 3 - не меньше. Эти три года вы предлагаете лишь мечтательно воздыхать в предвкушении? Если так - не имею возможности составить вам в этом компанию ![]() Когда вышел PHP 5 и где рынок хостеров, наперебой предлагающих размещать у них сайты, написанные на нём, по-дешевле? Сколько их сейчас и как быстро появлялись те, что есть? Нет рынка - считай, нет и технологии, есть только игрушки... Ну а насчёт строго-статичных концепций - я не очень в курсе про С++ и PHP, но в Java есть такая штука - Reflection API - которая позволяет работать с классами как с mutable, делая с ними всё, что угодно - считай, если бы все программисты постоянно использовали Reflection API, эта ситуация во многом бы и напоминала реалии программмирования на JS. Просто при программировании на Java не принято использовать Reflection API, он используется только для специфичных задачь, например сетевыми взаимодействиями и инструментальными средствами для облегчения разработки. Примерно тот же подход я предлагаю внести и сюда - некоторое соглашение, что мы не используем без крайней на то необходимости метод "eval" и динамическое создание/удаление/изменение методов, а так же стараемся по-минимуму использовать public-поля и, если уж используем, то с сохранением их типа и других соглашений в отношении них. Эти защиты, т.е. инкапсуляция, делаются для того, что бы упростить интерфейс класса, дав пользователю библиотеки доступ только к тем методам и полям, которые сделаны для него и ник каким другим. Что бы он мог полностью абстрагироваться от реализации и думать о решении задачи в тех терминах, в которых ем предлагается о нём думать. Потому что реализация - это не его зона ответственности, за это отвечают другие - а именно - создатели этой библиотеки.
Ну, во-первых здесь не имитация private`ов, а самые настоящие private`ы - попробуте-ка обратиться к свойству "_privateField1" напрямую - ничего не выйдет, оно замкнуто - так что это самое настоящее private-поле, никакой "имитации". Просто реализовано оно через замыкание. А по поводу RIA - я свои аргументы изложил. Я не знаю, как писался GMail, но учитывая что таких приложений не очень много, могу предположить, что обошёлся этот проект достаточно дорого и потребовал привлечения хороших профессионалов, которых под силу найти, обучить и сбить в дружный коллектив могут себе позволить немного компаний. В моём понимании проекты подобного масштаба удобнее писать большими командами, а разработчики - это люди со своими проблемами и заморочками и без изоляции одного кода от другого и чёткого разграничения ответственности чаще всего далеко не уедешь. Вот этот-то подход и оборачивается злом в больших проектах. Реальность такова, что заказчик, на которого давят конкуренты, будет давить на вас со сроками и постоянными непредсказуемыми изменениями в проекте, и что бы под этим давлением отстаивать нормальную, стройную архитектуру приложения, нужно иметь железные нервы и большой авторитет в глазах заказчика, которых чаще всего нет. В итоге либо вы, либо кто-то другой не выдержит и начнёт использовать "грязные" приёмы программирования - т.е. эксплуатировать слабые, не защищённые с концептуальной точки зрения, места в технологиях на уровне их реализации - например, в данном случае, зная об этом именовании, слабовольные программист начнёт активно работать с этими значениями напрямую и плодить в будущем трудноуловимые баги, которые хорошо если ему попадётся исправлять и он ещё будет помнить, что он делал, а если они достанутся кому-то, кто придёт после него, когда он уже уволится и его уже это не будет касаться? В итоге через несколько лет разработка больших проектов превращается в настоящий кошмар, где без рефакторинга ничего не сделаешь, а разоряться на рефакторинг никто не будет... -------------------- |
|||
|
||||
dsCode |
|
||||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 565 Регистрация: 8.9.2007 Где: Saint-Petersburg Репутация: 19 Всего: 26 |
поправка - занимаюсь и в данный момент (хотя, в последнее время - больше фронтэндом, а именно - JS), по версиям - начиная с 3-ей и до текущей 5.2.6. А Питоном я занимаюсь только "на досуге" (пока). Мотивы? Всего лишь показал схожесть с JS и, как там реализованы private-свойства. Питон идет в составе любого нормального дистрибутива Linux. Кстати, Java мне также очень нравится, поэтому не подумайте, что я собираюсь тут холиворить о том, какой язык лучше. Я вправе использовать все, какие потребуются [с учетом их специфики для достижения оптимальных результатов]. Я в курсе =) и в PHP она достаточно хорошо организована. Более того, в Питоне эта "штука" тоже есть. Анализ-то - понятно, но скажите, как при помощи рефлекции (или интроспекции) можно добавить новое свойство / метод в класс и, чтобы это свойство отобразилось на всех уже инстанцированных объектах? [я просто не использую ее каждый день, и не слышал, что так можно ![]()
Кто такой слабовольный программист? Зачем он начнет это делать? Вот это, как раз-таки, игрушки. Если ему так это захочется, он пойдет, переименует свойство в public и будет менять его дальше напрямую. Нет-нет, я знаю, что такое инкапсуляция и зачем она нужна. В разных языках - разные подходы, и Питон я приводил лишь для примера альтернативного подхода - пусть "псевдо-инкапсулируещего", но тем не менее. И это не значит, что я против инкапсуляции в Java, PHP, C++ - вовсе нет, не делайте неверных выводов. Ах, пардон, я не заметил return new function() {. Ну, т.е. получился wrapper который должен дублировать имена приватных свойств (рабочих приватных свойств) в своем скопе (только с двумя подчеркиваниями). Каждый объект имеет собственные свойства getPrivateField1 и setPrivateField1 (и т.д.) - пусть это теперь не "цельные тяжелые куски", а лишь ссылки на методы контейнера, но все же - они свои, в то время как семантически одинаковым методам место в прототипе (но здесь получается выигрыш в скорости - посредством делегирования медленней получить результат, чем вызвав свой метод, который "под боком", но проигрыш в ресурсах). Только я боюсь, что кто-то скажет (когда увидит вот это в каждом методе):
"Блин, а ... никто не знает, зачем в каждом методе здесь вот эти две строчки всегда надо писать? Инкапсуляция? Да ладно?... Хм.. Оригинальный подход..". Не кажется ли Вам, что, забудь все тот же "слабовольный программист" (Ваше определение) написать загрузку этих инкапсулированных строк, он еще больше трудно-уловимых багов наделает? P.S.: еще раз, тем не менее, я в состоянии оценить проделанную работу. ![]() Это сообщение отредактировал(а) dsCode - 12.6.2008, 17:29 |
||||
|
|||||
AKS |
|
|||
Участник форума ![]() ![]() Профиль Группа: Участник Сообщений: 725 Регистрация: 20.9.2006 Репутация: 27 Всего: 52 |
Се ля ви, да, действительно, теперь в порядке! Стал разбираться с кодом – появился все тот же вопрос. Вы ушли от более простого к более сложному. Если раньше в теле конструктора для каждого экземпляра создавалась пара геттер/сеттер для доступа к локальной переменной, то теперь для каждого экземпляра создается объект privateState плюс все та же самая парочка геттер/сеттер, являющаяся теперь методами этого объекта. Вопрос в следующем – Вы просто смирились с тем, о чем писали ранее: "тут получается, что я расточительно создаю каждый раз новый объект-функцию"?
Ну и еще не могу удержаться, чтобы не задать буквально парочку вопросов. У Вас сейчас _super – это св-во глобального объекта. Каждый конструктор в момент вызова будет присваивать ей новое значение. Это так хитро задумано? ![]() ![]() dsCode, я просто дословно воспринял это ваше "obj.getA() будет работать, но obj.a - уже нет". Подумал, как же так сделать, чтобы obj.a было доступно через obj.getA(), и никак иначе. ![]() |
|||
|
||||
dsCode |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 565 Регистрация: 8.9.2007 Где: Saint-Petersburg Репутация: 19 Всего: 26 |
объект, который содержит скоп всех верхних "породителей" (ведь и _privateField1 и _privateField2 оседают в скоп-чейне медотов this._get и this._set (которые всегда свои для privateState'a), так?). И помимо этих двух геттеров / сеттеров, есть еще и ссылка-геттер, и ссылка-сеттер, которые хоть и ссылки, но имеют значения, а значит - "жрут ресурсы". Это сообщение отредактировал(а) dsCode - 12.6.2008, 17:40 |
|||
|
||||
AKS |
|
|||
Участник форума ![]() ![]() Профиль Группа: Участник Сообщений: 725 Регистрация: 20.9.2006 Репутация: 27 Всего: 52 |
Я их и имел в виду, написав "парочка". Т.е. я все по-прежнему, с начала темы, обращаю внимание именно на объекты (раньше были функции, теперь объект плюс его методы), которые будут создаваться всякий раз для каждого экземпляра отдельно. |
|||
|
||||
dsCode |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 565 Регистрация: 8.9.2007 Где: Saint-Petersburg Репутация: 19 Всего: 26 |
AKS, да это-то я вижу =) Я просто хотел поинтересоваться про скоп-чейн, который хранит все эти замкнутые var'ы. Скоп внешней функции приплюсовывается к скопу внутренней при ее создании. Получается, что и this._get и this._set имеют скоп с var'ами _privateField1 и _privateField2 (поскольку используют эти var'ы). В то же время, privateState всегда новый (в виду new). Получается куча этих скопов, связанных с this._get и this._set будет жить при создании нового объекта (или там ссылка на, может быть, какой-то общий скоп-чейн?).
Это сообщение отредактировал(а) dsCode - 12.6.2008, 18:16 |
|||
|
||||
AKS |
|
|||
Участник форума ![]() ![]() Профиль Группа: Участник Сообщений: 725 Регистрация: 20.9.2006 Репутация: 27 Всего: 52 |
dsCode, там получается следующее. Сначала идет вот это: F._class = new F;. В момент первого вызова конструктора F выполняется та часть его кода, которая в else. Все, что там создается - там же и остается. Все методы хранят ссылку на variable-объект, созданный в этот момент (момент первого вызова F). Переменная _privateField1 - одна на всех. Ее поиск будет осуществляться так (VO - это variable-объект функций): _get VO, VO анонимной функции, createPrivateState VO, F VO (тот, что был создан в момент первого вызова).
|
|||
|
||||
dsCode |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 565 Регистрация: 8.9.2007 Где: Saint-Petersburg Репутация: 19 Всего: 26 |
AKS, ага... Т.е. на момент первого вызова (фактически - на момент определения _get / _set, которые используют _privateField1 из скопа F), будет однозначно определена цепь скопов, по которым будет производиться поиск _privateField1 при вызове _get - не зависимо от того, что this.createPrivateState всегда возвращает результат новой анонимной функции. Эмм.... Ну да, в любом случае _privateField1 принадлежит VO(F) и будет искаться в нем. Спасибо =)
|
|||
|
||||
Се ля ви |
|
||||||||||||||||
![]() Java/SOAрхитектор ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 2016 Регистрация: 5.6.2004 Где: place without tim e and space Репутация: 5 Всего: 127 |
dsCode,
А, ну тогда вот это прямо по адресу: Это замечательно. Я, честно говоря, тоже немного сталкивался с Python`ом и тоже испытываю к нему симпатию. Особенно нехватает в Java его фишки с блоками с помощью табуляций - настолько это было бы удобно!.. Хотя вообще-то, больше всех мне нравится язык SmallTalk - это вообще божественный язык программирования, жаль, что ни одна крупная корпорация не взялась его продвигать и писать под него библиотеки на все случаи жизни, как содружество Java Community Process для Java, Microsoft для C# и Borland для Object Pascal... :( Но это уже совсем другая тема. Я не очень подробно занимался этим вопросом. Я слышал, что это реализуется на этапе подгрузки класса - можно переопределить ClassLoader и при подгрузке класса в JVM поменять в нём всё что угодно. Однако про такие приёмы, как изменение свойств класса, что бы они отразились на уже созданных экземплярах я не слышал - но, возможно, есть и такие, я просто не достатьчно подробно занимался этим вопросом. Можете спросить об этом в соответствующем разделе Vingrad`а - у нас по Java очень сильные специалисты. Не столько в этом, сколько в том, что теперь объект-функция (ведь каждая функция - это объект) теперь создаётся один раз и все объекты просто на неё ссылаются - на одну и ту же. Я сначала хотел, действительно, реализовать их через прототип, но тогда я не смог бы продолжать цепочку наследования дальше - т.е. не смог бы обеспечить каждый объект F своим собственным экземпляром E - поскольку прототип у класса был бы один и нельзя было бы реализовать скозную (через класс) связь объекта с объектом предка - задача, с которой началась эта тема. Так что пришлось реализовывать так. Фактически, это - паттерн. Обычно в комментариях указывается, что "это и то было реализовано с использованием паттерна такого-то...". И что бы разобраться в чужом коде, если натыкаешься на упоминание о паттерне в комментариях, очень полезно бывает посмотреть описание этого паттерна в каталоге паттернов - тогда все вопросы о страннастях кода отпадают. По крайней мере так принято в мире Java. Здесь так же может помочь только этот подход.
Совершенно верно! По-этому я и говорю:
AKS,
Да, теперь это просто пара ссылок на существующие вне объекта методы.
Почему же смирился? Как раз наоборот - каждая функция-то теперь одна единственная, на неё только ссылок много, но ссылки памяти практически не занимают, в отличие от объектов, на которые они ссылаются. Представьте, что у вас 100 000 экземпляров одного конструктора с одной парой геттер/сеттер. Если он реализован в простой модели, то это означает, что у нас появляется ещё 100 000 объектов-функций геттеров и 100 000 объектов-функций сеттеров. А в данной модели 100 000 ссылок на геттер и 100 000 ссылок на сеттер - что будет тяжелее обработать браузеру? Это, конечно, зависит от того, насколько хорошо реализованы ссылки в браузере, но думаю, что объём памяти, используемой при таких раскладах в первом и во втором случае просто несоизмерим - второй подход тут просто единственно-возможен.
Это ошибка, спасибо, что подсказали. Действительно, нужно поставить var, уже исправил. Кстати раз это private-поле, то хранить его нужно в объекте privateState - а тогда и передавать его туда нужно параметром для правильной инициализации, что я и сделал:
и потом:
Это проверка, переданы ли аргументы. Просто инициировать объект сразу после создания имеет смысл лишь тогда, когда ему был передан хотя бы один аргумент - иначе это означает, что объект создаётся для будущего наследника. Просто в нашем простом случае у нас так и так нету параметров, так что и в случае отсутствия даже одного первого аргумента мы тоже должны вызвать метод "init". Так что первая строчка "для порядку" - что бы когда кто-то будет copy/paste`ить этот код, то ему было просто удобнее вписывать свой код в те места, где сейчас по сути заглушки ![]() -------------------- |
||||||||||||||||
|
|||||||||||||||||
dsCode |
|
||||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 565 Регистрация: 8.9.2007 Где: Saint-Petersburg Репутация: 19 Всего: 26 |
Се ля ви,
В Python ООП модель заимствованна именно из SmallTalk (хотя на Смолтоке я ни разу не программировал - не доводилось (как ни странно - даже ради интереса), но, уверен, что мне бы тоже понравился (в виду того, что он является и прародителем JavaScript'a). Может, как-нить гляну на досуге). Кстати, есть реализация Jyton - реализация Питона на Java, выполняющаяся через JVM, таким образом есть возможность использовать классы Java. Ну ладно, не о Питоне речь - опять отвлекася =)
Не сомневаюсь, что сильные, да только мне еще сильнее "кажется", что нет такого ни в Java, ни в C++, ни в PHP (но есть в JavaScript, Python, Ruby (скорей всего, не проверял) и Smalltalk (также интуитивно предполагаю)).
Так принято в любой нормальной системе. И я имел в виду, что "паттерн" этот будет слишком избыточным в коде (постоянное присутствие этих двух строк) и в итоге, все равно, сжирающим память. Ну а теперь обратно к вопросу (и AKS правильно подметил): пусть getPrivateField1 теперь будет ссылкой, но createPrivateState у каждого объекта свой (вы же сами меня поправили, когда я не досмотрел, что состояния у объектов - свои), и ввиду return new function() { ... } так же будут свои _get и _set - т.е. остается все та же "парочка" (только она теперь в другом месте - внутри createPrivateState), плюс к этому две ссылки - getPrivateField1 и setPrivateField1. Это сообщение отредактировал(а) dsCode - 13.6.2008, 01:12 |
||||
|
|||||
Се ля ви |
|
||||
![]() Java/SOAрхитектор ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 2016 Регистрация: 5.6.2004 Где: place without tim e and space Репутация: 5 Всего: 127 |
Да и PHP есть реализация и вообще в JDK6 есть механизм скриптинга - можно множество языков реализовывать и использовать.
Насчёт createPrivateState - что значит - у каждого объекта свой? Это метод класса, который просто возвращает нам объект. Этот объект у каждого свой, но метод-то один ![]() Ну да, согласен, у нас появляются пара _get и _set для каждого объекта и в случае с одним полем это выглядет одинаково, но одно поле - это только для демонстрации, подразумевается-то, что у каждого объекта по многу свойств и, соответственно, много пар геттер/сеттер и тогда при таком подходе мы меняем всё это множество методов на одну реализацию методов и _get с _set`ом для подмены контекста класса. Выигрыш будет именно при наличии большого количества методов. -------------------- |
||||
|
|||||
AKS |
|
|||
Участник форума ![]() ![]() Профиль Группа: Участник Сообщений: 725 Регистрация: 20.9.2006 Репутация: 27 Всего: 52 |
Се ля ви, я, конечно, не очень много видел в своей жизни, но хотелось бы написать, что такой конструкции не встречал. Получилась не плохая тема для блога (Вы ведь, вроде, хотели статью писать). Теперь единственное, что может напугать, так это: "подразумевается-то, что у каждого объекта по многу свойств". Т.е. если будет много св-в, то конструктор будет выглядеть громоздко. Но это, наверняка, можно обойти, используя, например, массивы или еще как-нибудь...
Ну а в общем - мне нравится (хоть и не испытывал толком, но зато уже "привык" к ходу вашей мысли ![]() |
|||
|
||||
AKS |
|
|||
Участник форума ![]() ![]() Профиль Группа: Участник Сообщений: 725 Регистрация: 20.9.2006 Репутация: 27 Всего: 52 |
Забыл про проверку аргументов написать. ;)
Вот это: if (arguments[0] != null) не проверка "переданы ли аргументы". Это проверка "нет ли у первого аргумента значений null/undefined". Поэтому и спросил - это дизайн такой на запрет передачи подобных значений или еще что-то. |
|||
|
||||
dsCode |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 565 Регистрация: 8.9.2007 Где: Saint-Petersburg Репутация: 19 Всего: 26 |
аай, ну это уже опечатка (Copy-Paste'ная) - конечно, я имел в виду объект privateState, а не метод, который его создает. угу, ну это, действительно, радует =) Се ля ви, ну а в общем - мне тоже нравится в плане реализации private'ов в стиле Java (как я уже говорил =)). Anyway, хранение всех этих семантически одинаковых геттеров / сеттеров в прототипе, наличие псевдо-инкапсуляции, и отсутствие в каждом методе этих двух строк по загрузке / выгрузке privateState'a, - будет быстрее (замкнутый var всегда будет искаться дольше в цепи, чем this-свойство) и легче (и по ресурсам и по трудозатратам). А вот при какой реализации будет больше трудноуловимых багов, - это надо еще проверить, и, я думаю, вы еще напишете об этом в своей статье =) Это сообщение отредактировал(а) dsCode - 13.6.2008, 14:21 |
|||
|
||||
Се ля ви |
|
||||||||||||||||
![]() Java/SOAрхитектор ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 2016 Регистрация: 5.6.2004 Где: place without tim e and space Репутация: 5 Всего: 127 |
Да, спасибо за поправку. Изменил на
Ещё нововведение - наследование решил снести внутрь объявления класса:
![]() Чуть по-сложнее, но тоже оказалось возможным избавиться и от другой неудобной строчки:
![]() Второй заяц, которого мы убиваем этим приёмом - теперь мы создаём класс только в момент создания первого его экземпляра, таким образом в случае, если нам объект не понадобится, мы сэкономим пользователю память. Ну и некоторые редакторы на "super" ругаются - вроде как зарегистрированное слово, хотя браузеры проглатывают. Не будем искушать судьбу и аргумент функции "createPrivateState" назовём "super_", а то - мало ли что? В общем, финальный вариант кода:
-------------------- |
||||||||||||||||
|
|||||||||||||||||
![]() ![]() ![]() |
Форум для вопросов, которые имеются в справочниках, но их поиск вызвал затруднения, или для разработчика требуется совет или просьба отыскать ошибку. Напоминаем: 1) чётко формулируйте вопрос, 2) приведите пример того, что уже сделано, 3) укажите явно, нужен работающий пример или подсказка о том, где найти информацию. |
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | JavaScript: Общие вопросы | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |