Здравствуйте, Darth Jurassic, Вы писали:
DJ>Даже у persistent-классов бывают данные, которые не нужно читать
Это как? Пример можно?
DJ>, и уж тем более ни в коем случае не нужно туда что-то писать
Отсутсвие поддержки readonly свойств — это проблема конкретно BLToolkit, а не свидетельство правильности навешивания лдогики закрузки на entity-класс.
DJ>Что значит «переутяжеляют объекты»?
Значит назначать одному классу слишком большое количество сложных функций.
DJ> Есть бизнес-требования, и объекты приходится создавать в соответствии с этими бизнес-требованиями.
Если в твоих бизнес-требованиях к прикладному приложению упоминается слово класс — выкинь их в помойку.
DJ>В общем в моей практике приходилось дебагить работу с объектами, которые сами сохраняли себя в базу. Никаких проблемм с этим не возникало.
Твой гипотетический опыт никоим образом не может служить обоснованием в публичном разговоре — никому другому из здесь присутствующих подробности того опыта неизвестны.
DJ> Видимо мы по-разному смотрим на то, как в принципе положено организовывать логику в классах, и собственно я хотел поделиться своим взглядом на это в публицистической форме.
Пока что ты здесь ничем не поделился.
... <<RSDN@Home 1.2.0 alpha 4 rev. 1090 on Windows Vista 6.0.6001.65536>>
Здравствуйте, Darth Jurassic, Вы писали:
C>>Боян. DJ>Буду благодарен за ссылку.
Это похоже на подход в EJB BMP beans. Ну и Google про их недостатки.
C>>Аргумент простой: single responsibility principle. Т.е. класс данных не должен заниматься загрузкой себя из базы. DJ>Какие риски я преобретаю, нарушая этот принцип?
Про увеличение связности тут уже сказали.
Из конкретно недостатков такой технологии — непонятно как нормально делать работу с коллекциями. Неудобно делать lazy loading и т.д.
Здравствуйте, Darth Jurassic, Вы писали:
DJ>Собственно мне известно два способа загрузки данных из базы: научить классы, либо пользовать нечто вроде NHibernate. Я сам сторонник первого и думаю поделиться своими мыслями в виде статьи. Посему у меня два вопроса: DJ>1. Это боян?
Боян.
DJ>2. Приветствуются аргументы за и против.
Аргумент простой: single responsibility principle. Т.е. класс данных не должен заниматься загрузкой себя из базы.
Здравствуйте, Darth Jurassic, Вы писали:
S>>В общем, универсальных решений не существует. И перед тем, как изобретать новое универсальное решение, следует поинтересоваться судьбой прочих. Хотя бы для того, чтобы представлять, чем Ваше решение лучше подходит для решения вопросов вечности DJ>Это решение не универсально, просто оно автоматизирует много рутинной работы.
Все же почитайте LINQ to SQL, Entity Framework. Думаю, что именно эти технологии объясняют пониженный интерес к Вашей автоматизации рутиной работы. Хотя, они тоже, к сожалению, не универсальны.
Собственно мне известно два способа загрузки данных из базы: научить классы, либо пользовать нечто вроде NHibernate. Я сам сторонник первого и думаю поделиться своими мыслями в виде статьи. Посему у меня два вопроса:
1. Это боян?
2. Приветствуются аргументы за и против.
Здравствуйте, MozgC, Вы писали:
MC>А мне кажется вопрос автора не в том, делать ли методы загрузки в классе предметной области или не делать, а в том, использовать ORM или нет.
Собственно мне известно два способа загрузки данных из базы: научить классы, либо пользовать нечто вроде NHibernate. Я сам сторонник первого и думаю поделиться своими мыслями в виде статьи.
Мне лично кажется, что речь идёт о самопальной ORM.
Здравствуйте, Darth Jurassic, Вы писали:
AVK>>Если у тебя нет связи между этими частями кода — зачем их тащить тогда в один класс?
DJ>В том то и дело, что я не хочу тащить БД и бизнес-логику в один класс.
Мне уже надоело намекать, поэтому спрошу прямо — когда ты наконец опишешь то, что предлагаешь?
AVK>>А в чем тогда состоит твое предложение?
DJ>Предложение в том, чтобы вернуться к интерфейсам и фабрикам.
Непонятно.
DJ> Не знаю, как в других местах, но в .NET об этом начинают забывать, отдавая всё на откуп абстрактным классам.
Кто забывает?
DJ>Так вот, делается пачка интерфейсов (приблизительно по интерфейсу на каждый объектный тип даных).
Объектный тип данных в дотнете это класс. Каждому классу делаем интерфейс? Зачем?
DJ> Делаются фабрики, которые внутри работают с классами данных
Что такое класс данных?
DJ>Выданный интерфейс подхватывается уже объектом другого класса, отвечающим за бизнес-логику (имя паттерна забыл, но суть в том, что из сценария обратиться к объекту данных напрямую нельзя, надо использовать прокладку).
Совершенно стандартное решение, если я правильно тебя понял, называется паттерн абстрактная фабрика. Так что тебе не нравится?
... <<RSDN@Home 1.2.0 alpha 4 rev. 1090 on Windows Vista 6.0.6001.65536>>
Здравствуйте, Darth Jurassic, Вы писали:
DJ>Собственно мне известно два способа загрузки данных из базы: научить классы, либо пользовать нечто вроде NHibernate. Я сам сторонник первого и думаю поделиться своими мыслями в виде статьи. Посему у меня два вопроса: DJ>1. Это боян?
Здравствуйте, Darth Jurassic, Вы писали:
DJ>Собственно мне известно два способа загрузки данных из базы: научить классы, либо пользовать нечто вроде NHibernate. Я сам сторонник первого и думаю поделиться своими мыслями в виде статьи. Посему у меня два вопроса: DJ>1. Это боян? DJ>2. Приветствуются аргументы за и против.
Тему тогда надо было бы назвать типа "ORM: За и Против".
А вы сами аргументы приведите, за и против, тем более статью думаете написать, а тут уже ваши аргументы прокомментируют.
Здравствуйте, Cyberax, Вы писали:
DJ>>1. Это боян? C>Боян.
Буду благодарен за ссылку.
DJ>>2. Приветствуются аргументы за и против. C>Аргумент простой: single responsibility principle. Т.е. класс данных не должен заниматься загрузкой себя из базы.
Здравствуйте, Cyberax, Вы писали:
C>Здравствуйте, MozgC, Вы писали:
MC>>А мне кажется вопрос автора не в том, делать ли методы загрузки в классе предметной области или не делать, а в том, использовать ORM или нет.
C>Мне лично кажется, что речь идёт о самопальной ORM.
Использовать ORM или не вопроса не стоит — при программировании бизнес-процессов с использованием принципов объектно ориентированного программирования без него не обойтись. Другое дело, что сейчас очень популярно писать классы данных, а затем загружать в них посредством какого-нибудь NHibernate или BLToolkit данные из базы. Лично я считаю это неправильным, и поэтому решил делать иначе: каждый объект данных знает, как и откуда он загружен. При этом в отличие от NHibernate, который вынужден порождать наследника для хранения своих метаданных, в случае с применяемым у меня методом метаданные как раз лежат в самом классе. Это порождает некоторые архитектурные особенности, но по моему личному мнению итоговое решение получается удобнее.
Так вот я и думаю, что ведь не я же первый использую такой подход, наверняка в RSDN подобные статьи уже были. Может кто подскажет корни?
Здравствуйте, Darth Jurassic, Вы писали:
DJ>Использовать ORM или не вопроса не стоит — при программировании бизнес-процессов с использованием принципов объектно ориентированного программирования без него не обойтись. Другое дело, что сейчас очень популярно писать классы данных, а затем загружать в них посредством какого-нибудь NHibernate или BLToolkit данные из базы. Лично я считаю это неправильным, и поэтому решил делать иначе: каждый объект данных знает, как и откуда он загружен. При этом в отличие от NHibernate, который вынужден порождать наследника для хранения своих метаданных, в случае с применяемым у меня методом метаданные как раз лежат в самом классе. Это порождает некоторые архитектурные особенности, но по моему личному мнению итоговое решение получается удобнее.
Здравствуйте, AndrewVK, Вы писали:
AVK>Здравствуйте, Darth Jurassic, Вы писали:
DJ>>Какие риски я преобретаю, нарушая этот принцип?
AVK>Как обычно — высокая связность кода, как следствие сложность его отладки и дальнейшей эволюции.
Высокая связанность кода порождается не тем, что класс данных умеет сам себя сохранять, а тем, что функционал по работе с БД начинает мешаться с функционалом, реализующим бизнес-логику. Этот риск устраним, если отделить класс, освечающий за работу с БД, от класса, отвечающего за предоставления интерфейса бизнес-логики. При этом программировать предлагается только второе, так как класс данных в принципе обладает всей необходимой инфраструктурой.
Здравствуйте, AndrewVK, Вы писали:
AVK>Здравствуйте, Darth Jurassic, Вы писали:
DJ>>Какие риски я преобретаю, нарушая этот принцип?
AVK>Как обычно — высокая связность кода, как следствие сложность его отладки и дальнейшей эволюции.
Кстати сказать, для работы с NHibernate и BLToolkit тоже приходится создавать лишние свойства, или открывать свойства, которые не должны быть открыты.
Здравствуйте, Darth Jurassic, Вы писали:
DJ>Высокая связанность кода порождается не тем, что класс данных умеет сам себя сохранять
Именно тем и порождается.
DJ>, а тем, что функционал по работе с БД начинает мешаться с функционалом, реализующим бизнес-логику.
Если у тебя нет связи между этими частями кода — зачем их тащить тогда в один класс?
DJ> Этот риск устраним, если отделить класс, освечающий за работу с БД, от класса, отвечающего за предоставления интерфейса бизнес-логики.
А в чем тогда состоит твое предложение?
... <<RSDN@Home 1.2.0 alpha 4 rev. 1090 on Windows Vista 6.0.6001.65536>>
Здравствуйте, Darth Jurassic, Вы писали:
DJ>Кстати сказать, для работы с NHibernate и BLToolkit тоже приходится создавать лишние свойства, или открывать свойства, которые не должны быть открыты.
Это, опять же, потому что переутяжеляют объекты. Объект, в который мы грузим данные, не должен ничего, кроме хранения этих данных делать. А коль так — какие основания для того, чтобы закрывать какие то свойства?
... <<RSDN@Home 1.2.0 alpha 4 rev. 1090 on Windows Vista 6.0.6001.65536>>
Здравствуйте, AndrewVK, Вы писали:
AVK>Здравствуйте, Darth Jurassic, Вы писали:
DJ>>Кстати сказать, для работы с NHibernate и BLToolkit тоже приходится создавать лишние свойства, или открывать свойства, которые не должны быть открыты.
AVK>Это, опять же, потому что переутяжеляют объекты. Объект, в который мы грузим данные, не должен ничего, кроме хранения этих данных делать. А коль так — какие основания для того, чтобы закрывать какие то свойства?
Даже у persistent-классов бывают данные, которые не нужно читать, и уж тем более ни в коем случае не нужно туда что-то писать (эта претензия скорее в BLToolkit, нежели к NHibernate). Что значит «переутяжеляют объекты»? Есть бизнес-требования, и объекты приходится создавать в соответствии с этими бизнес-требованиями.
В общем в моей практике приходилось дебагить работу с объектами, которые сами сохраняли себя в базу. Никаких проблемм с этим не возникало. Видимо мы по-разному смотрим на то, как в принципе положено организовывать логику в классах, и собственно я хотел поделиться своим взглядом на это в публицистической форме.
Здравствуйте, AndrewVK, Вы писали:
DJ>>, а тем, что функционал по работе с БД начинает мешаться с функционалом, реализующим бизнес-логику.
AVK>Если у тебя нет связи между этими частями кода — зачем их тащить тогда в один класс?
В том то и дело, что я не хочу тащить БД и бизнес-логику в один класс. Тем более, что для объектов с одним и тем же бизнес-функционалом могут применяться совершенно разные типы БД — как реляционные, так хранилища с XML-интерфейсом.
DJ>> Этот риск устраним, если отделить класс, освечающий за работу с БД, от класса, отвечающего за предоставления интерфейса бизнес-логики.
AVK>А в чем тогда состоит твое предложение?
Предложение в том, чтобы вернуться к интерфейсам и фабрикам. Не знаю, как в других местах, но в .NET об этом начинают забывать, отдавая всё на откуп абстрактным классам.
Так вот, делается пачка интерфейсов (приблизительно по интерфейсу на каждый объектный тип даных). Делаются фабрики, которые внутри работают с классами данных, но наружу выдают только интерфейсы. Выданный интерфейс подхватывается уже объектом другого класса, отвечающим за бизнес-логику (имя паттерна забыл, но суть в том, что из сценария обратиться к объекту данных напрямую нельзя, надо использовать прокладку).
Здравствуйте, AndrewVK, Вы писали:
AVK>Мне уже надоело намекать, поэтому спрошу прямо — когда ты наконец опишешь то, что предлагаешь?
Сразу бы спросил прямо, чай не в прятки играем. А то уже с темы съехали.
Постановка задачи: есть функциональные требования. В требованиях описаны сценарии бизнес-логики. Из этих сценарием аналитик выделил объекты бизнес-логики. При этом есть замечание, что состав полей объектов может меняться со временем, кроме того объекты могут получаться из разных источников.
Метод состоит в том, чтобы описывать объекты в виде XML (что-то вроде UML-описания, только со своими особенностями), после чего наложением различных XSLT-шаблонов получать скрипты создания базы, исходники классов и интерфейсов DAL-уровня и заглушки для классов бизнес-уровня. Метод обкатан и готов к тому, чтобы им делиться.
Я видел местами применение XSLT для генерации исходников в других местах, эта идея не нова. Но возможно в таком приложении она упростит кому-то жизнь.
P.S. Кстати первая часть генерила классы именно для NHibernate, но в других решениях я предпочёл NHibernate не использовать.
Здравствуйте, Darth Jurassic, Вы писали:
DJ>Метод состоит в том, чтобы описывать объекты в виде XML (что-то вроде UML-описания, только со своими особенностями), после чего наложением различных XSLT-шаблонов получать скрипты создания базы, исходники классов и интерфейсов DAL-уровня и заглушки для классов бизнес-уровня. Метод обкатан и готов к тому, чтобы им делиться.
Метод этот называется DSL — Domain Specific Language. Про него масса чего написана и есть море инструметов. Те же новые DSL Tools от Microsoft. А XSLT там или TT, дело десятое. И с ORM это пересекается слабо. Как и с SRP. Разный уровень.
... <<RSDN@Home 1.2.0 alpha 4 rev. 1090 on Windows Vista 6.0.6001.65536>>
Здравствуйте, Darth Jurassic, Вы писали:
DJ>Метод состоит в том, чтобы описывать объекты в виде XML (что-то вроде UML-описания, только со своими особенностями), после чего наложением различных XSLT-шаблонов получать скрипты создания базы, исходники классов и интерфейсов DAL-уровня и заглушки для классов бизнес-уровня. Метод обкатан и готов к тому, чтобы им делиться.
Проект на котором обкатывался этот метод уже завершен? (праздный интерес)
Дело в том, что наверняка вся кодогенерация заточена под специфичные требования проекта и может быть применена только для проектов со схожими требованиями. Кроме того, когда речь зайдет об гранулировании обращений к БД, более-менее сложных запросах, lazy load и прочей оптимизации, то скорее всего, метод придется выкинуть.
В общем, универсальных решений не существует. И перед тем, как изобретать новое универсальное решение, следует поинтересоваться судьбой прочих. Хотя бы для того, чтобы представлять, чем Ваше решение лучше подходит для решения вопросов вечности
Здравствуйте, Darth Jurassic, Вы писали:
DJ>>>2. Приветствуются аргументы за и против. C>>Аргумент простой: single responsibility principle. Т.е. класс данных не должен заниматься загрузкой себя из базы.
DJ>Какие риски я преобретаю, нарушая этот принцип?
Сложность тестирования, в частности, при написании юнит тестов.
Здравствуйте, samius, Вы писали:
S>Проект на котором обкатывался этот метод уже завершен? (праздный интерес)
Два проекта завершены, два в процессе разработки.
S>Дело в том, что наверняка вся кодогенерация заточена под специфичные требования проекта и может быть применена только для проектов со схожими требованиями. Кроме того, когда речь зайдет об гранулировании обращений к БД, более-менее сложных запросах, lazy load и прочей оптимизации, то скорее всего, метод придется выкинуть.
Шаболоны приходилось дорабатывать для полного соответствия, так что ещё есть куда развиваться. В частности приходилось делать динамическую загрузку и выгрузку объектов. Но сейчас реюзабилити процентов 90. Хотя минус есть: для остальных 10% надо знать XSLT.
S>В общем, универсальных решений не существует. И перед тем, как изобретать новое универсальное решение, следует поинтересоваться судьбой прочих. Хотя бы для того, чтобы представлять, чем Ваше решение лучше подходит для решения вопросов вечности
Это решение не универсально, просто оно автоматизирует много рутинной работы.
Всем спасибо, много полезных советов. Отднльное спасибо за ссылку на LINQ to SQL и отдельнейшее спасибо за EJB Entity Beans with BMP Architecture — это действительно близко к тому, о чём собираюсь писать.
В общем, начинаю работать. Если будут ещё какие-то замечания/уточнения — милости просим.