Здравствуйте, Сергей Губанов, Вы писали: СГ>Вывод: КОП в .NET еще очень переочень далека от совершенства. Представляю что было бы если бы в C# каждый файл исходного текста программы являлся бы модулем (как в Оберонах). По четыре метра на каждый минимальный модуль — это черезчур!
Ты несешь абсолютную чушь. СГ>Теперь я понимаю почему у некоторых был сильный шок после того как я сказал, что если программа написана на нескольких сотнях файлах исходного текста, то и скомпилирована она должна быть в несколько сотен модулей. В Модулах и Оберонах 1 файл исходника = 1 модуль (компонент) системы. Разумеется, если в .NET такие огромные накладные расходы (от 4 до 8 метров минимум) на каждый модуль, то несколько сотен модулей мгновенно зажрут всю память!
А ты попробуй сделать минимальное консольное приложение, включив в него пару-тройку сборок. И расскажи нам, как зависит использование памяти от количества сборок. СГ>То есть, выходит, что .NET всего лишь деклалрирует, что она якобы компонентная, но на самом деле писать программы состоящие из сотен компонентов под .NET является безумством.
Неверное предположение конечно же приводит к неверным выводам.
... << RSDN@Home 1.1.4 beta 3 rev. 185>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Andre, Вы писали:
S_>> Для разнесения на большое количество сборок есть и другие причины.
A>Недавно в блогах какого то архитектора микрософта встретил упоминание о вредности дробления по мелким сборкам. Вкратце, очень большие затраты на подгрузку. Рекомендовали плодить как можно меньше сборок.
А ведь и в самом деле! И как я на это раньше внимания не обратил! Тупо запускаем Task Manager и наблюдаем:
Каждое минимальное консольное .NET приложение, то есть каждый (консольный) компонент, отнимает 3.8 мегабайтов виртуальной памяти.
Каждое минимальное оконное .NET приложение, то есть каждый (оконный) компонент, отнимает около 8 мегабайтов виртуальной и 7 мегабайтов оперативной памяти.
Вывод: КОП в .NET еще очень переочень далека от совершенства. Представляю что было бы если бы в C# каждый файл исходного текста программы являлся бы модулем (как в Оберонах). По четыре метра на каждый минимальный модуль — это черезчур!
Теперь я понимаю почему у некоторых был сильный шок после того как я сказал, что если программа написана на нескольких сотнях файлах исходного текста, то и скомпилирована она должна быть в несколько сотен модулей. В Модулах и Оберонах 1 файл исходника = 1 модуль (компонент) системы. Разумеется, если в .NET такие огромные накладные расходы (от 4 до 8 метров минимум) на каждый модуль, то несколько сотен модулей мгновенно зажрут всю память! То есть, выходит, что .NET всего лишь деклалрирует, что она якобы компонентная, но на самом деле писать программы состоящие из сотен компонентов под .NET является безумством.
Для сравнения, запускаем BlackBox и идем в пункт меню Info -> Loaded Modules, видим список загруженных модулей. В моем блэкбоксе я насчитал 71 загруженный модуль (по умолчанию). Смотрю сколько он памяти занял: 7 мегабайтов оперативной 6 мегабайтов виртуальной. А если бы BlackBox был бы написан под .NET то семьдесят модулей заняли бы всю установленную на моем компе оперативку и дальнейшая работа была бы сильно усложнена.
Здравствуйте, AndrewVK, Вы писали:
AVK> КОП ортогонально классам.
Дело не в ортогональности. Разница между КОП и ООП в масштабе грануляции. ООП с классами — это микроуровень. КОП с компонентами — это макроуровень. Один КОП-компонент включает в себя несколько ООП — классов/интерфейсов объектов.
Здравствуйте, Silver_s, Вы писали:
S_>- Компонента это следующий, более крупный уровень инкапсуляции после классов.
КОП ортогонально классам.
S_> Инкапсулированный код это минимум деталей торчащих наружу. Для компонентов желательно чтобы они были в двоичном формате,
Обязательно.
S_>- Судя по всему с понятием компонента тесно связано понятие объектная модель.
Компонентная модель.
S_> Класс это (с натяжкой) фабрика объектов с плоским набором функций, компонента может выступать как фабрика объектных моделей.
Нет. Фабрика это сущность, класс это декларация.
S_> или из компонента создать новый, слегка его модифицировав его объектную модель.
Такого требования ни в одном опреджелении КОП я не видел.
S_> Так чтобы в результате опять получился компонет — единица инкапсуляции и деплоймента. Вот с этим у C# проблемы.
Никаких.
S_>В C# компоненты в бинарном формате создавать, инкапсулировать и использовать можно, но этого недостаточно,
Достаточно.
S_>Например имеем компоненту A с такой объектной моделью с корнем IA1.
Опять ты путаешь КОП и ООП.
S_>interface IA1 S_>{ S_> IA2 IA2{get;} S_> void Func1(); S_>}
S_>interface IA2 S_>{ S_> void Func2(); S_> ICallback Callback{get;set;} S_>}
S_>Необходимо создать компоненту B на базе A. S_>Чтобы из B торчала почти такая же ОМ как IA1 (отнаследоваться от ОМ). S_> Но реализовать следующее внутри B: S_> 1) реализовать и подключить CallBack. S_> 2) Закрыть доступ к проперти CallBack. S_> 3) Добавить новую функцию (или поддерево в ОМ). S_> 4) И естейственно чтобы эта компонента B осталась компонентой, т.е. инкапсулированой единицей деплоймента, такой же простой в подключении как исходная A. S_> На C# сейчас такое сделать принципиально невозможно, ... а зря.
Возможно. Вот только здесь явные проблемы с дизайном. Такую кашу в интерфейсах в реальности нужно рефакторить по получения ясной модели.
S_> Враперами теоретически можно обернуть. Но на практике это не реально в дереве могут быть не два узла а десятки, сотни.
CBO спасет отца русской демократии.
S_> Если нужен совсем конкретный пример, то ткнем пальцем в компоненты из Office,
Хреновый пример. Большую кашу, чем API офиса, еще поискать надо.
S_> например PivotTable или Charting. Проимпортируем OWC, полученые обертки будут компонетой, единицей инкапсуляции и деплоймента ( по крайней мере если там где будем деплоить стоит офис). Но в ОМ у PivotTable есть несколько глючных пропертей для DataSource, они завязаны на древние RecordSet'ы, S_>чтобы загнать в них данные нужно DataSet перегнать в XML файл на диске,потом отконвертировать XML в другой формат и потом его вставлять в компоненту.
Для преобразования XML сохранять его на диск не обязательно.
S_> Лучше было бы отнаследоваться от этой компоненты и прикрыть в ОМ эти проперти, и на их место повесить свою проперти типа DataSet.
PivotTable это СОМ. При чем тут C#?
S_> А на C# в лучшем случае можно сделать компоненту с отдельной функцией S_> SetDataSource(axPivotTable pt,DataSet ds), инкапсуляцией здесь не пахнет. S_> Для одной функции может так и сойдет, но для чего то большего это криво.
А правильным решением было бы создание отдельного компонента, занимающегося преобразованием требуемых потоков данных.
Здравствуйте, Silver_s, Вы писали:
S_> ...не обращай внимания на эти лишние 50 классов...
О! А я что говорил! Модули (то бишь компоненты системы, они же сборки в дотНете) должны быть маленькими. 10 классов в одном модуле — это уже серьезно, а 50 — явный перебор.
Здравствуйте, Silver_s, Вы писали:
S_> Для разнесения на большое количество сборок есть и другие причины. S_>Главная из них это правильная декомпозиция и инкапсуляция для более крупных блоков кода чем класс. И пользование соответствующими фичами: internal types, раздельная компиляция, раздельные проекты в студии итд. S_> Можно конечно это все держать в уме и диаграммах, а код валить в кучу (разделив код на директории и неймспейсы), но это не то. S_> Для 30-50 тыс строк 10-15 раздельных проектов (и соответственно сборок) — это разве слишком много? Дык проблем будет гораздо больше если они не будут разделены.
Я тебе вот что скажу по опыту. В нашем проекте изначально был примерно такой подход. Когда количество проектов перевалило за 5 десяток, стало понятно что дальше так жить нельзя. В результате пришлось потратить довольно много усилий для склеивания проектов. Факторами, которые теперь влияют на разделение проектов, являются местоположение (сервер/клиент/дизайнер/утилиты/общее), конфигурация (у нас 2 варианта поставки), внешние компоненты, независимые универсальные фреймворки. В результате жить стало значительно легче.
Ни о чем — не говорит.
т.к. во-первых, программисткого словаря у них нет,
во-вторых, при разработке программ можно использовать, как прикладные аналогии — тогда справедливо использовать слово "компонент", так и математические аналогии, тогда справедливо слово "компонента".
VD>>Ну, и читай ее внимательно: VD>>
компонента, -ы (матем.) VD>>О чем по-твоему говорит выделенное?
Как вобще умудрились позаимствовать из английского слово component, и сделать из него два разных.
А их ведь еще как-то по всем падежам склонять как-то надо
VD>>О чем по-твоему говорит выделенное?
DG>Ни о чем — не говорит. DG>т.к. во-первых, программисткого словаря у них нет, DG>во-вторых, при разработке программ можно использовать, как прикладные аналогии — тогда справедливо использовать слово "компонент", так и математические аналогии, тогда справедливо слово "компонента".
многократно используемый компонент (элемент программного обеспечения, который может использоваться множеством приложений и реализуется в виде dll- или ocx-файлов на основе стандартных интерфейсов)
S_> Для разнесения на большое количество сборок есть и другие причины.
Недавно в блогах какого то архитектора микрософта встретил упоминание о вредности дробления по мелким сборкам. Вкратце, очень большие затраты на подгрузку. Рекомендовали плодить как можно меньше сборок.
Считаю что C# + .NET пока далек от компонентного программирования, хотя приблизился к нему немного ближе чем многие другие языки и среды.
Что такое КОП и компонента, насколько я понял, нет однозначного определения. У меня ИМХО такое:
— Компонента это следующий, более крупный уровень инкапсуляции после классов. Инкапсулированный код это минимум деталей торчащих наружу. Для компонентов желательно чтобы они были в двоичном формате, потому что из исходников торчит бесчисленное множество деталей.
— Судя по всему с понятием компонента тесно связано понятие объектная модель. Класс это (с натяжкой) фабрика объектов с плоским набором функций, компонента может выступать как фабрика объектных моделей. Объектной моделью можно обернуть гораздо более сложный функционал чем объектом.
Объектная модель это связанное множество объектов (чаще дерево), и инкапсулируются за этим деревом сложные внутренние связи.
— В КОП Должна быть возможность манипуляции такими сущностями как компонента (как это делается с классами в ООП).
Например:
Из нескольких компонент создать один новый компонент,
или из компонента создать новый, слегка его модифицировав его объектную модель. Так чтобы в результате опять получился компонет — единица инкапсуляции и деплоймента. Вот с этим у C# проблемы.
В C# компоненты в бинарном формате создавать, инкапсулировать и использовать можно, но этого недостаточно, должна быть возможность и средства производить с компонентами различные манипуляции .
Манипуляций довольно много, в которых реально возникает необходимость.
Необходимо создать компоненту B на базе A.
Чтобы из B торчала почти такая же ОМ как IA1 (отнаследоваться от ОМ).
Но реализовать следующее внутри B:
1) реализовать и подключить CallBack.
2) Закрыть доступ к проперти CallBack.
3) Добавить новую функцию (или поддерево в ОМ).
4) И естейственно чтобы эта компонента B осталась компонентой, т.е. инкапсулированой единицей деплоймента, такой же простой в подключении как исходная A.
На C# сейчас такое сделать принципиально невозможно, ... а зря.
Враперами теоретически можно обернуть. Но на практике это не реально в дереве могут быть не два узла а десятки, сотни.
--------------------------------------
Если нужен совсем конкретный пример, то ткнем пальцем в компоненты из Office, например PivotTable или Charting. Проимпортируем OWC, полученые обертки будут компонетой, единицей инкапсуляции и деплоймента ( по крайней мере если там где будем деплоить стоит офис). Но в ОМ у PivotTable есть несколько глючных пропертей для DataSource, они завязаны на древние RecordSet'ы, чтобы загнать в них данные нужно DataSet перегнать в XML файл на диске,потом отконвертировать XML в другой формат и потом его вставлять в компоненту. Лучше было бы отнаследоваться от этой компоненты и прикрыть в ОМ эти проперти, и на их место повесить свою проперти типа DataSet.
А на C# в лучшем случае можно сделать компоненту с отдельной функцией
SetDataSource(axPivotTable pt,DataSet ds), инкапсуляцией здесь не пахнет.
Для одной функции может так и сойдет, но для чего то большего это криво.
Если я правильно Вас понял, то компонент системы, в общем случае, экспортирует структуру взаимосвязанных интерфейсов объектов — то что Вы назвали объектной моделью (ОМ), а также экспортирует фабрики по производству объектов реализующих эти (и другие) интерфейсы. (Хотя могут быть и вырожденные компоненты системы: 1) экспортирующие только взаимосвязанные интерфейсы, 2) экспортирующие только фабрики по производству объектов реализующих интерфейсы описанные в другом компоненте системы.) С этим я совершенно согласен.
У меня поправочка по поводу:
S_> ...в дереве могут быть не два узла а десятки, сотни...
компонент системы должен быть очень маленьким. Десятки и сотни экспортируемых интерфейсов объектов это слишком много. Лично у меня (после тщательного проектирования) количество взаимосвязанных интерфейсов внутри одного компонента системы не превосходило десятка. Я этого добивался за счет агрегации.
Здравствуйте, Сергей Губанов, Вы писали:
СГ>У меня поправочка по поводу:
S_>> ...в дереве могут быть не два узла а десятки, сотни...
СГ>компонент системы должен быть очень маленьким. Десятки и сотни экспортируемых интерфейсов объектов это слишком много. Лично у меня (после тщательного проектирования) количество взаимосвязанных интерфейсов внутри одного компонента системы не превосходило десятка. Я этого добивался за счет агрегации.
Ну в MSHTML объектной модели например, там довольно много обьектов и интерфейсов и сложно сказать что там что-то лишнее.
Зависит от сложности сущности на которую натягивают объектную модель.
Здравствуйте, AndrewVK, Вы писали:
AVK>КОП ортогонально классам.
Возможно я другое понятие КОП имею в виду, так сказать ObjectModel Oriented Programming
S_>> Класс это (с натяжкой) фабрика объектов с плоским набором функций, компонента может выступать как фабрика объектных моделей.
AVK>Нет. Фабрика это сущность, класс это декларация.
S_>> или из компонента создать новый, слегка его модифицировав его объектную модель. AVK>Такого требования ни в одном опреджелении КОП я не видел.
Я тоже в теории такого требования к КОП не видел, такие требования предявляют реальные задачи.
S_>> Так чтобы в результате опять получился компонет — единица инкапсуляции и деплоймента. Вот с этим у C# проблемы. AVK>Никаких.
Проблем нет только при полной агрегации и полном сокрытии всех агрегированных компонентов.
А определение какой то структуры данных или класс из агрегированой компоненты протолкнуть
наружу уже нельзя. Единственный выход долбаные враперы для них писать.
S_>>interface IA1 S_>>{ S_>> IA2 IA2{get;} S_>> void Func1(); S_>>}
S_>>interface IA2 S_>>{ S_>> void Func2(); S_>> ICallback Callback{get;set;} S_>>}
S_>>Необходимо создать компоненту B на базе A. S_>>Чтобы из B торчала почти такая же ОМ как IA1 (отнаследоваться от ОМ). S_>> Но реализовать следующее внутри B: S_>> 1) реализовать и подключить CallBack. S_>> 2) Закрыть доступ к проперти CallBack. S_>> 3) Добавить новую функцию (или поддерево в ОМ). S_>> 4) И естейственно чтобы эта компонента B осталась компонентой, т.е. инкапсулированой единицей деплоймента, такой же простой в подключении как исходная A. S_>> На C# сейчас такое сделать принципиально невозможно, ... а зря.
AVK>Возможно. Вот только здесь явные проблемы с дизайном. Такую кашу в интерфейсах в реальности нужно рефакторить по получения ясной модели.
Каша это если за каждым интерфейсом по 10 строчек функционала. А если десятки тысяч, то это очень мощная инкапсуляция.
Все зависит от метрик, какой обьем функционала удалось упаковать по отношению
к размеру логичности и понятности интерфейсной части.
К сожалению не всякий функционал можно упрятать за плоским набором функций.
Такой патерн в нескольких проектах очень круто разруливал ситуацию.
Конкретнее: Имеем компоненту объемом пару десятков тыс. строк и довольно сложными связями
внутри. Удалось состряпать интерфейс из небольшой и логичной объектной модельки. Штук 8-10 интерфейсов в дереве,
по 5-10 функций и пропертей в каждом.
Далее на одном из узлов дерева гнездо для плагина — ICallback Callback{get;set;}, в колбэк интерфейсе 5-7 родственных функций
Сам плагин — не совсем плагин а наращивание функционала, по сложности и объему он примерно такой же как и первая компонента (много человеко месяцев), но там совсем другой функционал.
Плагин втыкает в дерево свой колбэк и плюс еще пользуется разными частями дерева ОМ.
В данном случае такая декомпозиция единственно возможный вариант, т.к. резко упростила разработку этих 2 компонент.
Если компоненту-плагин засунуть внутрь то кранты, там связанность и зависимости между частями значительно сложнее,
чем это выглядит по объектной модели.
Все бы хорошо но эта компонента+плагин опять образуют единицу инкапсуляции. Т.е. клиент этих компонент поступает так:
Инстанциирует сущность которая в компоненте 1, инстанциирует плагин передав ему ссылку на ОМ компоненты.
И дальше пользуется функционалом плагина, и частью функционала ОМ компоненты 1 , помня что нежелательно в этой ОМ кое что трогать-то куда прикрепился плагин.
Дык вот нужны средства из этой связки сделать более инкапсулированный компонент, более цивилизоваными средствами чем враперы.
Т.е. кое что прикрыть нужно в этом дереве и кое что прикрепить, чтобы единая сущность получилась.
Так что в этом случае делать? Отказаться от декомпозиции основной компонент-плагин принципиально не возможно и не правильно.
Но к инкапсулированому виду привести с эту связку очень желательно.
Уж проще тогда для всего этого хозяйства потом написать большой и тупой нудный врапер.
S_>> На C# сейчас такое сделать принципиально невозможно, ... а зря.
AVK>Возможно. Вот только здесь явные проблемы с дизайном. Такую кашу в интерфейсах в реальности нужно рефакторить по получения ясной модели.
Это реальная ситуация.
Часто есть чужой компонент/библиотека (или свой, но который менять не хочеться по ряду причин), в котором хочется изменить или добавить/удалить несколько мелочей.
Но изменение этих мелочей выливается во что-то большое и монстрообразное, если исходный компонент имел структуру далекую от плоской.
Здравствуйте, Silver_s, Вы писали:
AVK>>КОП ортогонально классам.
S_>Возможно я другое понятие КОП имею в виду, так сказать ObjectModel Oriented Programming
S_>>> или из компонента создать новый, слегка его модифицировав его объектную модель. AVK>>Такого требования ни в одном опреджелении КОП я не видел.
S_> Я тоже в теории такого требования к КОП не видел, такие требования предявляют реальные задачи.
А при чем тут тогда КОП? Рассказывай в чем у тебя проблемы, а не обвиняй современные языки в недостаточной компонентноориентированности.
S_>>> Так чтобы в результате опять получился компонет — единица инкапсуляции и деплоймента. Вот с этим у C# проблемы. AVK>>Никаких.
S_> Проблем нет только при полной агрегации и полном сокрытии всех агрегированных компонентов. S_> А определение какой то структуры данных или класс из агрегированой компоненты протолкнуть S_> наружу уже нельзя.
Это называется подключение реализаций.
S_> Единственный выход долбаные враперы для них писать.
Не единственный. Как минимум есть еще уже упомянутый CBO и возможность делать это при помощи кодогенерации в рантайме.
А можно просто перепроектировать структуру программы так, чтобы подключение реализаций не понадобилось. Для этого существуют несколько паттернов, например коннектор.
AVK>>Возможно. Вот только здесь явные проблемы с дизайном. Такую кашу в интерфейсах в реальности нужно рефакторить по получения ясной модели.
S_> Каша это если за каждым интерфейсом по 10 строчек функционала.
Это пофигу. Каша не в реализации, а в интерфейсе.
S_> А если десятки тысяч, то это очень мощная инкапсуляция. S_> Все зависит от метрик, какой обьем функционала удалось упаковать по отношению S_> к размеру логичности и понятности интерфейсной части. S_>К сожалению не всякий функционал можно упрятать за плоским набором функций.
Мдя. А по русски никак?
S_> Конкретнее: Имеем компоненту объемом пару десятков тыс. строк и довольно сложными связями S_> внутри. Удалось состряпать интерфейс из небольшой и логичной объектной модельки. Штук 8-10 интерфейсов в дереве, S_> по 5-10 функций и пропертей в каждом. S_> Далее на одном из узлов дерева гнездо для плагина — ICallback Callback{get;set;}, в колбэк интерфейсе 5-7 родственных функций
Я не могу ничего сказать про то, что ты описываешь, могу лишь догадываться. А догадки такие:
1) Колбеки очень неприятная штука на самом деле, особенно при сложных объектных графах, особенно в условиях GC.
2) Практически в любой ситуации существуют несколько проектных решений, одинаково хороших по большинству параметров.
3) Выставление наружу сложных объектных графов как правило сильно утежеляет API и делает его запутанным и слабомасштабируемым. По возможности с подобным следует бороться. Для этого опять же существуют паттерны — мост, визитор.
S_>В данном случае такая декомпозиция единственно возможный вариант,
Не верю.
S_> т.к. резко упростила разработку этих 2 компонент.
Да я уж вижу как упростила. Так что возможностей языка перестало хватать, а от взгляда даже на грубую модель наружного интерфейса становится страшно
Здравствуйте, AndrewVK, Вы писали:
S_>> Так чтобы в результате опять получился компонет — единица инкапсуляции и деплоймента. Вот с этим у C# проблемы. AVK>Никаких.
Вот все таки хочется такую фичу как выборочный экспорт типов из агрегированой сборки наружу.
Например приобрели у некоторого разработчика компоненту. Т.е. сборку .dll
Подключили к проекту, и вылетает ошибка, какая то функция возвращает System.Drawing.Point, надо добавлять ссылку на System.Drawing. А нельзя ли было сделать так чтобы этот компонент ссылался на System.Drawing, и экспортировал Point(ну и все от которых зависит), так чтобы клиент не добавлял ссылки на System.Drawing и не видел бы из нее другие типы кроме Point , желательно даже чтобы через Reflection видно не было. Если же подключит Drawing, естейственно нужно чтобы эти Point оказались одним и тем же типом.
Ну для стандартных то сборок это не так актуально.
А вот если разработчику приспичило при разработке компоненты сделать декомпозицию на 4 сборки.
Вопрос на засыпку, это будет хорошая инкапсуляция или нет?: Если мы приобретем компоненту в таком виде — Разработчик впарил нам компоненту состоящую из 4-х .dll. И инструкцию по применению,
1) Все dll должны лежать в исполняемой директории,
2) При подключении к проекту добавлять ссылку на 3 dll. Одна основная, в двух других по одному классу которые используются основной сборкой как возвращаемый параметр, поэтому на них ссылки тоже надо подключать. На четвертую сборку можно не обращать внимания, она просто должна быть, и никуда ее подключать не надо.
3) Главная сборка полностью для клиента, а из 2 другх используются 2 класса, а остальные 50 классов из них трогать не стоит они только для внутреннего взаимодействия между этими 4 частями.
Ну скажем этому разработчику — "криво получилось, иди дальше инкапсулируй".
"А он скажет — да не могу я их инкапсулировать, я одну сборку вобще купил у третьего разработчика, а во второй сборке этот класс нельзя переносить в основную иначе архитектура попортится сложнее разработка будет. А враперы для этих 2 классов писать запарюсь. Так что либо на 30% стоимость компоненты увеличу, либо не обращай внимания на эти лишние 50 классов, если их не тревожить они вреда не причинят..."
...И накапливаться это будет как снежный ком, разрушая инкапсуляцию.
Так что при сборке одной компоненты из нескольких, проблемки с инкапсуляцией есть.
Здравствуйте, Silver_s, Вы писали:
S_> Например приобрели у некоторого разработчика компоненту. Т.е. сборку .dll S_> Подключили к проекту, и вылетает ошибка, какая то функция возвращает System.Drawing.Point, надо добавлять ссылку на System.Drawing. А нельзя ли было сделать так чтобы этот компонент ссылался на System.Drawing, и экспортировал Point(ну и все от которых зависит), так чтобы клиент не добавлял ссылки на System.Drawing и не видел бы из нее другие типы кроме Point , желательно даже чтобы через Reflection видно не было. Если же подключит Drawing, естейственно нужно чтобы эти Point оказались одним и тем же типом.
Ничего не понял. Разрешение ссылок все равно происходит в рантайме. Ссылки в студии по большей части нужны для компилятора. Даже если ты ссылаешься на сборку, она все равно реально загрузится только в момент использования, а если не ссылаешься то вполне можешь загрузить сам. Если же тебе нужна хитрая механика управления доступностью кода, то для этого есть CAS.
S_> Вопрос на засыпку, это будет хорошая инкапсуляция или нет?: Если мы приобретем компоненту в таком виде — Разработчик впарил нам компоненту состоящую из 4-х .dll. И инструкцию по применению, S_>1) Все dll должны лежать в исполняемой директории, S_>2) При подключении к проекту добавлять ссылку на 3 dll. Одна основная, в двух других по одному классу которые используются основной сборкой как возвращаемый параметр, поэтому на них ссылки тоже надо подключать. На четвертую сборку можно не обращать внимания, она просто должна быть, и никуда ее подключать не надо. S_>3) Главная сборка полностью для клиента, а из 2 другх используются 2 класса, а остальные 50 классов из них трогать не стоит они только для внутреннего взаимодействия между этими 4 частями.
Если есть объективные причины такого разнесения по сборкам (раздельная поставка, компоненты третьих фирм и т.п.) то вполне нормально.
S_> ...И накапливаться это будет как снежный ком, разрушая инкапсуляцию. S_> Так что при сборке одной компоненты из нескольких, проблемки с инкапсуляцией есть.
Здравствуйте, AndrewVK, Вы писали:
AVK>А при чем тут тогда КОП? Рассказывай в чем у тебя проблемы, а не обвиняй современные языки в недостаточной компонентноориентированности.
Я на C# особо не наезжаю, просто некоторые фичи хотелось бы иметь дополнительно.
S_>> Все зависит от метрик, какой обьем функционала удалось упаковать по отношению S_>> к размеру логичности и понятности интерфейсной части. S_>>К сожалению не всякий функционал можно упрятать за плоским набором функций. AVK>Мдя. А по русски никак?
Если две крупные компоненты связаны всего одним callback интерфейсом с 6 функциями, значит они получились очень независимыми. Между 2 сущностями по 500 строчек каждая, callback такого объема это слабенькая инкапсуляция, если они по 10тыс. строк тогда сильная инкапсуляция. Нравится это или нет но эти связи останутся по любому. И лучше эти связи явно запротоколировать интерфейсом и разделить эти части.
AVK>1) Колбеки очень неприятная штука на самом деле, особенно при сложных объектных графах, особенно в условиях GC. AVK>2) Практически в любой ситуации существуют несколько проектных решений, одинаково хороших по большинству параметров. AVK>3) Выставление наружу сложных объектных графов как правило сильно утежеляет API и делает его запутанным и слабомасштабируемым. По возможности с подобным следует бороться. Для этого опять же существуют паттерны — мост, визитор.
Да,конечно, несколько решений существует. То что я описал имеет аналоги в ООП. Если бы делалось в стиле ООП, то очень приближенно первая компонента была бы плоским классом где все свалено в кучу. Но все же в этом классе еще были бы парочка коллекций других классов, в которых абстрактные функции — это альтернатива callback интерфейсам для прикрепления функционала. Классы в этих коллекциях не просто лежат, а взаимодействуют и между собой и с контейнером
Ну скажем примерно 10тыс строк на основные классы, и 10тыс строк на реализацию абстрактных функций.
Но такой вариант был бы очень неудачный, слабая инкапсуляция со всеми вытекающими последствиями.
А так оно реально выглядит как наследование от сложной иерархической компоненты и расширение функционала. Те. наследование от более высокоуровневой штуки чем класс. Только сам механизм которым достигается такое наследование не очень удобный.
S_>> т.к. резко упростила разработку этих 2 компонент. AVK>Да я уж вижу как упростила. Так что возможностей языка перестало хватать, а от взгляда даже на грубую модель наружного интерфейса становится страшно
Лучше небольшие сложности поиметь на самом верхнем уровне при стыковке этих компонент, чем сложности при их реализации.
AVK>Не единственный. Как минимум есть еще уже упомянутый CBO и возможность делать это при помощи кодогенерации в рантайме.
ContextBoundObject? Да его вроде немного для другого делали. Слишком уж темные делишки
внутри него творятся. И перфоманс он вроде неслабо просаживает.
А рантайм кодогенерация вызывает аналогии с ассемблерными вставками на C++, вcе же штатные средства получше и с проверками в компайл тайм.
AVK>А можно просто перепроектировать структуру программы так, чтобы подключение реализаций не понадобилось. Для этого существуют несколько паттернов, например коннектор.
Ну для начала исходим из того что могут быть случаи когда есть компонента с интерфейсом который трогать нельзя — либо от стороннего производителя и без исходников, либо этих исходников гигабайты..терабайты и в них ковыряться нельзя.
Вот что мешает для начала в язык добавить хотя бы такую фичу? :
Здесь IExternalInterface неизменяемый интерфейс из компоненты от сторннего производителя.
Здесь полудинамическое подключение во время конструирования. В компайл тайм здесь все полностью проверяемо. Т.е компилер всегда найдет ошибки если реализация подключилась не вся. А возни с враперами хоть немного но меньше будет.
Здравствуйте, AndrewVK, Вы писали:
AVK>1) Колбеки очень неприятная штука на самом деле, особенно при сложных объектных графах, особенно в условиях GC.
..... AVK>3) Выставление наружу сложных объектных графов как правило сильно утежеляет API и делает его запутанным и слабомасштабируемым. По возможности с подобным следует бороться. Для этого опять же существуют паттерны — мост, визитор.
Мост это по идее разновидность абстракции — "Не до конца реализованый объект + изолированная реализация". Вариантов реализации этой абстракции может быть много для разных целей, одна из них — "патерн мост". Даже простое наследование и переопределение виртуальных функций это похожая вешь но более статическая и с меньшей изоляцией.
Вот вариант с более мощной изоляцией:
IBase — это интерфейс не до конца реализованного объекта, находящегося в изолированой компоненте.
Здравствуйте, Silver_s, Вы писали:
S_> Считаю что C# + .NET пока далек от компонентного программирования, хотя приблизился к нему немного ближе чем многие другие языки и среды.
Ошибашся.
S_> Что такое КОП и компонента,
Он — компонет. Кого — компонента. Он не мужского рода.
S_> насколько я понял, нет однозначного определения.
компонет
S_>В C# компоненты в бинарном формате создавать, инкапсулировать и использовать можно, но этого недостаточно, должна быть возможность и средства производить с компонентами различные манипуляции . S_> Манипуляций довольно много, в которых реально возникает необходимость.
... S_>Необходимо создать компоненту B на базе A.
Это детали реализации которые к КОП отношения не имеют.
S_> На C# сейчас такое сделать принципиально невозможно, ... а зря.
Все на нем возможно. Было бы желание и умение.
... << RSDN@Home 1.1.4 beta 3 rev. 207>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Сергей Губанов, Вы писали:
СГ>Дело не в ортогональности. Разница между КОП и ООП в масштабе грануляции. ООП с классами — это микроуровень. КОП с компонентами — это макроуровень. Один КОП-компонент включает в себя несколько ООП — классов/интерфейсов объектов.
VD>Он — компонет. Кого — компонента. Он не мужского рода.
Если честно, запутался он это или она ... скорее всего оно.
...И вобще это оба варианта неправильные, правильно — component
VD>Это детали реализации которые к КОП отношения не имеют.
Вобще то меня ни ООП ни КОП практически не интересуют, интересны только конкретные фичи, которые потом обзывают разными словами ООП, КОП, АОП
S_>> На C# сейчас такое сделать принципиально невозможно, ... а зря. VD>Все на нем возможно. Было бы желание и умение.
Ну это то да конечно. Если бы оно было (желание и умение) то можно было бы все и на ассемблере писать. C# конечно далеко ушел от ассемблера, и даже c++, но есть еще куда развиваться.
Здравствуйте, Silver_s, Вы писали:
S_>Если честно, запутался он это или она ... скорее всего оно. S_> ...И вобще это оба варианта неправильные, правильно — component
Ну, ты уж определись, что тебя интересует.
S_>Ну это то да конечно. Если бы оно было (желание и умение) то можно было бы все и на ассемблере писать. C# конечно далеко ушел от ассемблера, и даже c++,
Вот именно.
S_> но есть еще куда развиваться.
Кто бы спорил... только причем тут это?
... << RSDN@Home 1.1.4 beta 3 rev. 207>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
AVK>Если есть объективные причины такого разнесения по сборкам (раздельная поставка, компоненты третьих фирм и т.п.) то вполне нормально.
Для разнесения на большое количество сборок есть и другие причины.
Главная из них это правильная декомпозиция и инкапсуляция для более крупных блоков кода чем класс. И пользование соответствующими фичами: internal types, раздельная компиляция, раздельные проекты в студии итд.
Можно конечно это все держать в уме и диаграммах, а код валить в кучу (разделив код на директории и неймспейсы), но это не то.
Для 30-50 тыс строк 10-15 раздельных проектов (и соответственно сборок) — это разве слишком много? Дык проблем будет гораздо больше если они не будут разделены.
Здравствуйте, AndrewVK, Вы писали:
AVK>Я тебе вот что скажу по опыту. В нашем проекте изначально был примерно такой подход. Когда количество проектов перевалило за 5 десяток, стало понятно что дальше так жить нельзя. В результате пришлось потратить довольно много усилий для склеивания проектов. Факторами, которые теперь влияют на разделение проектов, являются местоположение (сервер/клиент/дизайнер/утилиты/общее), конфигурация (у нас 2 варианта поставки), внешние компоненты, независимые универсальные фреймворки. В результате жить стало значительно легче.
И как это было интерпретировано? Как исправление ошибки, или как дальнейшее развитие.
Тут тоже не все так однозначно, есть приемущества при разбиении на большое количество компонет, есть и недостатки. На разных этапах проекта по разному. Эти все компоненты тоже ведь не одновременно появились. На некоторых этапах могут вобще существовать несколько вариантов определенных частей, с одной общей частью и необходимостью вносить изменения и в общую часть и в варианты. Здесь удобнее когда все разделено. Потом ближе к завершению реализации системы или подсистемы, удобнее уже объединять некторорые части.
Здравствуйте, Silver_s, Вы писали:
AVK>>Я тебе вот что скажу по опыту. В нашем проекте изначально был примерно такой подход. Когда количество проектов перевалило за 5 десяток, стало понятно что дальше так жить нельзя. В результате пришлось потратить довольно много усилий для склеивания проектов. Факторами, которые теперь влияют на разделение проектов, являются местоположение (сервер/клиент/дизайнер/утилиты/общее), конфигурация (у нас 2 варианта поставки), внешние компоненты, независимые универсальные фреймворки. В результате жить стало значительно легче.
S_>И как это было интерпретировано? Как исправление ошибки, или как дальнейшее развитие.
Здравствуйте, Silver_s, Вы писали:
S_>Как вобще умудрились позаимствовать из английского слово component, и сделать из него два разных. S_>А их ведь еще как-то по всем падежам склонять как-то надо
Компонента (в единственном) используется как специальный математический термин, т.е. в очень специализированной области знаний. Компонет — это общеупотребительный термин используемый в том числе и в программировании.
Таких (перегруженных) слов в русском (да и в английском) море.
... << RSDN@Home 1.1.4 beta 3 rev. 207>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.