Re[24]: Ответ
От: TK Лес кывт.рф
Дата: 27.01.04 04:12
Оценка:
Hello, "IT"
>
> IT>>С той оговоркой, что в решеаемой задаче используется ремоутинг. Такая формулировка устроит?
>
> TK>А если ремоутинг не используется? т.е. реально считается, что System.EnterpriseServices.ServicedComponent это просто "неживое" решение (особенно библиотечные COM+ компоненты) из-за тормозов в CBO?
>
> Можно вопрос точнее сформулировать?

Просто не раз уже упоминалось, что использование CBO это тормоза и только из-за ремоутинга их не заметно. Вот и интересно — а как быть с ServicedComponent — ведь этот класс наследуется от CBO и должен автоматически получать все проблемы с этим связанные.
Posted via RSDN NNTP Server 1.8 beta
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Re[25]: Ответ
От: IT Россия linq2db.com
Дата: 27.01.04 04:49
Оценка:
Здравствуйте, TK, Вы писали:

TK>Просто не раз уже упоминалось, что использование CBO это тормоза и только из-за ремоутинга их не заметно. Вот и интересно — а как быть с ServicedComponent — ведь этот класс наследуется от CBO и должен автоматически получать все проблемы с этим связанные.


Похоже что так. Нужно мерить.
Я сейчас померил скорость создания CBO объекта (без проксей) и простого объекта, разница в сотни раз. Многовато конечно. Создание обычного объекта может быть оптимизировано до нескольких десятков команд процессора, а CBO это переходы из unmanaged в managed и т.п. Основные тормоза где-то тут.
Если нам не помогут, то мы тоже никого не пощадим.
Re[26]: Ответ
От: TK Лес кывт.рф
Дата: 27.01.04 05:05
Оценка:
Здравствуйте, IT, Вы писали:

TK>>Просто не раз уже упоминалось, что использование CBO это тормоза и только из-за ремоутинга их не заметно. Вот и интересно — а как быть с ServicedComponent — ведь этот класс наследуется от CBO и должен автоматически получать все проблемы с этим связанные.


IT>Похоже что так. Нужно мерить.

IT>Я сейчас померил скорость создания CBO объекта (без проксей) и простого объекта, разница в сотни раз.

В смысле без проксей? По умолчанию прокси будет создаваться всегда, и при первом вызове CBO (конструктор) вызов пройдет по максимально длинному пути — через создание всех приемников и т.п.
с линейкой не считал, но наверное там как раз в районе сотни процессорных инструкций и набежит.

IT>Многовато конечно. Создание обычного объекта может быть оптимизировано до нескольких десятков команд процессора, а CBO это переходы из unmanaged в managed и т.п. Основные тормоза где-то тут.


Переход managed / unmanaged — достаточно быстрый. Собственно никакого перехода то и нет — просто jit навставляет десяток лишних инструкций на вызов каждого метода (это если контекст не покидать). Да даже если и покидать — ты считаешь, что сотня инструкций (циклов нет) это серьезный performance hit для вызова бизнес метода?
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Re[27]: Ответ
От: IT Россия linq2db.com
Дата: 27.01.04 05:36
Оценка:
Здравствуйте, TK, Вы писали:

TK>Переход managed / unmanaged — достаточно быстрый. Собственно никакого перехода то и нет — просто jit навставляет десяток лишних инструкций на вызов каждого метода (это если контекст не покидать). Да даже если и покидать — ты считаешь, что сотня инструкций (циклов нет) это серьезный performance hit для вызова бизнес метода?


Вот тест:

using System;
using System.Runtime.Remoting.Proxies;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Serialization;

namespace Example
{
    // -------------------------------------------------

    public class MyProxy : RealProxy
    {
        public MyProxy(Type type) : base(type)
        {
        }

        public MarshalByRefObject CreateInstance()
        {
            InitializeServerObject(null);

            return base.GetUnwrappedServer();
        }

        public override IMessage Invoke(IMessage msg)
        {
            return null;
        }
    }

    [AttributeUsage(AttributeTargets.Class)]
    public class MyClassFactoryAttribute : ProxyAttribute
    {
        public override MarshalByRefObject CreateInstance(Type type)
        {
            return new MyProxy(typeof(MyObject)).CreateInstance();
        }
    }

    [MyClassFactory]
    public class MyObject : ContextBoundObject
    {
    }

    // -------------------------------------------------

    [AttributeUsage(AttributeTargets.Class)]
    public class MikaClassFactoryAttribute : ProxyAttribute
    {
        public override MarshalByRefObject CreateInstance(Type type)
        {
            return (MarshalByRefObject)FormatterServices.GetUninitializedObject(typeof(MikaObject));
        }
    }

    [MikaClassFactory]
    public class MikaObject : ContextBoundObject
    {
    }

    // -------------------------------------------------
    
    [AttributeUsage(AttributeTargets.Class)]
    public class ProxyClassFactoryAttribute : ProxyAttribute
    {
        public override MarshalByRefObject CreateInstance(Type type)
        {
            return base.CreateInstance(type);
        }
    }

    [ProxyClassFactory]
    public class ProxyObject : ContextBoundObject
    {
    }

    // -------------------------------------------------

    public class CBOObject : ContextBoundObject
    {
    }

    // -------------------------------------------------

    public class JustAnObject
    {
    }

    class Test
    {
        static void Main()
        {
            MyObject     mo = new MyObject();
            MikaObject   io = new MikaObject();
            ProxyObject  po = new ProxyObject();
            CBOObject    co = new CBOObject();
            JustAnObject jo = new JustAnObject();

            DateTime dt = DateTime.Now;
            for (int i = 0; i < 500000; i++)
                mo = new MyObject();
            Console.WriteLine("MyObject:     {0}", DateTime.Now - dt);

            dt = DateTime.Now;
            for (int i = 0; i < 500000; i++)
                io = new MikaObject();
            Console.WriteLine("MikaObject:   {0}", DateTime.Now - dt);

            dt = DateTime.Now;
            for (int i = 0; i < 500000; i++)
                po = new ProxyObject();
            Console.WriteLine("ProxyObject:  {0}", DateTime.Now - dt);

            dt = DateTime.Now;
            for (int i = 0; i < 500000; i++)
                co = new CBOObject();
            Console.WriteLine("CBOObject:    {0}", DateTime.Now - dt);

            dt = DateTime.Now;
            for (int i = 0; i < 500000; i++)
                jo = new JustAnObject();
            Console.WriteLine("JustAnObject: {0}", DateTime.Now - dt);
        }
    }
}


Вот результат:

MyObject:     00:00:02.0156250
MikaObject:   00:00:00.4531250
ProxyObject:  00:00:39.5937500
CBOObject:    00:00:33.7500000
JustAnObject: 00:00:00.0156250


В общем, насчёт сотен раз я ошибся
Если нам не помогут, то мы тоже никого не пощадим.
Re[15]: Ответ
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 27.01.04 07:04
Оценка: 1 (1) +1
Здравствуйте, Batiskaf, Вы писали:

B>Никого я не собираюсь поучать, все кругом взрослые дядьки, просто мне казалось что форумы существуют для обмена опытом, а глядя на этот топик такое впечатление что времена доисторических религиозных разборок продолжаются в других руслах, нафига спрашивается...


Следует помнить о том что читают этот топик значительно больше народу, чем пишут. Вот для них собственно.
... << RSDN@Home 1.1.3 beta 2 >>
AVK Blog
Re[28]: Ответ
От: TK Лес кывт.рф
Дата: 27.01.04 07:19
Оценка:
Здравствуйте, IT, Вы писали:

TK>>Переход managed / unmanaged — достаточно быстрый. Собственно никакого перехода то и нет — просто jit навставляет десяток лишних инструкций на вызов каждого метода (это если контекст не покидать). Да даже если и покидать — ты считаешь, что сотня инструкций (циклов нет) это серьезный performance hit для вызова бизнес метода?


IT>Вот тест:


Ну, круто

IT>Вот результат:


MikaObject:   00:00:00.4005960
JustAnObject: 00:00:00.0100149
JustAnMbrObject: 00:00:00.0300447


IT>В общем, насчёт сотен раз я ошибся


как видно само создание cbo — процесс достаточно быстрый (MikaObject) и основные задержки идут на формирование инфраструктуры. А учитывая, что основная задача cbo — это фасад бизнес логики, то время создания получается достаточно приемлемым.
с тем же успехом можно попробовать открывать в цикле соединения к бд без использования пула — тоже медленно, вот только кто это реально использует?
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Re[2]: Ответ
От: VladD2 Российская Империя www.nemerle.org
Дата: 27.01.04 09:10
Оценка: 17 (2) :))) :))) :))
Здравствуйте, IT, Вы писали:

IT>А если я забуду воткнуть твои строки в вызываемые методы? А если мне захочется добавить ещё немножко аспектов? А вдруг заказчик одумается и решит отключить всё это нафиг? Каждый раз контекстный поиск замена?


IT, что бы убедить людей у которых догмы уже вросли в мозжечке нужно использовать их же терминологию. Ну, примерно так:

Пьеса о создании супер рэплэйсилке

Да! Ты прав! Это тот самый подход который был всем нужен, и которого все ждали. Но есть пара проблем. Поменять несколько тысяч методов даже один раз сложно. Нужно как-то автоматизировать этот процесс. Нам нужен тулз для рефакторинга. Согласись — это будет удобно!

Так что же должен уметь наш тулз? Ну, предположим замена по контксту. Но могут возникнуть проблемы. При замене по контексту может оказаться так, что имена методов совпадут с чем-нибудь, что трогать не надо. Или имена переменных перепутаются. Геморроя конечно меньше, чем при ручной замене. Но все же макросы и регекспы не совершенны. Так чего же им не хватает?

О! Идея! Им не хватает контекстности! Наш реплэйс должен уметь не просто находить текст, а прасить исходник и заменять и позволять отделять имена методы и их параметры не только по именам, но и по контексту языка. Таким образом наш тулз должен быть интеллектуальным реплэйсом учитывающим синтаксис языка.

Можно ли реализовать такую фичу в лоб? Несомненно, но есть одна проблемка. Создание примитивного парсера — это уже сложная задача. Так что делать такой парсер для локальной задачи очень расточительно. Но можно же сделать его универсальным! И тогда его можно будет подключить к макросам VS и использовать там где надо.

Эврика! Мы упростили себе работы на два порядка. Теперь такая контекстная замена делает в 5-10 нажатий мыши. Но... Но после некоторых замен мы теряем информацию. Что же делать? Наши замены оказывается необратимы! При некоторых из них мы обязаны брать информацию извне, а при других уничтожать лишнюю (на этот момент) информацию.

Придумал! Мы скопируем удаляемую информацию в отдельный файл!!!... Нет, опять как-то криво. А что если делать бэкапы? Тогда при если нужно будет все восстановить мы подымим бэкап и сделаем по нему нужную замену. Почти здорово, но душа прости чего-то белого и пушистого.

Конгениально! Мы не будем вообще ломать исхоники, а будем делать замену по контексту (мы же не забыли, что она теперь очень точная, почти интеллектуальная!) в отдельный каталог... прямо перед компиляцией. Ура!!! Вот она мечта копи-пэст-реплэйсера!!!

Ой, а что же у меня получилось? Макросы?! Вроде очень похоже, но с другой стороны нет. Макросы не контекстны, а наш супер реплэйсер контекст держит как тузик грелку. А! Точно у нас синтаксически управляемые макросы! Во!!!

Здорово. Но осталась одна проблема. При появлении новых задач по замене приходится писать код замены. А может и это автоматизировать? Точно! Как? А мы будем парсить код в синтаксическое дерево, и создавать процедуры, модифицирующие это дерево через универсальный АПИ. Тогда скоро мы наберем библиотеку и сможем применять нужные замены в нужных местах и комбинациях. Но как нам все же пометить куски кода для замены? О! Мы их пометим атрибутами!!!

Ну, все кажется идея супер реплэйса доведена до идеала. Ну, и на фиг нам ваш АОП?

Как это он и есть? Мы же делали систему реплэйсов по контексту? А это оно и есть. Просто реализованное по человечески. Ну, так бы сразу и сказал...

Занавес...

... << RSDN@Home 1.1.3 beta 2 >>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[9]: Ответ
От: VladD2 Российская Империя www.nemerle.org
Дата: 27.01.04 09:48
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Изначально, как я понял, встала задача — развесить хуки на вызовы методов (счетчики, мониторинг и т.д.),

V>так вот, для полиморфных методов это можно решить весьма даже многими способами

Не, у тебя уже зиначальная задача в том чтобы обернуть фрэймворком из неализации абстракций и фабрик код который собственно и должен будет выполнять бизнеслогику. Сдается мне, что объем оберточного кода у тебя бует ого-го каой. Причем если что случись рефакторить тебе его не перерефакторить. А вот теперь представь вметсо того чтобы все через фабрики создавать ты просто помечаешь объект как удаленный и создаешь его через обычный new.

Здорово? Нереально? При твоих технологиях конечно. А вот с АОП очень даже. Ты просто делаешь аспект который прикручивает нужный код ко всем классам помеченым определенным образом. И все. Если что случись меняшь только аспект. Код остается чисты и красивым как уроки общучения ОО-программированию.
... << RSDN@Home 1.1.3 beta 2 >>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[9]: Ответ
От: VladD2 Российская Империя www.nemerle.org
Дата: 27.01.04 09:48
Оценка:
Здравствуйте, vdimas, Вы писали:

V>1. COM — из typelib берем информацию об интерфейсе и в рантайме делаем ему заместитель, совместимый по vf_table, который в каждом методе вызывает наш хуковый счетчик, а потом вызывает (вызывает — громко сказано... делает jump на ) первоначальный метод замещенного метода интерфейса. При возврате ссылки на некий интерфейс — возвращаем прохаканный заместитель, если возвращаемый объект до этого не прохакан (это легко проконтроллировать)


И фигачим на каждый плевок по таблицы из 1024 методов плюс асмовские вставки. А как же иначе? Наш легкий джамп легок только в выполнении. На практике он требует хакерства.

И вот еще какая проблема. Код то может без ком-а работать. Ну, да тоже можно и через виртуальную таблицу зафигачить. Остается правда оверхэд на виртуальный вызов. Но это уже не так критично. Вроде все ОК? Ах да. Это хакерство же нужно теперь подключить ко всем интерфейсам что нужно перехватить. Да не к интерфейсам, а ко всем классам. Ну, да ладно пошли клепать тонны фабрик. Такова силявя.

V>3. .Net — очень много способов как сделать... выбираем на вкус... мне больше всего нравится идея в рантайм генерировать по typeinfo скриптинг, который делает нечто типа 1. и 2. но на "человеческом" .net ЯП, напр. С#


Здорово. Но вот время на компиляцию. Ошибки в рантайме. И трудность в отладке. Беда, однако.


V>Вполне допустимый подход, ибо после компиляции и "переваривания" Jit быстродействие такого объекта в точности равно быстродействию обычного, расходуем время только на автогенерацию и компиляцию скрипта — но это все одноразово, 1 раз на класс (в отличии от CBO, где рефлекшн используется в каждом вызове, что действительно приемлимо разве что в Remouting, где это тонет в общих временных затратах).


Ну, в общем конечно выход. Но вот проблемы описанные выше... А давай как мы твой вариант (смелый и красивый) немножко доработаем напильником... Знаешь, что мы сделам. Мы переведем генерацию кода из рантайма в компайл-тайм. И даже круче. Мы научимся модифицировать исходный код так чтобы можно было менять не только вызовы методов, но и любые части кода.

Правда красивее? Время в рантайме не тратится. Мы имеем проверку на стадии компиляции. И что приятно при отладке у нас полноценная отладочная информация. Мы же просто код компилятором компилировали!

Правда трудности остались. Каждый раз при изменениях аспектов нам нужно перегенерировть сам генератор. Нда. А! О! Придумал. Мы делаем АПИ позволяющее упростить создание генераторов. Делам некий синтаксис позволяющий делать такие замены кода которые нам нужны. Ё! Да мы же до того самого АОП и договорились. Во оно как! А?!

V>} лопата end;


Не. Это уже на кибер трактор тянет.

V>Ну а теперь вернемся в "человеческое" ООП.


Не. Ну, кудаж мы теперь вернемся. ООП то у нас уже человеческий! Без всяких ковычек. Ведь обвязка теперь у нас приклеивается во время компиляции. Причем шаблоны С++ просто детство по сравнению с гибкостью нашего решения. Привда?

V>...Ибо ООП предполагает затрату некоей мыслительной энергии на начальных этапах проектирования.


Погоди. Мы же в реалии жизни хотели вернуться. Или нет? А в реалии еще никто ен смог спроектировать систему без ошибок. Что-то забыли, что-то появилось пока реализовывали... Ну, бывает же... жизнь все же...

V>Тема крайне интересная, и хотелось бы от IT услышать хоть один достойный пример, где АОП имело бы преимущество перед ООП.


Тут оно как. Нет таких преимуществ. Они как бы прекрасно делают каждый свое дело. Просто АОП — это такое крутейшее средство реалтаймного рефакторинга. А ООП — это средство ясного изложения мыслей. Вместе они сила. А порознь одно бессмысленно, а второе начинает намыливаться мелочами не относящимися к делу.


V>И еще, самое главное:

V>Если не трудно, развития ради, интересно посмотреть на код и оценить трудоемкость подхода IT в решении его собственной задачки. ГВ предложил одну строчку кода на все интересующие методы, трудоемкость в этом случае ясна и понятна. IT, давай решение на АОЯП — справедливости ради, а то пока не ясно как все это сравнивать

А слабо прочесть статью ставшую основой этой теме?

Понимаю, качество у нее не очень. Много воды. Формулировки не точные. Ну, да мы договорились с автором и опубликуем статью в журнале "Технология Клиент-Сервер" в честь чего выжмем ее хорошенько, и причешем. Вот тогда может все спорящие ее и прочтут до конца.
... << RSDN@Home 1.1.3 beta 2 >>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[10]: Ответ
От: vdimas Россия  
Дата: 27.01.04 13:28
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Здравствуйте, vdimas, Вы писали:


V>>1. COM — из typelib берем информацию об интерфейсе и в рантайме делаем ему заместитель, совместимый по vf_table,

VD>И вот еще какая проблема. Код то может без ком-а работать. Ну, да тоже можно и через виртуальную таблицу зафигачить. Остается правда оверхэд на виртуальный вызов. Но это уже не так критично. Вроде все ОК? Ах да. Это хакерство же нужно теперь подключить ко всем интерфейсам что нужно перехватить. Да не к интерфейсам, а ко всем классам. Ну, да ладно пошли клепать тонны фабрик. Такова силявя.

Да нет, может я невнятно выразился, но смотрим на выделенное. Это все легко именно в рантайме делается.
И ничего клепать не надо, если согласно лигике один БО возвращает как результат метода другой БО (или их массив), то первый для второго и есть фабрика, и тут-то в рантайм и можно перехватить возвращаемые объекты. (и ведь не важно — только что созданные или когда-нить ранее...)

V>>3. .Net — очень много способов как сделать... выбираем на вкус... мне больше всего нравится идея в рантайм генерировать по typeinfo скриптинг, который делает нечто типа 1. и 2. но на "человеческом" .net ЯП, напр. С#


VD>Здорово. Но вот время на компиляцию. Ошибки в рантайме. И трудность в отладке. Беда, однако.


Дык, отладка-то одноразовая
и предположительный размер генератора невелик, да и результат его работы контроллировать крайне легко — скриптинг на "человеческом" ЯП.


V>>Вполне допустимый подход, ибо после компиляции и "переваривания" Jit быстродействие такого объекта в точности равно быстродействию обычного, расходуем время только на автогенерацию и компиляцию скрипта — но это все одноразово, 1 раз на класс (в отличии от CBO, где рефлекшн используется в каждом вызове, что действительно приемлимо разве что в Remouting, где это тонет в общих временных затратах).


VD>Ну, в общем конечно выход. Но вот проблемы описанные выше... А давай как мы твой вариант (смелый и красивый) немножко доработаем напильником... Знаешь, что мы сделам. Мы переведем генерацию кода из рантайма в компайл-тайм. И даже круче. Мы научимся модифицировать исходный код так чтобы можно было менять не только вызовы методов, но и любые части кода.


VD>Правда красивее? Время в рантайме не тратится. Мы имеем проверку на стадии компиляции. И что приятно при отладке у нас полноценная отладочная информация. Мы же просто код компилятором компилировали!


VD>Правда трудности остались. Каждый раз при изменениях аспектов нам нужно перегенерировть сам генератор. Нда. А! О! Придумал. Мы делаем АПИ позволяющее упростить создание генераторов. Делам некий синтаксис позволяющий делать такие замены кода которые нам нужны. Ё! Да мы же до того самого АОП и договорились. Во оно как! А?!


Так... А теперь давайте ближе к той же теме.
Идет разработка (прямо сейчас) n-таерной архитектуры на дотнете на Windows.Forms в качестве платформы клиента.
Так вот, есть несколько пожеланий (перечислю парочку):
1. Неохота на клиента тянуть библиотеки имплементирующие БО на стороне сервера (из-за их потенциального размера и, вероятно, частой обновляемости да и еще 100 причин), т.е. хошь не хошь а выбираем абстрактные базовые классы или интерфейсы для наших целевых БО.
2. Неохота удаленные экземляры этих БО биндить непосредственно к контролам форм, ибо не все изменения на форме клиента необходимо моментально перегонять на сервер, да и живость такого варианта "под пальчиками" оставляет желать лучшего при dial-up соединении. Из опытов предыдущих разработок выяснилось, что непосредственно гнать на сервер изменение поля БО надо дай бог в 10% случаев (для валидации сложной, либо для изменения значения других полей по сложному алгоритму), Поэтому решено автоматически генерить на клиенте заместитель, построение которого управляется типами и атрибуттами полей открытого абстрактного объявления БО.

Я всерьез предполагаю делать так, как описал выше насчет скриптинга.Статью прочел и доводы понятны. Есть мысли как сделать это сделать иначе, чем предложенный вариант?

Дополнительные условия функционирования системы:
— система начнет эксплуатироваться до своего полного завершения (да, именно так), будет вводится поблочно и предполагает быть максимально гибкой. Клиентское ПО будет при каждом запуске запрашивать текущие версии библиотек и тянуть их последнии варианты.
— БО — интерфейсы не "заморожены", т.е. регуляно могут добавлятся поля, или немного менятся тип существующих и т.д. Учитывая биндинг по именам и спецификацию клиентских форм в XML, это, вроде, не проблема.
— Конечное количество БО может быть действительно очень большим. Учитывая, что в качестве клиента могут выступать даже такие совсем тонкие платформы как планшетные ПК и их разновидности без HD, то предполагается тянуть на клиента библиотеки в процессе работы по мере надобности, т.е. охота сократить их размер до минимума. Учитывая, что один человек в течении одного рабочего дня вряд ли успеет пройтись вообще по всей системе, предполагается, что клиент-работник в силу своих привилегий, специализации и т.д. будет задействовать постоянно дай бог 5-10% всех существующих на сервере БО. Т.е. как бы не имеет смысл делать готовые заглушки заранее, именно охота в процессе работы формировать и догружать библиотеки (маленькие такие библиотеки, содержащие лишь объявления интерфейсов БО и аттрибутику)

И самое главное, поделитесь опытом, насколько реально в дотнетовском проекте перейти прямо сейчас на аспектную платформу без потери скорости? Какие есть инструменты?

Я пока, кроме inline компилятора AspectC# ничего более готового для дотнета не нашел, повторяя Влада — "И трудность в отладке. Беда, однако."
Re[11]: Ответ
От: VladD2 Российская Империя www.nemerle.org
Дата: 27.01.04 14:25
Оценка:
Здравствуйте, vdimas, Вы писали:

V>И самое главное, поделитесь опытом, насколько реально в дотнетовском проекте перейти прямо сейчас на аспектную платформу без потери скорости? Какие есть инструменты?


V>Я пока, кроме inline компилятора AspectC# ничего более готового для дотнета не нашел, повторяя Влада — "И трудность в отладке. Беда, однако."


Тебе не аспектами нужно увлекаться с твоими задачами. И не ООП. Тебе нужно клиентов на веб-интерфейс переводить. И тогда всю эту фигню даже обдумывать нужно не будет.
... << RSDN@Home 1.1.3 beta 2 >>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[11]: Ответ
От: IT Россия linq2db.com
Дата: 27.01.04 14:38
Оценка: :)
Здравствуйте, vdimas, Вы писали:

V>1. Неохота на клиента тянуть библиотеки имплементирующие БО на стороне сервера (из-за их потенциального размера и, вероятно, частой обновляемости да и еще 100 причин), т.е. хошь не хошь а выбираем абстрактные базовые классы или интерфейсы для наших целевых БО.

V>2. Неохота удаленные экземляры этих БО биндить непосредственно к контролам форм, ибо не все изменения на форме клиента необходимо моментально перегонять на сервер, да и живость такого варианта "под пальчиками" оставляет желать лучшего при dial-up соединении. Из опытов предыдущих разработок выяснилось, что непосредственно гнать на сервер изменение поля БО надо дай бог в 10% случаев (для валидации сложной, либо для изменения значения других полей по сложному алгоритму), Поэтому решено автоматически генерить на клиенте заместитель, построение которого управляется типами и атрибуттами полей открытого абстрактного объявления БО.

Вообще-то, как-то это всё мудрёно. БО конечно же не надо тянуть на клиента, на клиента обычно тянется фасадная dll, содержащая интерфейсы к БО и бизнес сущности. Таже валидация, например, может быть (и должна) быть встроена в безнес сущности.

V>И самое главное, поделитесь опытом, насколько реально в дотнетовском проекте перейти прямо сейчас на аспектную платформу без потери скорости? Какие есть инструменты?


Если вы используете ремоутинг, то все возможные тормоза вы уже получили, поэтому можно не стесняться и выносить весь сквозной код в интерсепторы.
Если нам не помогут, то мы тоже никого не пощадим.
Re[12]: Ответ
От: vdimas Россия  
Дата: 27.01.04 15:41
Оценка:
Здравствуйте, IT, Вы писали:

V>>И самое главное, поделитесь опытом, насколько реально в дотнетовском проекте перейти прямо сейчас на аспектную платформу без потери скорости? Какие есть инструменты?


IT>Если вы используете ремоутинг, то все возможные тормоза вы уже получили, поэтому можно не стесняться и выносить весь сквозной код в интерсепторы.


Да нет, имелось ввиду без потери в скорости разработки, разумеется.
Ибо VS.Net + Visio там же и плагин от Together, да еще с intellisense и удобным представлением проектов и классов, да плюс еще NDoc (+ еще 100 удобств, перечислите сами) — это довольно шустрая среда в плане именно скорости разработки.
Re[12]: Ответ
От: vdimas Россия  
Дата: 27.01.04 15:47
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Тебе не аспектами нужно увлекаться с твоими задачами. И не ООП. Тебе нужно клиентов на веб-интерфейс переводить. И тогда всю эту фигню даже обдумывать нужно не будет.


И веб-интерфейс, разумеется будет, для совсем уж тонких клиентов но с быстрым и-нетом (все эти "глобальные" решения принимаю не я, разумеется, это требования заказчика).

Как показал предыдущий проект (C++-клиент, CORBA, Java-сервак), "нормальный" (не веб) клиент куда как субъективно шустрее пашет, ибо по сети гоняются "голые" данные, а всякие мета-инфо и ресурсы форм — лишь однажды, да и те кешируются м/у запусками программы, т.е. в итоге получаем по dial-up и-нету субъективно неплохую скорость работы, с клиентской т.з. сравнимую с работой в локалке с какой-нить CS-системой.
Re[12]: Ответ
От: vdimas Россия  
Дата: 27.01.04 16:25
Оценка: 7 (1)
Здравствуйте, IT, Вы писали:

IT>Здравствуйте, vdimas, Вы писали:


V>>1. Неохота на клиента тянуть библиотеки имплементирующие БО на стороне сервера (из-за их потенциального размера и, вероятно, частой обновляемости да и еще 100 причин), т.е. хошь не хошь а выбираем абстрактные базовые классы или интерфейсы для наших целевых БО.


IT>Вообще-то, как-то это всё мудрёно. БО конечно же не надо тянуть на клиента, на клиента обычно тянется фасадная dll, содержащая интерфейсы к БО и бизнес сущности. Таже валидация, например, может быть (и должна) быть встроена в безнес сущности.


Так и есть, все очень фасадное, фасаднее чем ISomeThing не бывает.
Насчет валидации... Согласно собственной практике валидации можно классифицировать. Некоторые типы валидаций, напр. допустимые значения полей, заданные некоей формулой, легко записываются в виде аттрибутов полей и обрабатываются на клиенте. И нет смысла встраивать подобного рода валидацию в бизнес-сущности, т.к. валидация, не требующая наличия других каких-то других БО или даже доступа в БД легко описывается аттрибутами.

Более сложная валидация может происходить в имплементации самого БО, см. внимательней след. пункт. В тех же аттрибутах задается дополнительный тип поля (определяющий момент запуска валидирующего механизма) — "immediate update". А большинство полей передаются одним махом тем же автогенеренным прокси, который поддерживает наш некий интерфейс типа IDataSync, задействованный как раз при нажатии на клиентской форме кнопки "Save". (После нажатия на Save работающий с программой может вполне оправданно подождать пару секунд, но при набитии нескольких десятков полей все должно работать крайне шустро, и в то же самое время предоставлять возможность в ответ на изменение некоего поля прислать, скажем, обновленный список выбора на соседний ComboBox)

Возвращаясь к бизнес-сущностям, далеко не все виды валидаций да и просто каких-то осмысленных действий можно выполнить "силами" самой бизнес-сущности, в отрыве от других сущностей (которых может не быть в момент обработки в месте этой обработки — скажем на клиеннте), т.е. от них как от таковых (сущностей, "гоняемых" по значению, а не по ссылке) давно отказались.

V>>2. Неохота удаленные экземляры этих БО биндить непосредственно к контролам форм, ибо не все изменения на форме клиента необходимо моментально перегонять на сервер, да и живость такого варианта "под пальчиками" оставляет желать лучшего при dial-up соединении. Из опытов предыдущих разработок выяснилось, что непосредственно гнать на сервер изменение поля БО надо дай бог в 10% случаев (для валидации сложной, либо для изменения значения других полей по сложному алгоритму), Поэтому решено автоматически генерить на клиенте заместитель, построение которого управляется типами и атрибуттами полей открытого абстрактного объявления БО.


Т.е. что охота получить в итоге? Охота получить систему, которая может работать в режиме n-tier приложения или даже в режиме однопользовательского десктоп-варианта. Это тоже дано сверху. В последнем случае клиентские модули работают с БО напрямую (в режиме обычных подгружаемых DLL) и никаких проблем.

При экспериментах, непосредственный биндинг удаленных экземпляров к полям форм ведет себя неважно даже в случае бинарной сериализации. Поэтому, было решено для различных конфигураций создавать различный Session объект, являющийся корнем иерархии фабрик БО. Второй вариант Session-объекта — это просто обычный Session объект "обернутый" нашим автогенерируемым прокси, который распространяет свое действие по автоматическому созданию проксей на всю цепочку создаваемых БО.

Хоть это все вероятно и выглядит мудренно, зато в итоге порождает совсем немного целевого бизнес-кода, именно фреймворк берет на себя многие тонкости по организации передачи данных м/у слоями и кешированием данных. (Да, много чего есть в .net, но вот идеологию immediate or lazzy update пришлось конопатить ручками, хотя, вроде, очевидная весчь...)

Опять же (про бизнес-сущности), оперирование бизнес-сущностями требует ОСМЫСЛЕННОСТИ кода клиента. Хех, кому это надо? На клиента просто приходят ресурсы форм и описание биндинга полей. Что делается на клиенте, так это то, что и должно там делаться: drag&drop, например, и пр. клиентские фишки. (Утрирую, бывает, очень редко, но бывает, что осмысленный код приходится накидывать и на клиенте)

Для нормальной работы всей этой кухни, разумеется, пришлось отнаследоваться от всех потенциально требуемых data-aware контролов, для работы в подобной системе, зато формы можно плодить как грибы (накидал ресурсы и ЗАБЫЛ), а разработчик серверной части (т.е. БО-части) вообще практически не задумывается от том, как и кто создает или работает с его объектами...

В общем, есть что пообсуждать.
Re[19]: Спорно.
От: VladD2 Российская Империя www.nemerle.org
Дата: 27.01.04 23:21
Оценка: :)
Здравствуйте, IT, Вы писали:

IT>
IT>obj.Do<MyClass::Action1>(Tuple(12,Aliased<xParam>(2)));
IT>


IT>Очень наглядно. Хотя, конечно, в качестве job security очень даже ничего


Толи еще будет, если мы все это не остановим!
... << RSDN@Home 1.1.3 beta 2 >>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[20]: Спорно.
От: VladD2 Российская Империя www.nemerle.org
Дата: 27.01.04 23:32
Оценка:
Здравствуйте, naje, Вы писали:

N>вобще по поводу наглядности я там написал что рюшечек всяких можно подобавлять


Достаточно.

N>ты лучше ответь на такой вопрос, что если этот заказчик из твоего вопроса захочет не мониторинг добавить, а производительность неимоверную, и/или чтоб програмка вместе с операционкой помещалась на флэшку 8 МБ (такой запрос более реальный чем просьбя о мониторинге), а у тебя всё с испольлванием RealProxy уже написано

N>что делать?

Я так понимаю IT-у самому все эти реал-прокси не нравятся. Вод добьем R# будем все в компайл-тайме прикомпилировать.
... << RSDN@Home 1.1.3 beta 2 >>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[21]: Спорно.
От: VladD2 Российская Империя www.nemerle.org
Дата: 27.01.04 23:32
Оценка:
Здравствуйте, IT, Вы писали:

IT>Хороший вопрос между прочим. В случае поддержки AOP самим компилятором, как ты понимаешь, никаких проблем не будет. В случае RealProxy, которую, прошу ещё раз заметить, я не предлагал как панацею, имеем тормоза. Соответственно, придётся извращаться либо предложенным тобой способом, либо как предлагает ГВ.


Кстати, из всего предложенного самыми удобными были РеалПрокси и перемап vtbl-а в КОМ-овском объекте. Но и то, и то не катит если метод должен работать быстро. И ни, то ни то не может помочь заменить отдельные операторы и т.п.

PS

Мы там пока вы тут тренеруете силу убеждения нашли подходящий генератор кода, создали репозиторий ЦВС, залили туда превую альфу, открыли несколько дискусий, я написал вводную статью (поглядел бы, кстати).

Сейчас нужно:

1. Новую ветку в проектах.
2. Опубликовать статью (если хочешь допиши туда свои мысли по АОП, или создай отдельную статью).
3. Сделать ссылку на форум в ветке проекта.
4. Дать новость и объявление в дотнетный и С++-ный форумы.
5. Заняться агрессивной агитацией за вступление в редя разработчиков R#.

Если подсобиш, мы будет мтлько рады. А то явно для обращения в АОП-веру не хватает примеров на работающем прототпе.
... << RSDN@Home 1.1.3 beta 2 >>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[20]: Спорно.
От: IT Россия linq2db.com
Дата: 28.01.04 05:18
Оценка:
Здравствуйте, VladD2, Вы писали:

IT>>Очень наглядно. Хотя, конечно, в качестве job security очень даже ничего


VD>Толи еще будет, если мы все это не остановим!


Да, пора заканчивать с этим бардаком!
Если нам не помогут, то мы тоже никого не пощадим.
Re[16]: Ответ
От: Batiskaf Израиль http://www.mult.ru/
Дата: 28.01.04 08:41
Оценка: 25 (2)
Прошу прощения, у каждого тут свой спор, так что к барьеру мистер Ткачев
Итак, здравствуйте, IT, Вы писали:

IT>Какая демагогия? Я тебе привёл вполне реальный пример, может его чуть-чуть приукрасил. Замени пионера на бестолковую операционистку и всё будет как в жизни.

IT>Я тебе не за строки говорю, а за количество траха, которое мы все имеем при смешивании бизнеслогики и сквозного кода.

Вот давай я буду этой бестолковой операционисткой а ты будешь этим пионером, или наоборот, если хочешь .Net реализация АОП тебе не нравится, да? Ну а AspectJ нравится? Раз уж заговорили о количестве траха, то для сравнения я возьму тот же пример из статьи, все тот же Point, Line, DisplayUpdateAspect и попытаюсь выразить это на плюсах, а потом сравним со статьей.


struct Point
{
private:
    int x, y;
public:

    Point()
    {
        x=0;
        y=0;
    }    
    virtual    int getX() 
        { 
            return x; 
        }
    virtual    int getY() 
        { 
            return y; 
        }
    virtual    void setX(int x) 
        {
            this->x = x; 
        }
    virtual    void setY(int y) 
        {
            this->y = y; 
        }

};

struct Line
{
private:
    Point* p1, *p2;
public:
    virtual    Point* getP1() 
        { 
            return p1; 
        }
    virtual    Point* getP2() { return p2; }
    virtual    void setP1(Point* p1) 
        {
                     this->p1 = p1;
               }
    virtual    void setP2(Point* p2) 
        {
                     this->p2 = p2;
               }    
};

template<typename Base>
struct    DisplayUpdateAspectBase : public    Base
{
protected:
    Display* display;
public:
    /*SetDisplay/GetDisplay*/
};

template<typename Base>
struct PointDisplayUpdateAspect : public    DisplayUpdateAspectBase<Base>
{
public:
    virtual    void setX(int x) 
        {
            Base::setX(x);
            display->Update();
        }
    virtual    void setY(int y) 
        {
            Base::setY(y);
            display->Update();
        }
};

template<typename Base>
struct LineDisplayUpdateAspect : public    DisplayUpdateAspectBase<Base>
{
public:
    virtual    void setP1(Point* p1) 
        {
                     Base::setP1(p1);
            display->Update();
               }
    virtual    void setP2(Point* p2) 
        {
                     Base::setP2(p2);
            display->Update();
               }        
};

typedef    PointDisplayUpdateAspect<Point>    DisplayPoint;
typedef    LineDisplayUpdateAspect<Line>    DisplayLine;


Итак, мы я с легостью могу получить UI точки и линии, а так же их не визуальные представления, например мне нужны точки для представления логических кординат в коде вычислений, никакой связи с дисплеем нет. Юзверь в коде по прежнему работает с типом Point*, только пользуется фабрикой для создания визуальных точек и линий, или не визуальных. Решил я завтра обезопасить код DisplayPoint в мультитред логике, пишем следующее:


template<typename Base>
struct    LockAspectBase : public Base
{
protected:
    SyncObj    syncObj;
public:
    /*GetSyncObj*/
};

template<typename Base>
struct    PointLockAspect : LockAspectBase<Base>
{
public:
    virtual    void setX(int x) 
        {
            Mutex mtx( &syncObj);
            Base::setX(x);
        }
    virtual    void setY(int y) 
        {
            Mutex mtx( &syncObj);
            Base::setY(y);
        }    
};

Переписываем определение типа DisplayPoint:

typedef    PointDisplayUpdateAspect<Point>        DisplayPointBase;
typedef    PointLockAspect<DisplayPointBase>        DisplayPoint;


И все изменения, но, с ростом количества аспектов ростет количество вариантов типов, которые я могу создавать, это будет защищенная точка, защищенная точка с отображением, без отображения ( только логический обьект ) защищенный и незащищенный, и всего этого я добиваюсь в нескольких строчках кода. Реюзабилити моих "аспектов" гораздо выше чем в примере из статьи, например мы решили делать 3DPoint:


struct 3DPoint: public Point
{
protected:
    int z;
    3DPoint()
    {
        z = 0;
    }
    virtual    int getZ()
    {
        return Z;
    }
    virtual    void    setZ( int z )
    {
        this->z = z;
    }
};

template<typename Base>
struct 3DPointDisplayUpdateAspect : public    PointDisplayUpdateAspect<Base>
{
    virtual    void    setZ( int z )
    {
        Base::setZ(z);
        GetDisplay()->Update();
    }
};

template<typename Base>
struct 3DPointLockAspec : public PointLockAspec<Base>
{
    virtual    void    setZ( int z )
    {
        Mutex mtx( GetSyncObj());        
        Base::setZ(z);
    }
};


Количество вариантов как ты сам понимаешь ростет, а количество телодвижений за счет повторного использования моих же "аспектов" гораздо выше. Цель применения аспектов лежит в том что бы делать менее связанный, декларативный код, в примере из статьи я этого не вижу. Вот как я могу применить aspect DisplayUpdating в другом месте для другой компоненты в AspectJ, например для 3DPoint??? Они же все hardcoded, там четко прописано к какому методу какого типа все это привязывается, кроме всего нужно уметь понять что тут относится к сетап коду этих аспектов, а что к сквозной функциональности. А что касательно наследования таких аспектов???
Will I live tomorrow? Well I just can't say
But I know for sure — I don't live today.
Jimi Hendrix.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.