Re[14]: Про путаницу с репозиториями и DAO
От: Vladek Россия Github
Дата: 27.06.16 13:16
Оценка: -1
Здравствуйте, gandjustas, Вы писали:

G>Да вот у меня как-то не было примеров, чтобы одна и та же программа могла работать с любым источником данных. Скорее обратное. Даже небольшие различия в разных движках БД приводили к различному коду, даже с применением ORM.


У тебя есть приложение, которое берёт данные из корпоративной бд. Ваша контора слилась с другой конторой, приложение должно теперь обслуживать и её, однако данные та другая контора хранила в каком-то облаке с доступом по wep api и что-то менять будет дорого, поэтому приложение теперь должно уметь общаться с тем веб-сервисом, а бизнес-процесс менять не надо.

Код доступа к бд через ORM менять не надо, надо просто добавить ещё один.
Re[11]: Про путаницу с репозиториями и DAO
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 27.06.16 13:18
Оценка:
Здравствуйте, Vladek, Вы писали:

G>>Естественно писать заведомо неэффективный код — моветон.


V>
V>var employees = await employeeRepo.GetEmployeesAsync(EmployeeCategory.SpecificCategory);
V>foreach (var employee in employees)
V>{
V>    employee.ChangeSalary(factor: +0.1f);
V>}
V>await Employee.SaveChangesAsync(employees);
V>


Ох сколько вопросов сразу:
1) В случае List<T> надо все синхронные операции в async\await оборачивать?
2) В случае базы данных вместо одного апдейта в базу улетит 100500?
3) Откуда вообще у веб-сервиса метод с фильтрами по категории или будут тянуться все сотрудники, а потом фильтр пойдет на клиенте?


У вас получился заведомо неэффективный код для каждого из случаев И сразу же отрублены все возможности улучшить ситуацию.
Re[15]: Про путаницу с репозиториями и DAO
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 27.06.16 13:20
Оценка: +1
Здравствуйте, Vladek, Вы писали:

V>Здравствуйте, gandjustas, Вы писали:


G>>Да вот у меня как-то не было примеров, чтобы одна и та же программа могла работать с любым источником данных. Скорее обратное. Даже небольшие различия в разных движках БД приводили к различному коду, даже с применением ORM.


V>У тебя есть приложение, которое берёт данные из корпоративной бд. Ваша контора слилась с другой конторой, приложение должно теперь обслуживать и её, однако данные та другая контора хранила в каком-то облаке с доступом по wep api и что-то менять будет дорого, поэтому приложение теперь должно уметь общаться с тем веб-сервисом, а бизнес-процесс менять не надо.


Тупо загружается из облако все в базу и проблема на этом кончается.
И, как это ни странно, я как раз такой сценарий реализовывал на практике при слиянии компаний.

V>Код доступа к бд через ORM менять не надо, надо просто добавить ещё один.

Никто такой фигней не занимается. Проще перелить данные в один источник, чем заниматься таким геморроем.
Re[11]: Про путаницу с репозиториями и DAO
От: Vladek Россия Github
Дата: 27.06.16 14:01
Оценка:
Здравствуйте, Sharov, Вы писали:

G>>Архитектура это не тогда, когда много паттернов, а когда сделано ровно столько, сколько нужно, чтобы решить задачу и не изобретать велосипеды.


S>Для этого и придуманы паттерны. Современная архитектура -- это взаимодействие паттерноподобных сущностей, абстракций. А гофосккие паттерны -- платоновский идеал.


Паттерны носят описательный характер. Они описывают то, что уже есть в коде, никто их отдельно не придумывал и вообще вменяемый разработчик переизобретает их сам, даже не читая книжек про паттерны. Хорошая архитектура не та, в которой много паттернов, а та, которую легко описать.
Re[7]: Про путаницу с репозиториями и DAO
От: IT Россия linq2db.com
Дата: 27.06.16 14:02
Оценка:
Здравствуйте, another_coder, Вы писали:

_>God-object )


Помоечка с кучей необходимого для одного процесса.
Если нам не помогут, то мы тоже никого не пощадим.
Re[10]: Про путаницу с репозиториями и DAO
От: Vladek Россия Github
Дата: 27.06.16 14:12
Оценка:
Здравствуйте, IT, Вы писали:

IT>Попробуй. Хорошо писать как бог на душу положит мало у кого получается. Это вывсшее дао программирования. Я пока таких людей не встречал.


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

Проблемы возникают со второй функцией кода — быть готовым к изменениям. Для этого и нужна архитектура.

Подход, когда код сначала пишется с наскока, а потом, будучи испытанным в деле, рефакторится в нечто вменяемое, работает довольно неплохо если с самого начала проектирование архитектуры буксовало.
Re[12]: Про путаницу с репозиториями и DAO
От: Vladek Россия Github
Дата: 27.06.16 14:32
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Ох сколько вопросов сразу:

G>1) В случае List<T> надо все синхронные операции в async\await оборачивать?
Тривиальная задача.
G>2) В случае базы данных вместо одного апдейта в базу улетит 100500?
Не обязательно. Скорее всего, не важно.
G>3) Откуда вообще у веб-сервиса метод с фильтрами по категории или будут тянуться все сотрудники, а потом фильтр пойдет на клиенте?
Метод с фильтрами по категории у нашего репозитория, а как он реализован — дело десятое. Главное, код работы с зарплатой от этого никак не зависит.

G>У вас получился заведомо неэффективный код для каждого из случаев И сразу же отрублены все возможности улучшить ситуацию.

Что такое "эффективный код" в случае изменения важной информации о сотрудниках предприятия?
Re[16]: Про путаницу с репозиториями и DAO
От: Vladek Россия Github
Дата: 27.06.16 14:39
Оценка:
Здравствуйте, gandjustas, Вы писали:

V>>У тебя есть приложение, которое берёт данные из корпоративной бд. Ваша контора слилась с другой конторой, приложение должно теперь обслуживать и её, однако данные та другая контора хранила в каком-то облаке с доступом по wep api и что-то менять будет дорого, поэтому приложение теперь должно уметь общаться с тем веб-сервисом, а бизнес-процесс менять не надо.


G>Тупо загружается из облако все в базу и проблема на этом кончается.

G>И, как это ни странно, я как раз такой сценарий реализовывал на практике при слиянии компаний.

И руководство компаний тебе просто доверилось? А потом сразу упразднили во второй компании старый процесс и перешли на новый? Почему слиянием БД занимался программист, а не команда администраторов БД и бизнес-аналитиков?

V>>Код доступа к бд через ORM менять не надо, надо просто добавить ещё один.

G>Никто такой фигней не занимается. Проще перелить данные в один источник, чем заниматься таким геморроем.

Занимаются те, для кого это совсем не гемморой, кто хорошо изолировал свой код от источников данных.
Re[13]: Про путаницу с репозиториями и DAO
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 27.06.16 14:41
Оценка:
Здравствуйте, Vladek, Вы писали:

V>Здравствуйте, gandjustas, Вы писали:


G>>Ох сколько вопросов сразу:

G>>1) В случае List<T> надо все синхронные операции в async\await оборачивать?
V>Тривиальная задача.
Так и запишем — лишняя работа.
Кстати что SaveChangesAsync будет в этом случае делать? Как гарантировать в тестах что он вызывается, если мы изначально делаем на List<T>, а потом "подменяем storage"?

G>>2) В случае базы данных вместо одного апдейта в базу улетит 100500?

V>Не обязательно. Скорее всего, не важно.
Скорее всего очень важно. Примерно на два порядка будет отличаться время работы в зависимости от реализации.

G>>3) Откуда вообще у веб-сервиса метод с фильтрами по категории или будут тянуться все сотрудники, а потом фильтр пойдет на клиенте?

V>Метод с фильтрами по категории у нашего репозитория, а как он реализован — дело десятое. Главное, код работы с зарплатой от этого никак не зависит.
Во-во и на практике приведёт к тому, что будет затягиваться вес список и фильтроваться на клиенте. А потом этот потрясающий get-метод ктонить использует на главной странице и приложением станет невозможно пользоваться.

G>>У вас получился заведомо неэффективный код для каждого из случаев И сразу же отрублены все возможности улучшить ситуацию.

V>Что такое "эффективный код" в случае изменения важной информации о сотрудниках предприятия?
Эффективный код, который не делает лишней работы или соотношение лишней или доля лишней работы крайне мала. Чем он занимается — неважно, потому что имеется тенденция распространения стиля на все приложение. То что кажется в одном месте маленькой неэффективностью копируется в другое место, где появляются тормоза на несколько десятков секунд.

Не знаю как ты, а я все это уже проходил. За каждым из приведенных выше вопросов стоит косяк в реальной программе, который привел к реальным потерям.
Re[17]: Про путаницу с репозиториями и DAO
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 27.06.16 14:48
Оценка:
Здравствуйте, Vladek, Вы писали:

G>>Тупо загружается из облако все в базу и проблема на этом кончается.

G>>И, как это ни странно, я как раз такой сценарий реализовывал на практике при слиянии компаний.
V>И руководство компаний тебе просто доверилось? А потом сразу упразднили во второй компании старый процесс и перешли на новый? Почему слиянием БД занимался программист, а не команда администраторов БД и бизнес-аналитиков?
Примерно так было. Было две CRM, с одной стороны самописная, с другой нет. Из самописной выгрузили послезные данные и загрузили в рабочую.
Не просто доверилось, а когда посчитали затраты на доработку самописной + такую архитектуру как ты предлагаешь, так сразу просили перелить данные побыстрее.

G>>Никто такой фигней не занимается. Проще перелить данные в один источник, чем заниматься таким геморроем.

V>Занимаются те, для кого это совсем не гемморой, кто хорошо изолировал свой код от источников данных.
У меня начали закрадываться подозрения, что ты ни одного реального приложения не сделал. Чтобы сотня ГБ данных и хотя бы 1000 пользователей была.
Re[14]: Про путаницу с репозиториями и DAO
От: Vladek Россия Github
Дата: 27.06.16 15:14
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Здравствуйте, Vladek, Вы писали:


V>>Здравствуйте, gandjustas, Вы писали:


G>>>Ох сколько вопросов сразу:

G>>>1) В случае List<T> надо все синхронные операции в async\await оборачивать?
V>>Тривиальная задача.
G>Так и запишем — лишняя работа.


G>Кстати что SaveChangesAsync будет в этом случае делать? Как гарантировать в тестах что он вызывается, если мы изначально делаем на List<T>, а потом "подменяем storage"?


Извлекает из сотрудников все нужные данные (в виде DTO) и отправляет их на сохранение в хранилище. Не важное какое хранилище, на входе у него всегда эти DTO.

G>>>2) В случае базы данных вместо одного апдейта в базу улетит 100500?

V>>Не обязательно. Скорее всего, не важно.
G>Скорее всего очень важно. Примерно на два порядка будет отличаться время работы в зависимости от реализации.

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

G>>>3) Откуда вообще у веб-сервиса метод с фильтрами по категории или будут тянуться все сотрудники, а потом фильтр пойдет на клиенте?

V>>Метод с фильтрами по категории у нашего репозитория, а как он реализован — дело десятое. Главное, код работы с зарплатой от этого никак не зависит.
G>Во-во и на практике приведёт к тому, что будет затягиваться вес список и фильтроваться на клиенте. А потом этот потрясающий get-метод ктонить использует на главной странице и приложением станет невозможно пользоваться.
На практике у веб-сервиса есть подходящий API для выборки данных, хотя бы простой поиск. Ты в своей фантазии про медленный get можешь добавить в реализацию хранилища кэш, это опять же никак не повлияет на код репозитория.

G>>>У вас получился заведомо неэффективный код для каждого из случаев И сразу же отрублены все возможности улучшить ситуацию.

V>>Что такое "эффективный код" в случае изменения важной информации о сотрудниках предприятия?
G>Эффективный код, который не делает лишней работы или соотношение лишней или доля лишней работы крайне мала. Чем он занимается — неважно, потому что имеется тенденция распространения стиля на все приложение. То что кажется в одном месте маленькой неэффективностью копируется в другое место, где появляются тормоза на несколько десятков секунд.

Эффективный код в отношении изменения зарплаты сотрудников должен быть атомарным. Мы это достигаем за счёт аккумулирования всех изменений в одном вызове SaveChangesAsync. Будет он выполняться 50 мс или 10 секунд — дело десятое и легко решаемое, для задачи гораздо важнее гарантированное выполнение или чёткий откат в случае сбоя.

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


С изменением требований я сталкиваюсь постоянно. Сегодня надо работать с таким источником данных, завтра с ещё одним. Использую описанный подход и не имею особых проблем.
Re[11]: Про путаницу с репозиториями и DAO
От: IT Россия linq2db.com
Дата: 27.06.16 15:27
Оценка:
Здравствуйте, another_coder, Вы писали:

_>Не пора ли уже остановиться?


Дык спираль развития же.
Если нам не помогут, то мы тоже никого не пощадим.
Re[10]: Про путаницу с репозиториями и DAO
От: Baudolino  
Дата: 27.06.16 17:38
Оценка:
Здравствуйте, IT, Вы писали:

IT>Нет. Основная функция DAL — изоляция работы с БД от остальной части приложения. То, что это обладает ещё какими-то другими свойствами — это побочный эффект. Например, ту же обстракцию БД вполне хорошо, даже лучше чем DAL выполняет LINQ, но принципиально по-другому.


Два момента:
1. LINQ не "выполняет абстракцию БД", потому что это интерфейс доступа к наборам произвольных данных (и первый же пример из MSDN об этом, поскольку использует LINQ на обычном списке).
2. DAL в случае с LINQ никуда не девается, просто всю работу за вас делает вендор ORM-решения, которое и представляет собой тот самый DAL, абстрагирующий вас от особенностей работы с БД с помощью LINQ.
Re[18]: Про путаницу с репозиториями и DAO
От: Vladek Россия Github
Дата: 27.06.16 18:22
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Здравствуйте, Vladek, Вы писали:


G>>>Тупо загружается из облако все в базу и проблема на этом кончается.

G>>>И, как это ни странно, я как раз такой сценарий реализовывал на практике при слиянии компаний.
V>>И руководство компаний тебе просто доверилось? А потом сразу упразднили во второй компании старый процесс и перешли на новый? Почему слиянием БД занимался программист, а не команда администраторов БД и бизнес-аналитиков?
G>Примерно так было. Было две CRM, с одной стороны самописная, с другой нет. Из самописной выгрузили послезные данные и загрузили в рабочую.
G>Не просто доверилось, а когда посчитали затраты на доработку самописной + такую архитектуру как ты предлагаешь, так сразу просили перелить данные побыстрее.

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

G>>>Никто такой фигней не занимается. Проще перелить данные в один источник, чем заниматься таким геморроем.

V>>Занимаются те, для кого это совсем не гемморой, кто хорошо изолировал свой код от источников данных.
G>У меня начали закрадываться подозрения, что ты ни одного реального приложения не сделал. Чтобы сотня ГБ данных и хотя бы 1000 пользователей была.

Лучше опиши свой подход к архитектуре, которая однако благополучно переживала потрясения типа описанных выше.
Re[11]: Про путаницу с репозиториями и DAO
От: IT Россия linq2db.com
Дата: 27.06.16 19:06
Оценка:
Здравствуйте, Baudolino, Вы писали:

B>1. LINQ не "выполняет абстракцию БД", потому что это интерфейс доступа к наборам произвольных данных (и первый же пример из MSDN об этом, поскольку использует LINQ на обычном списке).


Это у кого как и смотря что мы под этим понимаем.

B>2. DAL в случае с LINQ никуда не девается, просто всю работу за вас делает вендор ORM-решения, которое и представляет собой тот самый DAL, абстрагирующий вас от особенностей работы с БД с помощью LINQ.


Нет. Функция изоляции переехала в LINQ. А сам DAL больше нафиг не нужен.
Если нам не помогут, то мы тоже никого не пощадим.
Re[19]: Про путаницу с репозиториями и DAO
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 27.06.16 21:26
Оценка: 1 (1)
Здравствуйте, Vladek, Вы писали:

V>Тогда пример не подходит. Вернее, твой опыт про другое — внутренний проект закрыли, данные импортировали в сторонний продукт. Нужна гибкая архитектура, способная подстроиться под новый источник данных. Репозитории как способ общения ядра программы с внешним миром — тут и пригождаются.

Никому твоя архитектура не нужна. Нужно чтобы быстро работало и быстро вносились изменения.
Самый быстрый способ в случае объединения двух систем — перелить данные одной в другую.


G>>>>Никто такой фигней не занимается. Проще перелить данные в один источник, чем заниматься таким геморроем.

V>>>Занимаются те, для кого это совсем не гемморой, кто хорошо изолировал свой код от источников данных.
G>>У меня начали закрадываться подозрения, что ты ни одного реального приложения не сделал. Чтобы сотня ГБ данных и хотя бы 1000 пользователей была.
V>Лучше опиши свой подход к архитектуре, которая однако благополучно переживала потрясения типа описанных выше.

Мой подход — использовать ORM https://habrahabr.ru/post/230623/ и http://blog.gandjustas.ru/2014/09/23/asp.net-linq-ef-sql-server-performance/
И делать кеширование
https://habrahabr.ru/post/168725/
https://habrahabr.ru/post/168869/
https://habrahabr.ru/post/227129/
https://habrahabr.ru/post/240269/

Еще я применяю IOC иногда http://blog.gandjustas.ru/categories/#IOC

И вот такие подходы к архитектуре http://blog.gandjustas.ru/categories/#Архиетктураприложений
Re[14]: Про путаницу с репозиториями и DAO
От: another_coder Россия  
Дата: 28.06.16 08:08
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Кстати что SaveChangesAsync будет в этом случае делать? Как гарантировать в тестах что он вызывается, если мы изначально делаем на List<T>, а потом "подменяем storage"?


Вы действительно проверяете в тесте вызовы методов? Если да, то зачем именно этот и как?

На мой взгляд, в юнит тестах вызов такого метода (сохраняющего в базу) проверять не надо. И в интеграциогнных тестах не следует проверять его вызов, а только наличие данных в хранилище после "действий". Поэтому не понимаю вопрос про проверку.
Отредактировано 28.06.2016 9:46 another_coder . Предыдущая версия .
Re[15]: Про путаницу с репозиториями и DAO
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 28.06.16 10:12
Оценка:
Здравствуйте, another_coder, Вы писали:

_>Здравствуйте, gandjustas, Вы писали:


G>>Кстати что SaveChangesAsync будет в этом случае делать? Как гарантировать в тестах что он вызывается, если мы изначально делаем на List<T>, а потом "подменяем storage"?


_>Вы действительно проверяете в тесте вызовы методов? Если да, то зачем именно этот и как?

Затем что был проект, покрытый юнит тестами и они не падали, но не работало. Оказалось, что тест проверял только добавление в коллекцию объекта, а метод сохранения не вызывался.
Проверяется банально моками.

_>На мой взгляд, в юнит тестах вызов такого метода (сохраняющего в базу) проверять не надо.

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

_>И в интеграциогнных тестах не следует проверять его вызов, а только наличие данных в хранилище после "действий". Поэтому не понимаю вопрос про проверку.

В интеграционных да, но разработчики часто не прогоняют интеграционные тесты, а юнит-тесты, особенно с ReSharper прогоняются всегда.
Re[15]: Про путаницу с репозиториями и DAO
От: Sinclair Россия https://github.com/evilguest/
Дата: 28.06.16 11:21
Оценка:
Здравствуйте, Vladek, Вы писали:


V>Эффективный код в отношении изменения зарплаты сотрудников должен быть атомарным. Мы это достигаем за счёт аккумулирования всех изменений в одном вызове SaveChangesAsync. Будет он выполняться 50 мс или 10 секунд — дело десятое и легко решаемое, для задачи гораздо важнее гарантированное выполнение или чёткий откат в случае сбоя.

Это вам так кажется потому, что вы не представляете себе масштабов проблемы. Дело в том, что тормоза в подобных приложениях имеют многостадийный эффект.
То есть сначала просто всё работает чуть медленнее, чем хочется. Это нефункциональная проблема, и нам наплевать.
Потом оказывается, что с ростом нагрузки на базу транзакции, внутри которых происходит общение с клиентом, начинают тормозить всё сильнее — потому, что каждый update застревает на чуть-чуть в ожидании отпускания локов.
Транзакции становятся всё дольше, и удерживают локи на всё более длинное время. Тормоза стремительно прогрессируют.
Затем тормоза начинают становиться фейлами, потому что периодически происходят дедлоки. И наша атомарность оборачивается тем, что мы получаем "чёткий откат" вместо внесения изменений.
Начинаются вот эти вот знаменитые "девочки, все выйдите из терминала, я отгрузку провожу".
А всё оттого что в кузнице не было гвоздя вначале кто-то решил, что засосать тыщу записей в память, а потом по одной фигачить update на их основе — это нормальная стратегия. А чо — в тестах в single-user моде всё исполняется 10 секунд, что должно бы всех устроить.

V>С изменением требований я сталкиваюсь постоянно. Сегодня надо работать с таким источником данных, завтра с ещё одним. Использую описанный подход и не имею особых проблем.

Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[15]: Про путаницу с репозиториями и DAO
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 28.06.16 11:36
Оценка:
Здравствуйте, Vladek, Вы писали:


G>>Кстати что SaveChangesAsync будет в этом случае делать? Как гарантировать в тестах что он вызывается, если мы изначально делаем на List<T>, а потом "подменяем storage"?

V>Извлекает из сотрудников все нужные данные (в виде DTO) и отправляет их на сохранение в хранилище. Не важное какое хранилище, на входе у него всегда эти DTO.
Чего и откуда извлекаем? У нас list<T> — хранилище. Ты для него будет маппинги T на T писать?

G>>>>2) В случае базы данных вместо одного апдейта в базу улетит 100500?

V>>>Не обязательно. Скорее всего, не важно.
G>>Скорее всего очень важно. Примерно на два порядка будет отличаться время работы в зависимости от реализации.
V>Хранилище на входе получает список DTO со всеми изменёнными данными и вольно делать с ними всё, что пожелает: упаковать в один запрос к БД, в несколько, как угодно. Проблемы с этим решаются на уровне кода хранилища, другой код от вносимых изменений зависеть не будет.
Каким образом интересно?
Как из набора запросов вида
update T set F=F+50 where ID=1
update T set F=F+50 where ID=4
update T set F=F+50 where ID=7
...

Получить запрос

update T set F=F+50 where Category=x

?

V>На практике у веб-сервиса есть подходящий API для выборки данных, хотя бы простой поиск.

Это очень сильное предположение. Я гораздо больше веб-сервисов видел без методов поиска, чем с ним.


V>Эффективный код в отношении изменения зарплаты сотрудников должен быть атомарным. Мы это достигаем за счёт аккумулирования всех изменений в одном вызове SaveChangesAsync. Будет он выполняться 50 мс или 10 секунд — дело десятое и легко решаемое, для задачи гораздо важнее гарантированное выполнение или чёткий откат в случае сбоя.

Прости, а как ты обеспечишь атомарность для:
1) Веб-сервиса, которому нужно PUT на каждый объект
2) List<T> в памяти?

Или у тебя контракт репозитария меняется в зависимости от реализации?


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

V>С изменением требований я сталкиваюсь постоянно. Сегодня надо работать с таким источником данных, завтра с ещё одним. Использую описанный подход и не имею особых проблем.
Это значит что у тебя приложения примитивные, возможно однопользовательские. Тогда действительно можно репозитариями пользоваться.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.