Domain-Driven Design: Продажа идеи

12 марта 2012 г.

Несколько месяцев назад я консультировал IT-компанию. Компания разработала проект для завода и хотела сделать из проекта тиражируемый продукт на другие предприятия в этой отрасли. После получения второго заказа они столкнулись со сложностью внесения изменений и настройки проекта. Это не позволяло им легко сделать второе внедрение, не говоря уже про постановку таких внедрений на поток.

Я поговорил с руководством компании и всеми заинтересованными лицами, провел анализ кода и выявил ряд проблем, которые мешали сделать переход к тиражируемому продукту.

Одним из серьезных препятствий оказалось то, что 90% бизнес-логики было написано на хранимых процедурах, остальная часть написана на .NET/C#. Ситуация осложнялась тем, что первая версия проекта была реализована и внедрена на Oracle, а второй заказчик настаивал на MSSQL.

Подход к продаже идеи

Понятно, что если бы я пришел к руководству компании, программистам и специалистам по БД и показал куда и как двигаться, то это не принесло бы желаемого результата. Поэтому для "продажи" идеи я использовал стандартный подход, обратите внимание на последовательность:

  1. Выявление проблемы (потребности)
  2. Выявление последствий проблемы
  3. Предложить решение, обсудить его выгоды
  4. Рассмотреть опасения
  5. Установить безопасное окружение для пилотирования
  6. Profit

Шаг 1. Выявление проблемы

У разработчиков были мысли, что бизнес-логику нужно выносить из БД, но куда и как они не знали. Плюс нужно было как-то обосновать для начальства время на рефакторинг и создание нового прототипа. Кроме того, в компании работал очень сильный администратор БД. Он оппонировал всем, кто хотел убрать бизнес-логику из БД и ни в какую не соглашался на смену архитектуры. Основным аргументом был вопрос о потере производительности.

В системе можно было выделить 3 компонента переплетенных между собой:

  1. Работа с пользовательским интерфейсом - UI
  2. Обработка данных - DB
  3. Набор множества объектов типа *Helper, *Manager, *Wrapper и т.п.

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

Посмотрите на один из самых простых примеров кода из блока UI:

 public EditGoodForm(DataRow dr)
 {
            InitializeComponent();
            connection = new SqlConnection(MainSQLConnection.Connection.ConnectionString);
            connection.Open();

            comboBoxType.DataSource = Populate("SELECT distinct id, Name FROM dbo.HB_GoodsType");
            comboBoxType.ValueMember = "ID";
            comboBoxType.DisplayMember = "Name";

            textBoxName.Text = _dr.Field<string>("Name");
            textBoxTolerance.Text = dr.Field<decimal?>("Tolerance")!=null?dr.Field<decimal?>("Tolerance").ToString():string.Format("{0:F}",0);
            comboBoxType.SelectedValue = _dr.Field<int>("HB_GoodsType_ID");
            comboBoxUnit.SelectedValue=_dr.Field<int>("HB_Unit_ID");
            comboBoxRouteMap.SelectedValue = _dr.Field<int>("HB_RouteMap_ID");
            checkBoxSkladUchet.Checked = _dr.Field<bool>("IsStoreMove");
 }
Вот вырезка из типичной хранимой процедуры:
--Получаем инфу по рецепту
SELECT @IsProduction=IsProduction,@Workcenter_ID = MF_WorkCenter_ID,@Good_ID = HB_Goods_ID,@RecipeOutcome=ProductionOutcome,@RecipeDateTimeShift=MinimalTime,@SingleObject = SingleObject,@MinimalObjectWeight = MinimalObjectWeightPercent * ProductionOutcome / 100,@NotPerformTechnicalReglament=NotPerformTechnicalReglament FROM MF_Recipe WHERE id = @IterationRecipeID

IF @SingleObject IS NULL SET @SingleObject = 1

SET @ObjectTime = DATEADD(hh,-@RecipeDateTimeShift,@TaskDateTime) --@TaskDateTime - @RecipeDateTimeShift

IF @RecipeOutcome = 0
SELECT @RecipeOutcome = SUM(Income) FROM MF_RecipeRow WHERE MF_Recipe_ID = @IterationRecipeID
--SET @Rule = 0
DECLARE @ObjectsOutput AS TABLE
(
ID INT,
ObjectOutcome DECIMAL(30,10),
RecipeMultipler DECIMAL(30,10),
AlredyExists BIT
)

-- --Фикитивная запись, для нумерации
INSERT @ObjectsOutput (ID, ObjectOutcome ,RecipeMultipler)
VALUES (0 ,0,0)

IF (dbo.F_MF_GetAuthorWorkcenter(@Workcenter_ID)=-1)
BEGIN
SET @Error = 'Для рабочего центра с ИД '+CAST(@Workcenter_ID AS VARCHAR(10))+' не найден родительский РЦ'
RAISERROR(@Error,12,1)
RETURN
END

Про Helper'ы и Wrapper'ы нечего говорить, потому что они представляют собой просто кучу статических объектов переплетённых между собой.

Ну и где же описана бизнес-логика? От ответа на этот вопрос зависит куда мы пойдем, когда требования заказчика изменятся.

Перечисляем проблемы

Пока я листал код на проекторе кто-то узнавал свой код и начинал оправдываться, кто-то смеялся и говорил, что даже трогать это боится. Менеджер проекта и IT-директор, сидевшие вместе с нами, впервые услышали реальное отношение разработчиков коду.

Итак, после обсуждения все вместе выявили ряд самых острых проблем:

  • Дублирование в C# коде
  • Дублирование в SQL-коде
  • Дублирование между C# и SQL-кодом
  • Бизнес-логика во всех слоях приложения
  • Нет разделения ответственности между классами и слоями приложения
  • В целом множество технических долгов

Как следствие из вышеперечисленного:

  • Трудно внести изменения и ничего не сломать
  • Трудно искать причины багов
  • Трудно гарантировать, что баг снова не выскочит
  • Рефакторинг значительно усложнен. Невозможно без опасения рефакторить SQL-код
  • Отсутствие модульных тестов: в C# коде сильная связанность и зависимость от внешних ресурсов, а на хранимые процедуры сложно писать модульные тесты

Отсутствие модульных тестов, которые можно запускать автоматически, приводило к ручному тестированию всей системы после каждого изменения. А чаще каждый релиз просто отдавали в «боевое» тестирование пользователям, чем последние были крайне не довольны.

Шаг 2. Выявление последствий проблемы

Последствия были для всех очевидны, оставалось только выписать их по пунктам:

  • Низкая скорость разработки
  • Непредсказуемые баги
  • Отсутствие Definition of Done
  • Невозможность быстро реагировать на изменения требуемые заказчику
  • Незаменимость разработчиков
  • Сложность создания универсального решения
  • По факту нет коробочной версии, а это значит, что нет потока денег для компании

Такое положение вещей никак не устраивало руководство компании.

Шаг 3. Предложить решение

Мое предложение строилось на внедрении Domain Driven Design и создании прототипа с новой архитектурой. Мы подробно разобрали следующие темы:

  • Создание домена и обход основных ошибок при использовании DDD
  • Aggregation Root
  • Работа с данными: Repository, Unit of Work и Persistence Ignorance
  • Прямо во время обсуждение рождалось море идей по тому, как можно просто и красиво реализовать задачи проекта, как изменить архитектуру системы, как реализовать работу с БД. Вдохновение витало в воздухе, появлялись конструктивные споры.

    Шаг 4. Рассмотреть опасения

    Одно дело признать проблемы, узнать про новые возможности, совсем другое принять решение о начале изменений. Важным шагом является совместный расчет рисков и опасений связанных с грядущими изменениями:

    • Если мы внесем изменения в систему, как это повлияет на уже работающую версию?
    • Не упадет ли скорость работы, когда бизнес-логика перейдет из БД в .NET?
    • В проекте есть работа с датчиками, датчики сидят на общей шине, которая настроена писать данные напрямую в БД. Можно ли будет перенастроить систему на отсылку сообщений в .NET?
    • После перехода к новой архитектуре смогут ли все разработчики в ней разобраться?
    • Начнется ли сопротивление со стороны администратора БД из-за потери своего влияния в компании? Если да, то как это можно будет смягчить?

    Теперь осталось выбрать путь, по которому изменения пройдут с наименьшими рисками, а значит и без сопротивления.

    Шаг 5. Установить безопасное окружение для пилотирования

    Мы совместно с IT-директором компании выделили двух программистов, которые очень активно хотели уйти от бизнес-логики из БД. Они пообещали в течение месяца сделать прототип системы, исходя из новой для них парадигмы - Domain Driven Desing. Эти программисты пообещали, что больше никогда не предложат подобный рефакторинг, если идея с переходом на DDD окажется для их проекта не жизнеспособной.

    Шаг 6. Profit

    Меньше, чем за месяц программисты вынесли всю бизнес-логику из БД, написали на нее модульные тесты, сделали эмулятор железок и протестировали систему на быстродействие. Сейчас система готовится к выходу на новый объект для внедрения. К слову, первая версия системы делалась несколько лет целой командой.

    Выводы

    Я надеюсь, что эта история вдохновит многих разработчиков, которые находятся в заложниках обстоятельств. Знайте, что у вас почти всегда есть шанс донести новые идеи и воплотить их в жизнь. Чтобы понять как это сделать, посмотрите на причины возникновения проблем в компании и обстоятельства, за счет которых их удастся решить.

    Какие я вижу предпосылки к появлению проблем в описанной компании:

    • Бизнес-логика исторически была в хранимых процедурах, вызывала проблемы, но никто не решался это изменить
    • Новые проекты писали по-старинке и бились об те же грабли снова и снова
    • Команда очень мало общалась, проблемы редко выносились на обсуждение
    • Авторитет в виде сильного администратора БД, с которым никто не хотел связываться
    • Программисты, которые были за хорошие идеи не знали как "продать" их без внешней помощи

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

    • Руководство компании было действительно заинтересовано в скорейших результатах
    • Мне удалось показать связь между хорошим кодом, тестами и прибылью для компании
    • Продажа идеи шла по шагам без спешки, без рассказа про серебряные пули
    • В компании мы нашли энтузиастов, которые взяли на себя ответственность по созданию прототипа

    Ссылки

    Видео с AgileDays 2010 - Как продать Agile заказчику, Асхат Уразбаев

    Книга СПИН-продаж, Нил Рекхэм

    Взаимоотношения или споры в команде, группа DotNetConf

    30 комментариев:

    1. т.е всю бизнес-логику(БЛ) реализованную в ХП убрали? Судя по коду ХП - задача связана с выпиской рецептов? Интересуюсь с тем, что в новом проекте большую часть БЛ реализована в виде ХП, CLR объектов и SSIS пакетов и почему вы так против такой реализации? Единственный большой минус который я вижу в том что очень тяжело тестировать.

      ОтветитьУдалить
    2. Все проблемы перечислены на Шаге 1, последствия кода бизнес-логики в БД перечислены на Шаге 2.

      Тяжело тестировать и тяжело рефакторить - даже этих двух пунктов хватит, чтобы задуматься, а стоит ли писать бизнес-логику в БД? Прибавьте возможные проблемы с переходом на другую СУБД.

      ОтветитьУдалить
    3. @19b9f5144365ca0586c0850541938296  нет единственно верного подхода. В Вашей ситуации описанный Вами подход вполне может работать и быть более производительным чем DDD.

      Использование модели требует моделирования, понимания предметной области, создание правильных абстракций, глубоких знаний ООП, умения использовать шаблон многослойной архитектуры и т.д. В некотором смысле модель DDD это инструмент, а не решение.

      ОтветитьУдалить
    4. А как же потеря производительности при пакетной обработке? Тем боле не приходиться думать про многие вещи.
      >Незаменимость разработчиков
      Такого вроде не может быть :-) Если все очень хорошо задокументировано то с этим проблем не должно быть.

      ОтветитьУдалить
    5. Будет *очень* наглядно и полезно, если вы напишите некое приложение с бизнес-логикой, хранением данных, UI, и прочими реальными ситуациями из production'a с нуля и до конца. Пусть оно будет небольшим, но по одному реализованному примеру. При этом, с применениями всех практик, которые вы описываете - TDD, DDD, разделение на слои, лучшие практики, БД, и т.д. 

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

      ОтветитьУдалить
    6. Все верно. Но, на мой взгляд, не правильное позиционирование, что DDD ускорило процесс разработки, все таки первую версию системы делали несколько лет не только из-за технологии процесса программирования, а еще из-за неопределенного ТЗ и новой предметной области. А программисты "меньше чем за месяц" переписали только алгоритмы работы, а не всю системы целиком (алгоритмы, интерфейсы, документация и т.п.)

      ОтветитьУдалить
    7. > А как же потеря производительности при пакетной обработке?

      Потеря производительности зависит от требований к производительности. Ваше приложение должно быть ну очень сильно нагружено, чтобы вам не хватило обычной ORM и кэша.
      > Такого вроде не может быть :-)
      По факту такое есть. Когда хранимые процедуры занимают по 50-100 строк, то обычно есть человек, без которого в эти процедуры лучше не лазить. 

      ОтветитьУдалить
    8. Да, хорошая идея, на которую у меня конечно не было времени, пока я не согласился участвовать в SkillTrek. Там мы как раз 4 месяца будем заниматься созданием такого приложения. На счет того будут выложены исходники или нет, пока сказать не могу.

      ОтветитьУдалить
    9. К сожалению, в этом тренинге я принять участие не смогу. Если у вас будет возможность поделиться исходным кодом, будет замечательно.

      ОтветитьУдалить
    10. Тем не менее процесс разработки на самом деле стал быстрее и стабильнее. Понятно, что переписывали готовую систему и уже были хорошие знания предметной области, это всё дало фору. Тем не менее, правильный подход к проектированию сыграл значительную роль.

      ОтветитьУдалить
    11. Я обязательно уточню у компании SkillTrek будем ли мы выкладывать исходный код или нет. Если будет, то он 100% появится в этом блоге :)

      ОтветитьУдалить
    12. Да проблема тестирования ХП есть но это техническая проблема.  А вот замена ХП и обработки целосности со стороны базы и перекладывание на плечи ORM и кеша влечет за собой полную замену архитетуры приложения и перевода на совершенно новый уровень.

      Я как раз делал обратное для решения проблем с производительностью и маштабированостью.  Особенно "красиво" выглядел ORM на Azure при наггузочном тестировании.  Так красиво что пришлось его вырезать всюду где был и больше не возвращатся.Незная оригинальных условий эксплуатации и развертывания данного приложения а также требований говорить о DDD или ORM как панацея я бы не стал.А то, "смешались в кучу кони, люди" то тут TDD и DDD мало помогут так как подразумевают не просто использование паттернов а необходимо "правильное" использование патернов о чем многие часто забывают.Я на своем опыте убедился что патерны и их правильно применение это две больших разницы.

      ОтветитьУдалить
    13. Да, к сожалению, каждый понимает их по-своему неправильно :) Ну и от кривых рук не спасет хорошая ORM и кэш.

      > Незная оригинальных условий эксплуатации и развертывания данного приложения а также требований говорить о DDD или ORM как панацея я бы не стал

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

      ОтветитьУдалить
    14. Павел Колодин22 марта 2012 г. в 14:39

      Тем не менее, тем не менее. А читатели блога всё равно читают "меньше чем за месяц". Будут ли исправления?

      ОтветитьУдалить
    15. Зачем исправления, если программисты в этой компании НА САМОМ ДЕЛЕ меньше, чем за месяц вынесли всю бизнес-логику из БД, написали на нее модульные тесты, сделали эмулятор железок и протестировали систему на быстродействие. Это факт, и это произошло меньше чем за месяц.

      ОтветитьУдалить
    16. >А то, "смешались в кучу кони, люди" то тут TDD и DDD мало помогут так как подразумевают не просто использование паттернов а необходимо "правильное" использование патернов о чем многие часто забывают

      Забавная кстати мысль.
      Я часто слышу предупреждения о неправильном использовании паттернов. Даже в книжках по проектированию это иногда пишут, особенно в старых.

      Но прикол в том, что я ниразу в своей практике не встречал что бы наличие паттернов было хуже их отсутствия.

      Серьёзно!

      Да может быть  кто-то сделал синглтоном объект который не обязан был быть им. Но это же лучше чем делать глобальный объект!
      Кто-то неумело сделал фабрику, но это лучше чем отсутствие фабрики!

      Да и в ORM и DDD - если есть проблемы в производительности, то всегда можно внести изменения и легко разменять гибкость на производительность. Но производительность на гибкость разменять трудно, долго и дорого. А порой и невозможно.

      Да и в вашем примере, я на 80% уверен, что выигрышь который вы получили в производительности он фейковый. Те деньги которые вы теперь тратите на поддержку этого кода и разработку, могли бы влёгкую окупить более мощный хостинг.

      ОтветитьУдалить
    17. Не подскажете, если не сложно, опыта у меня нет куда копать не нашел. 

      Есть в нашей компании программа работают люди на нем уже лет 6-7. "Сопровождаю" его я , и это ад. Так как , Бизнес-Логика разрознена по всей программе, она есть в хранимых процедурах, в GUI приложение(самое больше количество) , в отдельных классах(кто то видимо пытался вынести). Ко всему этому добавляется Огромное количество дублирования кода, как в хранимках так и в коде.Сейчас в отпуске, решил посде выхода разговаривать с начальством о полной переписи, или попытатся рефакторинги проводить, т.к. невозможно сопроводать продукт, любое изменения приводит к такому количество нецензурной брани, и занимает продолжительный период времени. К сути проблемы, ТЗ не осталось, людей способных обяснить все бизнес процесы нет, программистов которые писали сее чудо нет. что затрудняет переписывать весь продукт. Есть вариант рефакторига, ну тут проблема что без TDD опасно это проводить. Тесты создать на логику которая полностью засела в GUI для меня не реально сложно , да и вообще это возможно? Не встечалась ли вам такая проблема? Что думаете по этому поводу как быть? PS  Извиняюсь за навязывания, просто не к кому обратиться за информацие. Любой полезной ссылкой, советом буду благодарен. Заранее спасибо.PPS извиняюсь за мою орфографию и пунктуацию.

      ОтветитьУдалить
    18. Не подскажете, если не сложно, опыта у меня нет куда копать не нашел. 
      Есть в нашей компании программа работают люди на нем уже лет 6-7. "Сопровождаю" его я , и это ад. Так как , Бизнес-Логика разрознена по всей программе, она есть в хранимых процедурах, в GUI приложение(самое больше количество) , в отдельных классах(кто то видимо пытался вынести). Ко всему этому добавляется Огромное количество дублирования кода, как в хранимках так и в коде.Сейчас в отпуске, решил посде выхода разговаривать с начальством о полной переписи, или попытатся рефакторинги проводить, т.к. невозможно сопроводать продукт, любое изменения приводит к такому количество нецензурной брани, и занимает продолжительный период времени. К сути проблемы, ТЗ не осталось, людей способных обяснить все бизнес процесы нет, программистов которые писали сее чудо нет. что затрудняет переписывать весь продукт. Есть вариант рефакторига, ну тут проблема что без TDD опасно это проводить. Тесты создать на логику которая полностью засела в GUI для меня не реально сложно , да и вообще это возможно? Не встечалась ли вам такая проблема? Что думаете по этому поводу как быть? PS  Извиняюсь за навязывания, просто не к кому обратиться за информацие. Любой полезной ссылкой, советом буду благодарен. Заранее спасибо.PPS извиняюсь за мою орфографию и пунктуацию.

      ОтветитьУдалить
    19. Есть классическая книга на этот счёт, очень советую Michael Feathers' Working Effectively with Legacy Code

      ОтветитьУдалить
    20.  Кроме книжки у меня было два опыта работы с legacy code.

      В первом случаей у меня была программа обработки радиосигналов, её писали несколько человек которые потом поспешно уволились =). Писали 2-3 года, мне следовало внести некоторые изменения, которые бы сделали программу более гибкой. В программе было около 10-15 тыс. строчек. сишного кода.

      Я использовал следующий подход.
      1. Я очертил функциональносьт которую я скорее всего затрону.
      2. Всю эту функциональность которую я хотел изменить из неООП кода я вынес в ООП-шный слой.
      3. Всё к чему я прикасался я выносил в ООП код и покрывал тестами.

      В итоге проект успешно был провален за 2 месяца. Причина - оказалось что реальное положение дел в программе несколько отличается от того что думал заказчик. И мой код он просто оголил все те проблемы которые крылись за многочисленными багами. Это был полный фейл с руганью и взаимными упрёками.

      Второй раз, у меня был исходный код программы терминала оплаты, там было около 10 тыс. строк, писали его 1.5 года. Я поступил по-другому.

      Составил на основе исходного кода и пользовательского интерфейса требования, затем разработал архитектуру, сделал тесты под эту архитектуру.
      Затем придерживался следующих правил:
      1. Ответсвенные участки писал заново
      2. Неответсвенные брал из legacy code инкапсюлировал под новую архитектуру

      Этот проект мне тоже не получилось довести до конца, но команда которая потом вела этот проект успешно его завершила. Я считаю это двойной успех, т.к. сделать архитектуру которую удалось реализовать уже другим людям это намного сложнее чем закончить самому. В проекте я был 2 месяца, и ещё 5 месяца писали без меня люди которых я же сам и обучал программированию=). Итого 7 месяцев. Я потом смотрел код, прибавилось много в реализации, но классы остались теми что и при проектировании. Т.е. архитектура была сохранена. Это был большой успех, приложение в данный момент находится в коммерческом использовании.

      Везде речь идёт о c++.

      ОтветитьУдалить
    21. Интересные истории), учту на заметку способы.  Спасибо за книжку. как раз закончил книгу 
      Refactoring: Improving the Design of Existing Code, думаю будет достойное продолжение основам рефакторинга

      ОтветитьУдалить
    22. Есть программы, которые никогда не будут написаны хорошо. Это просто их судьба.

      ОтветитьУдалить
    23. Да тут проблема то в другом. То что поддержкой занимаюсь я. и все поддержка идет с черепашей скоростью.  

      ОтветитьУдалить
    24. http://code.google.com/p/ndddsample/ или http://dddsamplenet.codeplex.com/ на C# или http://dddsample.sourceforge.net/download.html на Java -- примеры из книги Эванса.

      ОтветитьУдалить
    25. Плохого в этом ничего, но возникают несколько проблем:

      1. SQL-код сложно рефакторить. Нет инструментов, которые хотя бы приближаются к работе с C# кодом в VS+R#

      2. Сложно тестировать, фактически невозможно писать модульные тесты

      3. Дублирование логики в SQL и C# коде, если писать бизнес-логику и там и там.

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

      "Оттуда узнать как напрямую конектися в БД"

      Вообще не обязательно указывать строку подключения к БД в клиентском коде. Можно сделать, чтобы код взаимодействовал с БД через веб-сервисы.

      Если сильно нужно строку подключения указывать прямо в клиентском коде, то можно сделать шифрованную секцию в файле конфигурации.



      Опять же, вот у вас есть клиентское приложение и БД, в которой хранимые процедуры. Как это схема обеспечивает безопасность?

      ОтветитьУдалить
    26. "Если сильно нужно строку подключения указывать прямо в клиентском коде, то можно сделать шифрованную секцию в файле конфигурации."

      Но эта шифрованная секция как то расшифровывается приложением? Так же ведь?! А раз так, то и мы можем расшифровать ее (как я уже говорил ILSpy, Reflector рулят).

      "Опять же, вот у вас есть клиентское приложение и БД, в которой хранимые процедуры. Как это схема обеспечивает безопасность?"

      Каждый пользователь приложения коннектится к БД используя своего sql-пользователя (пользователя созданного MSSQL сервером). Каждому пользователю назначены определенные sql-роли. Доступ на запуск хранимых процедур осуществляется как раз с помощью этих sql-ролей (то есть используется модель безопасности sql-сервера).
      То есть, если пользователь даже законнектится напрямую под своим sql-пользователем, то он не сможет запустить ни одной комманды, ни одной хранимой процедуры которая не предусмотрена его sql-ролями. Все хранимые процедуры создаются зашифрованными с помощью WITH ENCRYPTION (которые все же можно расшифровать, но только имея доступ на уровне sa).

      На мое мнение, единственный разумный вариант - это использование какой-то прослойки между sql-сервером и клиентским приложением. В веб приложениях такой прослойкой есть веб сервер. Но web мне не подходит.

      "Можно сделать, чтобы код взаимодействовал с БД через веб-сервисы."

      Это наверное единственный разумный вариант который мне, почему то никто до Вас не предлагал :) (хотя идея использования допольнительного сервера мне как то не очень). Сам я об этом и не задумывался, так как нигде не встречал ни одного примера такой архитектуры. К сожалению у меня не очень много опыта в этой сфере. Да и нарыть стоящего материала по этому делу так же трудно.

      ОтветитьУдалить
    27. На счет ограничения прав, можно в клиентском коде указать того же пользователя с ограниченными правами. Если вы будете использовать ORM, то он будет подключаться с такими же ограниченными правами.

      На счет сервисов советую для начала полистать:

      http://www.soapatterns.org/

      и прочитать http://www.manning.com/rotem/

      ОтветитьУдалить
    28. "На счет ограничения прав, можно в клиентском коде указать того же пользователя с ограниченными правами. Если вы будете использовать ORM, то он будет подключаться с такими же ограниченными правами."

      Написав такое, я думаю что наверное Вы меня не поняли. Потому что именно так у меня все и организовано. Только вот строка подключения генерится автоматически на основании выбраного пользователя (из combobox-a) и его пароля. А на счет ORM, то так оно то так, но хранимые процедуры от этого никуда не поденеш. ORM как известно в основном генерит sql-код динамически а не работает с хранимыми процедурами. Ведь функция ORM состоит как раз в том чтобы скрыть от програмиста непосредственную работу с БД.

      Спасибо за ссылки. Почитаю на досуге.

      И да, еще на счет этого:

      "SQL-код сложно рефакторить. Нет инструментов, которые хотя бы приближаются к работе с C# кодом в VS+R#"

      Вы наверное ничего не слышали о новом типе проекта в Visual Studio 2010. Называется "Sql Server xxxx Database Project". Поддержывает intellisence, переименование всех обьектов, ошибки на стадии компиляции, deploy на сервер и многое другое. Короче говоря, писать sql-код намного проще. Информации в сети крайне мало, но если с ним разобратся то это принесет очень много пользы.

      ОтветитьУдалить
    29. Дмитрий Мартовой12 августа 2014 г. в 19:50

      Алгебра любого ОРМ априори меньше алгебры нативного SQL конкретной платформы. Это значит что найдется такая выборка (запрос), осуществить который средствами ОРМ будет невозможно при сравнимой производительности с нативным SQL.


      Из вышеуказанного вытекает, что строгий отказ от нативного SQL в сторону более высокоуровневого инструмента должен быть обоснован гораздо сильнее, чем, даже, при обратном переходе.

      p.s. Лично неоднократно встречал куски EF 5.0 кода (запрос), который при попытке добавить ещё одну таблицу в один из внутренних join выдавал мне сообщение о том, что запрос слишком сложен и не может быть исполнен...

      ОтветитьУдалить
    30. Александр,

      > ORM как известно в основном генерит sql-код динамически а не работает с хранимыми процедурами

      ORM и с хранимыми процедурами может работать и результаты SQL кода маппить в объекты.

      > Вы наверное ничего не слышали о новом типе проекта в Visual Studio 2010

      Слышали и даже пользуемся :) Всё-равно с мощностью рефакторинга C# кода это не сравнить.

      Посмотрите обновленные мысли по поводу применимости ORM и переход на легковесные мапперы http://blog.byndyu.ru/2013/03/dapper-queryobject-orm.html

      ОтветитьУдалить

    Моя книга «Антихрупкость в IT»

    Как достигать результатов в IT-проектах в условиях неопределённости. Подробнее...