Разделение записи товара в БД на слои кода
От: zelenprog  
Дата: 15.09.23 08:50
Оценка:
Здравствуйте!

В предыдущей теме я спрашивал про валидацию:
https://rsdn.org/forum/design/8586755
Автор: zelenprog
Дата: 24.08.23


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

Общий алгоритм следующий:
1) Выгружаем из базы-источника товары в файл передачи
2) В новой базе читаем файл передачи из конкретной n-ой базы-источника.
3) По разным реквизитам (наименование, штрихкод) пытаемся установить соответствия между товарами из текущей базы и из базы-источника.
Это соответствие между товарами пока что "логическое".
4) Выводим пользователю таблицу, разделенную на две части:
— в левой колонке товар из текущей новой базы (или пустота, если не найдено соответствие)
— в правой колонке товар из старой базы (или пустота, если не найдено соответствие)
— поля для признаков "проверен", "записывать", "записан" (при первом заполнении они пустые)
5) Пользователь смотрит на эту таблицу, проверяет данные:
5.1) Если пользователь убеждается, что соответствие установлено верно и товар надо загружать, он включает флажки "проверено", "записывать".
При этом в базу записывается "жесткое" фиксированное соответствие: GUID товара из старой базы, GUID товара из новой базы, признак "записывать" = "Да".
5.2) Если пользователь убеждается, что соответствие установлено верно и товар не надо загружать, он включает признак "проверено", "записывать" выключает.
В базу записывается "жесткое" фиксированное соответствие: GUID товара из старой базы, GUID товара из новой базы, и признак "записывать" = "Нет".
5.3) Если соответствия нету, и пользователь решает, что товара из старой базы еще нету в новой базе, он включает признаки "проверено", "записывать".
Это значит, что в новой базе надо создать новый товар на основании товара из старой базы.
В базу записывается просто GUID товара из старой базы и признак "записывать" = "Да".
6) Пользователь нажимает кнопку "Записать".
Для каждой строки из списка выделенных строк:
— выполняется проверка флажков "проверен" и "записан", если флажки установлены, то выполняется:
— запись информации о товаре в базу
— запись в таблицу "Флажки" признака "записан" и GUID товара из старой базы, чтобы при повторной работе скрыть уже записанные товары.

Получается, структура БД должна быть такой:
— Таблица "Товары"
— Таблица "Соответствие"
— Таблица "Флажки"

Следует обратить внимание, что алгоритм записи товара для пункта (5.1) (когда есть соответствие) отличается от алгоритма записи для пункта (5.3) (когда соответствия нету).
По пункту (5.1) надо перезаписать товар в новой базе информацией из старой базы.
По пункту (5.3) надо в новой базе создать новый товар на основании информации о товаре из старой базы.

При нажатии на кнопку "Записать" для пункта (5.1) алгоритм записи следующий (соответствие предварительно зафиксировано в таблице "Соответствия"):
— Перезаписываем поля в таблице "Товары" для GUID из таблицы соответствия
— Записываем признак "Записан".
При нажатии на кнопку "Записать" для пункта (5.3) алгоритм записи сложнее (соответствие предварительно не зафиксировано, и его надо зафиксировать в процессе записи):
— Создаем новый товар, запоминаем его GUID
— Записываем этот GUID в таблицу "Соответствие", а также GUID старого товара
— Записываем признак "Записан".
— Обновить в интерфейсе таблицу соответствия, так как появился новый товар, и его нужно там "нарисовать".

Вопрос такой.
По идее, разные алгоритмы записи (5.1) и (5.3) дожлны быть реализованы на уровне слоя бизнес-логики. Верно?
Ведь слой доступа к базе "тупой", он ведь не должен знать что и как надо записывать.
Как в методе "Записать" базнес-логики выполнить алгоритм (5.3) в одном "запросе" и обеспечить целостность транзакции?
Какой класс бизнес-логики это должен делать?
В общем вопросов много, так как опыта мало.
Подскажите, пожалуйста.

Также не понятно по классам.
Вроде бы ясно, что нужен класс "ТоварНоваяБД", "ТоварСтараяБД".
А вот надо ли создавать отдельно класс, который "хранит" информацию о соответствии и работает с ней?

Как дать понять интерфейсу, что создан новый товар, соответствующий товару из старой базы, и что надо дорисовать таблицу на форме?
В общем по п. (5.3) получается какая-то запутанная бизнес-логика.
Отредактировано 15.09.2023 9:08 zelenprog . Предыдущая версия . Еще …
Отредактировано 15.09.2023 9:03 zelenprog . Предыдущая версия .
Re: Разделение записи товара в БД на слои кода
От: Разраб  
Дата: 15.09.23 09:56
Оценка:
Здравствуйте, zelenprog, Вы писали:

да вроде вы уже все расписали. тянет на готовое ТЗ.
Про опыт зря. главное в рассуждениях не сильно заабстрагироваться.
Можете просто накидать прототип с ин-мемори базкой например банальный dict
в качестве яп можно даже js + HTML взять лишь бы суть не утекала.
Я пишу на C#, думаю на F#
☭ ✊ В мире нет ничего, кроме движущейся материи.
Re: Разделение записи товара в БД на слои кода
От: bnk СССР http://unmanagedvisio.com/
Дата: 15.09.23 10:07
Оценка: +1
Здравствуйте, zelenprog, Вы писали:

Z>Теперь вопрос более общий, по "архитектуре".

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

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

Почистить можно и потом, просто применив фильтры.
Отредактировано 15.09.2023 10:11 bnk . Предыдущая версия .
Re[2]: Разделение записи товара в БД на слои кода
От: zelenprog  
Дата: 15.09.23 10:42
Оценка:
bnk>А не проще будет слить их как есть, а потом удалить дубликаты?
bnk>Так хоть будет гарантия, что все данные передались, а то при твоем подходе с миллионом галочек пользователь случайно нажмет не то и привет.

Ничего страшного он там не может сделать.
Те товары, которые записаны — они записаны.
А те, которые не записаны, он их видит, может поменять галочки и записать.

Подход менять не хочется.
Тем более, что это уже все согласовано.
Вопрос только в "грамотной" реализации, выделении классов, разделении их по слоям.
Re: Разделение записи товара в БД на слои кода
От: binks Россия  
Дата: 15.09.23 10:51
Оценка:
Здравствуйте, zelenprog, Вы писали:

Не понятно зачем столько таблиц.
Есть таблица Товары. Нужно дополнительно создать постоянную таблицу импорта товаров (в последующем можно будет посмотреть историю импорта, либо после импорта удалять).
К импортированным товарам джойните существующие товары. Отображаете получившийся датасет одной таблицей, пользователь выставляет нужные флажки, жмёт Ок. Далее вы пробегаете по итоговому датасету и решаете что нужно делать с текущей записью. Либо скопом делаете инсерт/апдейт.
Отредактировано 15.09.2023 11:14 binks . Предыдущая версия .
Re[3]: Разделение записи товара в БД на слои кода
От: bnk СССР http://unmanagedvisio.com/
Дата: 15.09.23 12:06
Оценка:
Здравствуйте, zelenprog, Вы писали:


bnk>>А не проще будет слить их как есть, а потом удалить дубликаты?

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

Z>Ничего страшного он там не может сделать.

Z>Те товары, которые записаны — они записаны.
Z>А те, которые не записаны, он их видит, может поменять галочки и записать.

Я про то что если он ошибся, и дубликат на самом деле не дубликат например (или наоборот), как в твоей системе это можно будет "отменить"?

По поводу архитектуры — ну нафига вообще какая-то архитектура или тем более "слои" для одноразовой задачи, которую сделал и забыл.
Отредактировано 15.09.2023 12:19 bnk . Предыдущая версия .
Re[4]: Разделение записи товара в БД на слои кода
От: zelenprog  
Дата: 15.09.23 14:17
Оценка:
bnk>Я про то что если он ошибся, и дубликат на самом деле не дубликат например (или наоборот), как в твоей системе это можно будет "отменить"?

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

bnk>По поводу архитектуры — ну нафига вообще какая-то архитектура или тем более "слои" для одноразовой задачи, которую сделал и забыл.


Ну потому что при определенном количестве строк кода уже начинаю путаться: что кого откуда вызывает и какие параметры передает, конвертирует.
Сейчас уже базовые функции написаны: по работе с интерфейсом, базой данных, флажками. Но из-за того что их много, уже тяжело ориентироваться в коде.
А еще дальше нужно дорабатывать дополнительные возможности, например установление соответствия "вручную".
Разделение на слои нужно, это намного улучшает и упрощает доработку новой функциональности.
Главное, чтобы разделить правильно. Когда разделено неправильно — только хуже становится.
Re[5]: Разделение записи товара в БД на слои кода
От: bnk СССР http://unmanagedvisio.com/
Дата: 15.09.23 14:53
Оценка:
Здравствуйте, zelenprog, Вы писали:


bnk>>Я про то что если он ошибся, и дубликат на самом деле не дубликат например (или наоборот), как в твоей системе это можно будет "отменить"?


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

Z>Если он думать не хочет, то результат будет такой как сама программа автоматически сопоставила.

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

bnk>>По поводу архитектуры — ну нафига вообще какая-то архитектура или тем более "слои" для одноразовой задачи, которую сделал и забыл.


Z>Главное, чтобы разделить правильно. Когда разделено неправильно — только хуже становится.


Эх не занимался бы ты ерундой, просто слил две базы да дал пользователям возможность удалить дубликаты удобно (пометить на самом деле, не удалять совсем).
Отредактировано 15.09.2023 15:00 bnk . Предыдущая версия .
Re[6]: Разделение записи товара в БД на слои кода
От: zelenprog  
Дата: 18.09.23 05:38
Оценка:
bnk>Эх не занимался бы ты ерундой, просто слил две базы да дал пользователям возможность удалить дубликаты удобно (пометить на самом деле, не удалять совсем).

Ну допустим...
А как пользователь обнаружит дубликаты?
Это же тоже ему придется делать вручную.
Re[7]: Разделение записи товара в БД на слои кода
От: bnk СССР http://unmanagedvisio.com/
Дата: 18.09.23 07:23
Оценка:
Здравствуйте, zelenprog, Вы писали:


bnk>>Эх не занимался бы ты ерундой, просто слил две базы да дал пользователям возможность удалить дубликаты удобно (пометить на самом деле, не удалять совсем).


Z>Ну допустим...

Z>А как пользователь обнаружит дубликаты?

Пользователь отсортировать же записи просто может. Дубликаты будут соседними.
Еще можно например фильтр дубликатов сделать, подсвечивать "подозрительные" записи например.
Как это в Excel делать есть куча видео.
Re: Разделение записи товара в БД на слои кода
От: Gt_  
Дата: 18.09.23 07:24
Оценка:
стандартная ETL задачка по Data Engineering. почитай про Medallion Architecture, там 3 слоя: bronze, silver, gold.
в bronze файлики что пришли, silver очищенные данные + пользовательский ввод, gold — финальные таблицы.
я бы пользовательские решения генерил как еще один файл идущий на вход на silver layer и грузил бы батчами, тогда в случае правок в алгоритме загрузки весь etl можно будет проигрывать с начала.
Re[8]: Разделение записи товара в БД на слои кода
От: zelenprog  
Дата: 18.09.23 11:40
Оценка:
bnk>Пользователь отсортировать же записи просто может. Дубликаты будут соседними.

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

bnk>Еще можно например фильтр дубликатов сделать, подсвечивать "подозрительные" записи например.

bnk>Как это в Excel делать есть куча видео.

Вот чтобы пользователь не занимался этой ерундой, для этого я и делаю обработку.
Это все должна сделать обработка на этапе сопоставления данных из обеих баз.
Какая разница при этом где лежат данные? Либо во внутренней таблицу БД, либо во внешней, либо в памяти в ТЗ.
Re[2]: Разделение записи товара в БД на слои кода
От: zelenprog  
Дата: 18.09.23 14:04
Оценка:
Здравствуйте, Gt_, Вы писали:

Gt_>стандартная ETL задачка по Data Engineering. почитай про Medallion Architecture, там 3 слоя: bronze, silver, gold.

Gt_>в bronze файлики что пришли, silver очищенные данные + пользовательский ввод, gold — финальные таблицы.
Gt_>я бы пользовательские решения генерил как еще один файл идущий на вход на silver layer и грузил бы батчами, тогда в случае правок в алгоритме загрузки весь etl можно будет проигрывать с начала.

Это оно?
https://learn.microsoft.com/en-us/azure/databricks/lakehouse/medallion

Как-то скудно тут описано. Всего пару абзацев. Где можно почитать подробнее?
Re[3]: Разделение записи товара в БД на слои кода
От: Gt_  
Дата: 18.09.23 15:13
Оценка:
Gt_>>стандартная ETL задачка по Data Engineering. почитай про Medallion Architecture, там 3 слоя: bronze, silver, gold.
Gt_>>в bronze файлики что пришли, silver очищенные данные + пользовательский ввод, gold — финальные таблицы.
Gt_>>я бы пользовательские решения генерил как еще один файл идущий на вход на silver layer и грузил бы батчами, тогда в случае правок в алгоритме загрузки весь etl можно будет проигрывать с начала.

Z>Это оно?

Z>https://learn.microsoft.com/en-us/azure/databricks/lakehouse/medallion

Z>Как-то скудно тут описано. Всего пару абзацев. Где можно почитать подробнее?


да, оно. вот тут чуть больше, но там пережевывать собственно нечего.
https://piethein.medium.com/medallion-architecture-best-practices-for-managing-bronze-silver-and-gold-486de7c90055

основная идея не смотреть на это как на программку, что по одной строке что-то грузит, а как на ETL процесс. пользователь валидирует целый батч, потыкал клавиши — сгенерил еще один файл с его решениями на загрузку.
Re[2]: Разделение записи товара в БД на слои кода
От: zelenprog  
Дата: 21.09.23 06:08
Оценка:
B>Не понятно зачем столько таблиц.
B>Есть таблица Товары. Нужно дополнительно создать постоянную таблицу импорта товаров (в последующем можно будет посмотреть историю импорта, либо после импорта удалять).
B>К импортированным товарам джойните существующие товары. Отображаете получившийся датасет одной таблицей ...

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

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


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

B> Либо скопом делаете инсерт/апдейт.


Да, это можно сделать для тех узлов дерева, у которых стоят соответствующие флажки.


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

В каком слое лучше реализовать работу с этой связью?
В слое бизнес-логики?
Отредактировано 21.09.2023 6:11 zelenprog . Предыдущая версия .
Re[3]: Разделение записи товара в БД на слои кода
От: binks Россия  
Дата: 21.09.23 06:57
Оценка:
Здравствуйте, zelenprog, Вы писали:

Z>Одной таблицей не получится это показать.

Z>Так как пользователь должен видеть по крайней мере две записи: первая запись — это импортируемый товар, вторая запись — это уже существующий в базе товар (если таковой обнаружен).
Z>Поэтому мы решили отобразить это в виде иерархического дерева: узел этого дерева — это ключевые реквизиты, по которым обнаружено соответствие, подчиненные строки узла — это товары из обеих баз.
Почему нельзя сделать в одной таблице?
У вас есть таблица Product. Для импорта товаров заводите таблицу ProductImport (Id, CreatedAt, UserId, Product.*).
Когда пользователь хочет импортировать список товаров, то в приложении он тычет кнопку "Создать импорт". Открывается окно, где он указывает путь к файлу. Нажимает "загрузить файл". В таблицу попадают все записи из файла, записи дополнительного присваивается Id текущей загрузки. Я так понял, база является только хранилищем данных, вся бизнес логика расположена в приложении. Тогда вторым шагом каждой записи в таблице ProductImport по каким-то критериям ищете и присваиваете ProductId. Grid ниже отображает таблицу ProductImport, с уже сопоставленными товарами. Соответственно кто не сопоставился ProductId будет равным null.

Z>Остался вопрос только в грамотном разделении всего этого кода на слои, классы и т.д.

Z>Вот например, сгруппированные данные для отображения в виде дерева — это слой представления? Или это слой бизнес-логики?
Z>По теории — дерево — это представление.
Z>Однако, связь между импортируемым товаром и существующим товаром пользователь фиксирует (с помощью флажка). И эта связь сохраняется в БД.
Z>Следовательно, связь (то есть по сути это узел дерева) — это объект бизнес-логики.

Z>В каком слое лучше реализовать работу с этой связью?

Z>В слое бизнес-логики?

В моём понимании сгрупированные данные это модель.
Re[4]: Разделение записи товара в БД на слои кода
От: zelenprog  
Дата: 21.09.23 08:28
Оценка:
B>Почему нельзя сделать в одной таблице?
B>У вас есть таблица Product. Для импорта товаров заводите таблицу ProductImport (Id, CreatedAt, UserId, Product.*).
B>Когда пользователь хочет импортировать список товаров, то в приложении он тычет кнопку "Создать импорт". Открывается окно, где он указывает путь к файлу. Нажимает "загрузить файл". В таблицу попадают все записи из файла, записи дополнительного присваивается Id текущей загрузки. Я так понял, база является только хранилищем данных, вся бизнес логика расположена в приложении. Тогда вторым шагом каждой записи в таблице ProductImport по каким-то критериям ищете и присваиваете ProductId. Grid ниже отображает таблицу ProductImport, с уже сопоставленными товарами. Соответственно кто не сопоставился ProductId будет равным null.

В принципе я согласен, для хранения в базе, можно использовать и одну таблицу.
Только нужно учесть еще один момент.
Когда будем загружать товары из 2-й и 3-й базы, они могут "соответствовать" уже загруженным в базу товарам.
Re[4]: Разделение записи товара в БД на слои кода
От: zelenprog  
Дата: 21.09.23 08:48
Оценка:
Z>>В каком слое лучше реализовать работу с этой связью?
Z>>В слое бизнес-логики?
B>
B>В моём понимании сгрупированные данные это модель.

"Модель" — вы имеете ввиду класс бизнес-логики?
Как формируется этот объект? В каком слое приложения?

Еще раз опишу задачу.
На экране пользователю надо показать список "соответствий" ("группировок") товаров.
Каждое соответствие — это:
1) все реквизиты (поля) импортируемого товара
2) все реквизиты (поля) соответствующего товара, найденного в базе

Если и (1) и (2) показывать в одной строке — это будет очень неудобно смотреть.
Надо (1) и (2) показать в двух строках, чтобы соответствующие реквизиты были друг под другом в одной колонке.
Поэтому мы решили это показывать в виде узла дерева с двумя подчиненными строками.

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

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

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

Какой вариант лучше? И как это реализовать?
Как правильно разделить ответственности программного кода (классов) за формирование\хранение\отображение этого дерева соответствий?
Какие это будут классы и в каких слоях-модулях они должны находиться?
Re[5]: Разделение записи товара в БД на слои кода
От: binks Россия  
Дата: 21.09.23 09:46
Оценка:
Здравствуйте, zelenprog, Вы писали:

Z>В принципе я согласен, для хранения в базе, можно использовать и одну таблицу.

Z>Только нужно учесть еще один момент.
Z>Когда будем загружать товары из 2-й и 3-й базы, они могут "соответствовать" уже загруженным в базу товарам.

Нет, вы не поняли.
Таблица Product — основная, а ProductImport постоянная, но вспомогательная. Когда происходит окончательный шаг импорта, то по выставленным флажкам/значениям в ProductImport происходит insert/update Product.
Но после импорта можно посмотреть историю импорта. То что не импортировали сейчас, можно импортировать позже.
Re[6]: Разделение записи товара в БД на слои кода
От: zelenprog  
Дата: 21.09.23 10:26
Оценка:
B>Нет, вы не поняли.
B>Таблица Product — основная, а ProductImport постоянная, но вспомогательная. Когда происходит окончательный шаг импорта, то по выставленным флажкам/значениям в ProductImport происходит insert/update Product.
B>Но после импорта можно посмотреть историю импорта. То что не импортировали сейчас, можно импортировать позже.

Я именно так и понял.
Вы имеете ввиду, что импортируемые товары, их соответствие и флажки хранятся только в одной таблице ProductImport (а не как у меня изначально — в разных таблицах).

Уточню свою фразу:
"В принципе я согласен, для хранения импортируемых товаров в базе, можно использовать одну таблицу".
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.