Инициализация соединения с внешней БД
От: zelenprog  
Дата: 05.10.23 14:33
Оценка:
Пробую сделать небольшая программу с разделением слоев по правилам DDD.
Эта программа выполняет конвертацию каталога товаров из нескольких старых баз данных в новую базу.

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

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

Форма ведь не должна напрямую "видеть" Репозиторий. Значит, форма не может в него передать имя файла.
А как тогда выполнить инициализацию Репозитория? Какой слой\объект отвечает за инициализацию источника данных?

Объясните плиз.
Re: Инициализация соединения с внешней БД
От: Qulac Россия  
Дата: 05.10.23 16:25
Оценка: 2 (1) +1
Здравствуйте, zelenprog, Вы писали:


Z>Пробую сделать небольшая программу с разделением слоев по правилам DDD.

Z>Эта программа выполняет конвертацию каталога товаров из нескольких старых баз данных в новую базу.

Z>Чтение старых товаров сделано в программе с помощью класса что-то типа Репозитория.

Z>Этот класс используется в слое Бизнес-логики.
Z>Источником данных для этого Репозитория является внешний файл переноса, в который были выгружены товары из старой базы.

Z>Имя файла переноса задается в пользовательской Форме программы.

Z>Как "прокинуть" имя этого файла в Репозиторий, чтобы он знал откуда читать данные?

Z>Форма ведь не должна напрямую "видеть" Репозиторий. Значит, форма не может в него передать имя файла.

Z>А как тогда выполнить инициализацию Репозитория? Какой слой\объект отвечает за инициализацию источника данных?

Z>Объясните плиз.


Как то делал программу где параметры подключения к бд задавались в интерфейсе. В домен добавил класс который создавал репозиторий по параметрам, этакий репозиторий репозиториев.
Программа – это мысли спрессованные в код
Re: Инициализация соединения с внешней БД
От: DiPaolo Россия  
Дата: 05.10.23 16:43
Оценка:
Инфраструктурный слой. Некий DatabaseContext. Я так понимаю, вы на C#. Наверное, что-то типа DbContext.OnConfiguring (https://learn.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.dbcontext.onconfiguring?view=efcore-7.0).

Вот тут есть пример https://www.entityframeworktutorial.net/efcore/entity-framework-core-dbcontext.aspx.

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

Кстати, если я правильно понял, в вашем случае можно рассматривать путь к файлу БД как сущность домена, то есть Entity. И хранить соответственно.

Ну а вообще можно не усложнять и сделать сильно проще без этих всех заморочек Возможно вы выбрали не самый подходящий для оттачивания навыков работы с DDD пример.
Патриот здравого смысла
Re: Инициализация соединения с внешней БД
От: RushDevion Россия  
Дата: 05.10.23 19:12
Оценка: 1 (1)
Z>Объясните плиз.

Можно так:

// Интерфейсы + реализация (обычно, но не обязательно, в отдельной сборке)
interface IRepository { ... }

interface IRepositoryFactory {
   IRepository Create(string fileName);
}

// Форма
class MainForm {
  // ...
  
  public MainForm(IRepositoryFactory repoFactory) => _repoFactory = repoFactory;
 
  private void MainForm_ImportButtonClicked(...) {
    var path = _txtFilePath.Text;
    var repo = _repoFactory.Create(path);
    // TODO: логика твоего импорта
  }
}

// Точка сборки, aka composition root (обычно где-то в Program.cs)
var repoFactory = new RepositoryFactory();
var mainForm = new MainForm(repoFactory);
Application.Run(mainForm);
Re: Инициализация соединения с внешней БД
От: Разраб  
Дата: 06.10.23 00:20
Оценка:
Здравствуйте, zelenprog, Вы писали:

Z>Форма ведь не должна напрямую "видеть" Репозиторий. Значит, форма не может в него передать имя файла.


Любая программа выполняется последовательно.
Чтобы это понять достаточно поиграть с нужным ЯП типа F#.
Его фича однопроходность. Т.е. чтобы что-то использовать оно должно быть выше определено.
Таким образом поток выполнения всегда идет сверху вниз именно так как была написана программа.
никаких обратных или двунаправленных связей кроме специальных рекурсивных случаев.
Ваши слои должны быть также расположены.
Нет ничего страшного в том чтобы из формы вызвать метод репозитория или использовать DI
для сборки модулей.
ДДД не рассматривает эти вопросы. ДДД это решение задачи бизнес-логики.
то откуда берутся данные для ядра ДДД-программы и куда сохраняются ей все равно.
но всегда есть точка где ДДД и инфраструктура должны быть соеденены.
Для этого хорошо подходит архитектура https://duckduckgo.com/?q=cqrs+pattern&atb=v368-1&ia=web
☭ ✊ В мире нет ничего, кроме движущейся материи.
Re[2]: Инициализация соединения с внешней БД
От: zelenprog  
Дата: 06.10.23 05:48
Оценка:
DP>Инфраструктурный слой. Некий DatabaseContext. Я так понимаю, вы на C#. Наверное, что-то типа DbContext.OnConfiguring (https://learn.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.dbcontext.onconfiguring?view=efcore-7.0).
DP>Вот тут есть пример https://www.entityframeworktutorial.net/efcore/entity-framework-core-dbcontext.aspx.

Не нашел в этих примерах про инициализацию БД "сквозь" Бизнес-логику.

DP>Опять же, тут надо смотреть конкретно ваш кейс. Сделать-то можно по-разному. Я так понимаю, у вас десктопной приложение. Там порой имеет смысл сделать иначе, чем в веб-приложении.


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

DP>Кстати, если я правильно понял, в вашем случае можно рассматривать путь к файлу БД как сущность домена, то есть Entity. И хранить соответственно.


А "соответственно" это как?
Типа вот так?

class MainForm {
  
  TTextField mPathTextField;
  
  private void OnButtonClicked() 
  {
      lDbPath = new TDbPath(mPathTextField);
      lBusinessLogic = new TBusinessLogic;
      lBusinessLogic.UseDbPath(lDbPath);
      lBusinessLogic.DoImport();
  }
}


DP>Ну а вообще можно не усложнять и сделать сильно проще без этих всех заморочек Возможно вы выбрали не самый подходящий для оттачивания навыков работы с DDD пример.


Если даже этот пример "не по зубам" для применения DDD, тогда что уж говорить о боее сложных ситуациях?
Re[2]: Инициализация соединения с внешней БД
От: zelenprog  
Дата: 06.10.23 05:51
Оценка:
RD>Можно так:

RD>
RD>// Интерфейсы + реализация (обычно, но не обязательно, в отдельной сборке)
RD>// Форма
RD>  // ...
RD>// Точка сборки, aka composition root (обычно где-то в Program.cs)
RD>var repoFactory = new RepositoryFactory();
RD>var mainForm = new MainForm(repoFactory);
RD>Application.Run(mainForm);
RD>


Идею понял — использовать точку сборки. А потом передавать уже проинициализированный Репозиторий в Бизнес-логику.
Верно?
Re[2]: Инициализация соединения с внешней БД
От: zelenprog  
Дата: 06.10.23 06:07
Оценка:
Р>Любая программа выполняется последовательно.
Р>Чтобы это понять достаточно поиграть с нужным ЯП типа F#.
Р>Его фича однопроходность. Т.е. чтобы что-то использовать оно должно быть выше определено.
Р>Таким образом поток выполнения всегда идет сверху вниз именно так как была написана программа.
Р>никаких обратных или двунаправленных связей кроме специальных рекурсивных случаев.
Р>Ваши слои должны быть также расположены.

Р>Нет ничего страшного в том чтобы из формы вызвать метод репозитория или использовать DI

Р>для сборки модулей.

Р>ДДД не рассматривает эти вопросы. ДДД это решение задачи бизнес-логики.

Р>то откуда берутся данные для ядра ДДД-программы и куда сохраняются ей все равно.
Р>но всегда есть точка где ДДД и инфраструктура должны быть соеденены.

ОК. Понял. Это важные замечания.

Р>Для этого хорошо подходит архитектура https://duckduckgo.com/?q=cqrs+pattern&atb=v368-1&ia=web


Здесь описан шаблон CQRS. Суть его понятна.
Однако, про инициализацию БД там ни слова.
Re[2]: Инициализация соединения с внешней БД
От: zelenprog  
Дата: 06.10.23 06:11
Оценка:
Q>Как то делал программу где параметры подключения к бд задавались в интерфейсе. В домен добавил класс который создавал репозиторий по параметрам, этакий репозиторий репозиториев.

Как мне кажется, Домен не должен создавать Репозитории.
Домен должен использовать Репозитории. А вот создаваться и инициализироваться они должны где-то в другом месте. Это чтобы Домен был "независимым" от других слоев.

А вот где нужно инициализировать все то, что используется Доменом?
Какой объект в программе является таким "всезнающим"?
Re[3]: Инициализация соединения с внешней БД
От: Qulac Россия  
Дата: 06.10.23 06:59
Оценка:
Здравствуйте, zelenprog, Вы писали:


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


Z>Как мне кажется, Домен не должен создавать Репозитории.

Z>Домен должен использовать Репозитории. А вот создаваться и инициализироваться они должны где-то в другом месте. Это чтобы Домен был "независимым" от других слоев.

Z>А вот где нужно инициализировать все то, что используется Доменом?

Z>Какой объект в программе является таким "всезнающим"?

Пусть у нас есть программа которая позволяет подключаться к разным бд, получить список объектов(таблицы, триггеры, хранимки) из них, создавать новые объекты, при необходимости записывать или читать в созданные таблицы. Это где все должно быть в домене или где-то в другом месте?
Программа – это мысли спрессованные в код
Re[3]: Инициализация соединения с внешней БД
От: DiPaolo Россия  
Дата: 06.10.23 07:37
Оценка:
DP>>Инфраструктурный слой. Некий DatabaseContext. Я так понимаю, вы на C#. Наверное, что-то типа DbContext.OnConfiguring (https://learn.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.dbcontext.onconfiguring?view=efcore-7.0).
DP>>Вот тут есть пример https://www.entityframeworktutorial.net/efcore/entity-framework-core-dbcontext.aspx.

Z>Не нашел в этих примерах про инициализацию БД "сквозь" Бизнес-логику.


А там и нет про "сквозь бизнес-логику". Вы спросили, в каком слое — я ответил + привел пример.

Z>Внешне приложение выглядит как десктопное. Однако, "внутри" оно организовано как клиент-серверное. Пользовательский интерфейс выглядит как обычные формы, но по сути это браузер. Форма формируется на сервере, отображается на клиенте.

Z>Причем, все это выполняет платформа автоматически.
Z>Для программиста это взаимодействие "прозрачно".
Z>Платформа только предписывает программисту явно разделить программный код (модуль) формы на две "части": клиентскую и серверную.

DP>>Кстати, если я правильно понял, в вашем случае можно рассматривать путь к файлу БД как сущность домена, то есть Entity. И хранить соответственно.


Z>А "соответственно" это как?

Z>Типа вот так?

Z>
Z>class MainForm {
  
Z>  TTextField mPathTextField;
  
Z>  private void OnButtonClicked() 
Z>  {
Z>      lDbPath = new TDbPath(mPathTextField);
Z>      lBusinessLogic = new TBusinessLogic;
Z>      lBusinessLogic.UseDbPath(lDbPath);
Z>      lBusinessLogic.DoImport();
Z>  }
Z>}
Z>


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

DP>>Ну а вообще можно не усложнять и сделать сильно проще без этих всех заморочек Возможно вы выбрали не самый подходящий для оттачивания навыков работы с DDD пример.


Z>Если даже этот пример "не по зубам" для применения DDD, тогда что уж говорить о боее сложных ситуациях?


Я не говорил, что он вам не по зубам. Я говорил, что возможно тут DDD не самая лучшая идея.
Патриот здравого смысла
Re[3]: Инициализация соединения с внешней БД
От: Разраб  
Дата: 06.10.23 08:27
Оценка:
Здравствуйте, zelenprog, Вы писали:


RD>>Можно так:


RD>>
RD>>// Интерфейсы + реализация (обычно, но не обязательно, в отдельной сборке)
RD>>// Форма
RD>>  // ...
RD>>// Точка сборки, aka composition root (обычно где-то в Program.cs)
RD>>var repoFactory = new RepositoryFactory();
RD>>var mainForm = new MainForm(repoFactory);
RD>>Application.Run(mainForm);
RD>>


Z>Идею понял — использовать точку сборки. А потом передавать уже проинициализированный Репозиторий в Бизнес-логику.

Z>Верно?

И да и нет. Бизнес-Логика должна работать только на своем уровне, а уже апп связать все слои вместе.

let repo = { db = "./path1" }
let domain = { some_logic = fun data -> () }
let result = repo.get_data () |> domain.some_logic 
result |> repo.save_data
☭ ✊ В мире нет ничего, кроме движущейся материи.
Re[4]: Инициализация соединения с внешней БД
От: zelenprog  
Дата: 06.10.23 09:14
Оценка:
DP>Я не говорил, что он вам не по зубам. Я говорил, что возможно тут DDD не самая лучшая идея.

Хм...
Много где написано, что архитектуры, основанные на принципах разделения слоев (выделение ядра в виде Domain-logic и т.д.) — это чуть ли не величайшее достижение в современном состоянии разработки ПО.

Вообще без разделения невозможно написать программу. Так что делить надо.
Пусть мы не будем выделять какое-то ядро в виде Domain Model. Но все равно на какие-то слои разделить программу мы должны.
Тогда вопрос — если в моем случае не использовать подход DDD, то тогда как лучше разделить программу?
Re[4]: Инициализация соединения с внешней БД
От: zelenprog  
Дата: 06.10.23 09:16
Оценка:
Р>И да и нет. Бизнес-Логика должна работать только на своем уровне, а уже апп связать все слои вместе.

А-а-а, то есть бизнес-логика вообще не должна взаимодействовать с Репозиториями?
А где же тогда Бизнес-логика будет "доставать" необходимую для нее информацию?
Отредактировано 06.10.2023 9:28 zelenprog . Предыдущая версия .
Re[5]: Инициализация соединения с внешней БД
От: DiPaolo Россия  
Дата: 06.10.23 10:02
Оценка:
Z>Много где написано, что архитектуры, основанные на принципах разделения слоев (выделение ядра в виде Domain-logic и т.д.) — это чуть ли не величайшее достижение в современном состоянии разработки ПО.

Разделение на слои и DDD не тождественно равны. А пихать бездумно везде DDD тоже не стоит.

Z>Вообще без разделения невозможно написать программу. Так что делить надо.

Z>Пусть мы не будем выделять какое-то ядро в виде Domain Model. Но все равно на какие-то слои разделить программу мы должны.
Z>Тогда вопрос — если в моем случае не использовать подход DDD, то тогда как лучше разделить программу?

Если я правильно понял ваш кейс (программа-конвертилка из одной схемы в другую), то тут исходная и таргет БД 9в том числе пути к БД) и являются самим доменом. Соответственно, в UI получили путь к файлу, провалили его в репозиторий, который хранит сущности исходной и таргет файлнеймов. А потом уже сервис конвертами берет оттуда эти пути. Ну либо сразу в сервис просуньте. При этом доменными Entity будут пути к файлам (+ может дополнительная метаинформация).

Я почему и говорил, что это не самый лучший кейс для оттачивания DDD, потому что тут путь к БД можно рассматривать как сам энтити домена. Вот и получается путаница.

Другой вариант: у вас есть DbContext (необязательно сишарповый, а просто некий класс настроек БД). В UI форме получили путь к БД, потом вызвали у DbContext метод для обновления пути к БД. Да, это может показаться "неканоничным". Что ж. Еще раз повторю, что у вас пример не самый очевидный для тренировки DDD.
Патриот здравого смысла
Re[5]: Инициализация соединения с внешней БД
От: Разраб  
Дата: 06.10.23 10:33
Оценка:
Здравствуйте, zelenprog, Вы писали:


Р>>И да и нет. Бизнес-Логика должна работать только на своем уровне, а уже апп связать все слои вместе.


Z>А-а-а, то есть бизнес-логика вообще не должна взаимодействовать с Репозиториями?

Z>А где же тогда Бизнес-логика будет "доставать" необходимую для нее информацию?
корень приложения будет соединять слои. но это имеет дополнительную сложность и потерю производительности.
☭ ✊ В мире нет ничего, кроме движущейся материи.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.