Здравствуйте, another_coder, Вы писали:
_>Здравствуйте, gandjustas, Вы писали:
G>>Вам не надо тестировать List<T>. А если выборки повторяются, то делаете extension-метод для List<Person>.
_>А если ему надо по-разному работать с List<T> (хранилищем) в зависимости от кастомера? Разные выборки без изменения основной логики.
Здравствуйте, gandjustas, Вы писали:
Q>>А причем тут БД, а если нужно хранить данные просто в памяти, а для хранения скидывать их в файл через серелизацию, как тогда организовывать работу с данными? G>При том, что без БД репозиторий имеет еще меньше смысла..
А при чем тут вообще какая-либо конкретная реализация? Списки, БД... почему вы не рассматриваете удаленный веб-сервис, например, в таком случае?
Задача любого архитектурного паттерна — фрагментация сложности. Паттерны DAL отделяют сложность бизнес-логики от сложности работы с хранилищем данных с помощью разного вида интерфейсов. Repository абстрагирует БД как коллекцию, TDG как объектный интерфейс к таблице, CQRS изолирует отдельные операции и т.д. Архитектурные паттерны — это интерфейсы, реализация которых может быть абсолютно любой. Используя их, вы говорите: клиенту должно быть всё равно, что за этим интерфейсом, пока они соблюдают контракт. Изменения в реализации, например, оптимизации производительности или журналирование, надежно скрыты за этим контрактом и не ломают клиентский код.
Реализация в виде хранилища в памяти тут просто удобная плюшка для ранних этапов разработки и юнит-тестов.
Здравствуйте, Baudolino, Вы писали:
B>Здравствуйте, gandjustas, Вы писали:
Q>>>А причем тут БД, а если нужно хранить данные просто в памяти, а для хранения скидывать их в файл через серелизацию, как тогда организовывать работу с данными? G>>При том, что без БД репозиторий имеет еще меньше смысла.. B>А при чем тут вообще какая-либо конкретная реализация? Списки, БД... почему вы не рассматриваете удаленный веб-сервис, например, в таком случае?
Потому что с веб-сервисом, базой данных и списком в памяти работа ведется совершенно по-разному.
1) Список в памяти можно обойти весь оператором foreach
2) К веб-сервису можно сделать запрос с определенными параметрами
3) К базе можно сделать SQL запрос, а еще она поддерживает транзакции.
Как вы эти три принципиально разные операции спрячете за одним универсальным интерфейсом?
В C# кстати придумали такой универсальный интерфейс — linq запросы. Но свой linq провайдер мало кто пишет, пользуется готовыми.
Вот и ответ на вопрос почему паттерн Repository бесполезен в наше время.
B>Задача любого архитектурного паттерна — фрагментация сложности. Паттерны DAL отделяют сложность бизнес-логики от сложности работы с хранилищем данных с помощью разного вида интерфейсов.
Обычная функциональная декомпозиция тоже занимается фрагметацией сложности. Для этого не нужно создавать отдельные сущности и паттерны.
И вообще никто не говорит, что надо в батонклике вызывать SqlCommand. Нужно использовать функциональную декомпозицию.
B>Repository абстрагирует БД как коллекцию
Это первая и главная ошибка. Коллекцция объектов в памяти и таблица в БД обладают принципиально разными свойствами с точки зрения кода, даже если можно их свести к одному интерфейсу.
B>Архитектурные паттерны — это интерфейсы, реализация которых может быть абсолютно любой.
Не может, у них контракты разные. См выше.
B>Изменения в реализации, например, оптимизации производительности или журналирование, надежно скрыты за этим контрактом и не ломают клиентский код.
Для этого снова не нужен репозиторий как паттерн.
B>Реализация в виде хранилища в памяти тут просто удобная плюшка для ранних этапов разработки и юнит-тестов.
Само по себе добавление репозитория на ранних этапах — бесполезное усложнение кода. Можно банально обращаться к статическим спискам в памяти пока не появится необходимость сохранять данные.
Здравствуйте, gandjustas, Вы писали:
G>Здравствуйте, Qulac, Вы писали:
Q>>Здравствуйте, gandjustas, Вы писали:
G>>>Здравствуйте, Qulac, Вы писали:
IT>>>>>Потому что в последние лет 8 появились более продвинутые способы работы с БД. Q>>>>А причем тут БД, а если нужно хранить данные просто в памяти, а для хранения скидывать их в файл через серелизацию, как тогда организовывать работу с данными? G>>>При том, что без БД репозиторий имеет еще меньше смысла.
G>>>Если у вас тупо коллекция в памяти, то это List<T>. На крайняк Dictionary<TKey, T>. В нужные моменты времени они сериализуются в файл, а при запуске программы десериализуются из файла.
Q>>Не ну это естественно, что внутри нашей коллекции будет List, Dictionary или что то еще подобное. Смысл: у нас ни чего не торчит лишнего через интерфейс, а если какие-то выборки данных повторяются в программе в многих местах, то здесь мы их объедением в нашей коллекции в виде методов. Вся логика работы с данными в одном месте, проще тестировать.
G>В List<T> есть лишнее? Логика в разных местах? Вы о чем вообще? G>Если вам в программе нужен список людей, например, то зачем городить что-то поверх List<T>?
Зачем вообще тогда нужна архитектура по, разделение интерфейсов и прочее, прочее. Мы ведь про архитектуру говорим или нет? Тогда вообще ни чего не нужно, можно писать как бог на душу положит.
G>Вам не надо тестировать List<T>. А если выборки повторяются, то делаете extension-метод для List<Person>.
Это частный случай решения проблемы, он не решает проблему слишком широкого интерфейса list, кто муже есть не во всех языках.
Здравствуйте, Qulac, Вы писали:
G>>В List<T> есть лишнее? Логика в разных местах? Вы о чем вообще? G>>Если вам в программе нужен список людей, например, то зачем городить что-то поверх List<T>?
Q>Зачем вообще тогда нужна архитектура по, разделение интерфейсов и прочее, прочее. Мы ведь про архитектуру говорим или нет? Тогда вообще ни чего не нужно, можно писать как бог на душу положит.
Архитектура это не тогда, когда много паттернов, а когда сделано ровно столько, сколько нужно, чтобы решить задачу и не изобретать велосипеды.
G>>Вам не надо тестировать List<T>. А если выборки повторяются, то делаете extension-метод для List<Person>. Q>Это частный случай решения проблемы, он не решает проблему слишком широкого интерфейса list, кто муже есть не во всех языках.
А в чем интерфейс List слишком широк? И почему это вообще должно быть проблемой?
На мой взгляд, вы не разделяете сущности от их технической реализации. В примере с тремя источниками данных, они все предлставляют собой одно и то же: хранилище данных. Для модуля системы, который использует хранилище данных, не важно что именно это (БД, IList, файл или web service). Весь функционал, который относится к доступу к данным спрятан там же и наружу не показывается. И вот тут как раз приходин на помощь объект, представляющий собой DAO. Конкретная его реализация может быть разной и зависить от уровня закладываемой абстракции в архитектуру. Это может быть EF, а может быть и просто объект с простым CRUD интерфейсом.
Вам это описание понятно?
В тексте Вы постоянно подразумеваете конкретную техническую реализацию, хотя это, в данным случае, не имеет значения.
Здравствуйте, another_coder, Вы писали:
_>Здравствуйте, gandjustas.
_>На мой взгляд, вы не разделяете сущности от их технической реализации. В примере с тремя источниками данных, они все предлставляют собой одно и то же: хранилище данных. Для модуля системы, который использует хранилище данных, не важно что именно это (БД, IList, файл или web service). Весь функционал, который относится к доступу к данным спрятан там же и наружу не показывается. И вот тут как раз приходин на помощь объект, представляющий собой DAO. Конкретная его реализация может быть разной и зависить от уровня закладываемой абстракции в архитектуру. Это может быть EF, а может быть и просто объект с простым CRUD интерфейсом.
Ок, давайте конкретнее. Пусть у вас есть "хранилище данных" сотрудников.
Фактически это будет три разных хранилища:
1) Список в памяти — List<T>
2) База данных
3) Веб-сервис, который имеет только методы получения и сохранения по ID.
У вас задача поднять сотрудникам определенной категории зарплату на 10%.
Какой интерфейс универсального "хранилища данных" вы спроектируете для решения этой задачи.
Естественно писать заведомо неэффективный код — моветон.
Здравствуйте, another_coder, Вы писали:
_>Здравствуйте, gandjustas, Вы писали:
G>>По-разному это как? Приведи пример.
_>Ну например, 1 выбирает по одному флагу, 2й выбирает по двум. Система мультитенант, и логика работы определяется динамически. Хранилище у всех IList.
Сделать две функции не?
Здравствуйте, gandjustas, Вы писали:
G>Как вы эти три принципиально разные операции спрячете за одним универсальным интерфейсом?
Есть такое слово "абстракция", знаете? Давайте вспомним его определение: абстракция — это техника анализа, в которой выявляются существенные аспекты, а несущественные исключаются. Как работает абстракция в объектно-ориентированном анализе? Вы определяете аспекты поведения объекта, существенные для клиента, скрывая (инкапсулируя) детали, для него не существенные. Как это работает в случае с паттерном "репозиторий" на примере упомянутых вами операций?
1. Клиенту нужен foreach: репозиторий должен уметь возвращать итератор по хранящимся в нем объектам. Это может быть реализовано за счет обращения к хранилищу и кэширования результатов для оптимизации производительности. Если хранилище — область оперативной памяти, кэш не требуется, если удаленный сервис или СУБД — можно вычитывать блоки данных и сохранять в кэш.
2. Клиенту нужен поиск по параметрам: репозиторий должен предоставлять метод поиска с параметрами. Реализация будет строить фильтр или формировать запрос к хранилищу — вариантов много.
3. Клиенту нужна транзакционность: ок, но это обычно делается на уровне бизнес-логики (менеджер транзакций должен использовать общие сессии вместе со всеми транзакционными службами, не только с репозиториями, но и, например, очередями). Если вдруг вы решили все же сделать поддержку транзакций частью репозитория, придется, разумеется реализовывать ее логику.
G>В C# кстати придумали такой универсальный интерфейс — linq запросы. Но свой linq провайдер мало кто пишет, пользуется готовыми. G>Вот и ответ на вопрос почему паттерн Repository бесполезен в наше время.
LINQ представляет собой удобный интерфейс описания возможных запросов к объектам. В случае с БД, таким объектом является компонент DAL, если точнее — ORM.
Факт существования LINQ, вообще говоря, ничего не означает.
B>>Задача любого архитектурного паттерна — фрагментация сложности. Паттерны DAL отделяют сложность бизнес-логики от сложности работы с хранилищем данных с помощью разного вида интерфейсов. G>Обычная функциональная декомпозиция тоже занимается фрагметацией сложности. Для этого не нужно создавать отдельные сущности и паттерны.
Паттерны стандартизируют такую декомпозицию, предлагая типовой подход к решению типовых задач. Отказываться от их использования там, где оно оправдано, — изобретать ненужный велосипед.
B>>Repository абстрагирует БД как коллекцию G>Это первая и главная ошибка. Коллекцция объектов в памяти и таблица в БД обладают принципиально разными свойствами с точки зрения кода, даже если можно их свести к одному интерфейсу.
С точки зрения сферического коня в вакууме возможно всё. С точки зрения конкретного клиентского кода принципиальных различий может и не быть.
B>>Архитектурные паттерны — это интерфейсы, реализация которых может быть абсолютно любой. G>Не может, у них контракты разные.
Контракт определяет интерфейс, а не его реализация. Реализация обязана соблюдать контракт по определению.
B>>Реализация в виде хранилища в памяти тут просто удобная плюшка для ранних этапов разработки и юнит-тестов. G>Само по себе добавление репозитория на ранних этапах — бесполезное усложнение кода. Можно банально обращаться к статическим спискам в памяти пока не появится необходимость сохранять данные.
У вас десять классов, работающих с хранилищем объектов типа А. Что проще — поменять в одном месте реализацию интерфейса хранилища объектов, или поменять во всех местах работу с ним со списка на что-то иное?
P.S. Давайте для более конструктивного разговора уточним позиции. Я не утверждаю, что репозиторий нужен всегда — скорее, я имею в виду, что у этого паттерна есть смысл и область применения, поэтому утверждение что он "не нужен вообще" не является истинным и связано, скорее, с непониманием этого смысла и области применения.
Q>>Зачем вообще тогда нужна архитектура по, разделение интерфейсов и прочее, прочее. Мы ведь про архитектуру говорим или нет? Тогда вообще ни чего не нужно, можно писать как бог на душу положит.
G>Архитектура это не тогда, когда много паттернов, а когда сделано ровно столько, сколько нужно, чтобы решить задачу и не изобретать велосипеды.
Для этого и придуманы паттерны. Современная архитектура -- это взаимодействие паттерноподобных сущностей, абстракций. А гофосккие паттерны -- платоновский идеал.
Здравствуйте, Baudolino, Вы писали:
B>Здравствуйте, gandjustas, Вы писали:
G>>Как вы эти три принципиально разные операции спрячете за одним универсальным интерфейсом? B>Есть такое слово "абстракция", знаете? Давайте вспомним его определение: абстракция — это техника анализа, в которой выявляются существенные аспекты, а несущественные исключаются.
Вы несущественными не то объявили.
Несущественные различия это делать Repository или extension-методы для List<T>. Это различие не влияет на характеристики программы.
А тип источника данных очень сильно влияет.
B>1. Клиенту нужен foreach: репозиторий должен уметь возвращать итератор по хранящимся в нем объектам. Это может быть реализовано за счет обращения к хранилищу и кэширования результатов для оптимизации производительности. Если хранилище — область оперативной памяти, кэш не требуется, если удаленный сервис или СУБД — можно вычитывать блоки данных и сохранять в кэш. B>2. Клиенту нужен поиск по параметрам: репозиторий должен предоставлять метод поиска с параметрами. Реализация будет строить фильтр или формировать запрос к хранилищу — вариантов много. B>3. Клиенту нужна транзакционность: ок, но это обычно делается на уровне бизнес-логики (менеджер транзакций должен использовать общие сессии вместе со всеми транзакционными службами, не только с репозиториями, но и, например, очередями). Если вдруг вы решили все же сделать поддержку транзакций частью репозитория, придется, разумеется реализовывать ее логику.
Отлично — у вас есть веб-сервис, обычный web api с Get и Post по ключу. А вы напроектировани репозиторий с поиском по параметрам. Что дальше делать?
И стоило его изначально таким делать?
G>>В C# кстати придумали такой универсальный интерфейс — linq запросы. Но свой linq провайдер мало кто пишет, пользуется готовыми. G>>Вот и ответ на вопрос почему паттерн Repository бесполезен в наше время. B>LINQ представляет собой удобный интерфейс описания возможных запросов к объектам. В случае с БД, таким объектом является компонент DAL, если точнее — ORM. B>Факт существования LINQ, вообще говоря, ничего не означает.
Факт существования ORM_ов c поддержкой Linq означает. Потому что Linq может за одинаковым интерфейсом скрыть и список в памяти, и веб-сервисы (с ограничениями) и базы данных.
Но писать такое с нуля для одного приложения никто не будет, надо пользоваться готовым. Поэтому паттерн repository категорически не в тему, надо пользоваться orm.
B>>>Задача любого архитектурного паттерна — фрагментация сложности. Паттерны DAL отделяют сложность бизнес-логики от сложности работы с хранилищем данных с помощью разного вида интерфейсов. G>>Обычная функциональная декомпозиция тоже занимается фрагметацией сложности. Для этого не нужно создавать отдельные сущности и паттерны. B>Паттерны стандартизируют такую декомпозицию, предлагая типовой подход к решению типовых задач. Отказываться от их использования там, где оно оправдано, — изобретать ненужный велосипед.
Repository сам по себе велосипед при наличии ORM.
Вы еще докажите оправданность репозитория по сравнению с обычной декомпозицией.
B>>>Repository абстрагирует БД как коллекцию G>>Это первая и главная ошибка. Коллекцция объектов в памяти и таблица в БД обладают принципиально разными свойствами с точки зрения кода, даже если можно их свести к одному интерфейсу. B>С точки зрения сферического коня в вакууме возможно всё. С точки зрения конкретного клиентского кода принципиальных различий может и не быть.
Принципиальное различие в скорости работы. Как только вызовы начинают пересекать граници процесса надо внимательно следить как часто происходят обращения и сколько данных передается. Иначе получается тормозное говно.
И это тоже часть архитектуры. Причем гораздо более важная, чем паттерны.
B>>>Архитектурные паттерны — это интерфейсы, реализация которых может быть абсолютно любой. G>>Не может, у них контракты разные. B>Контракт определяет интерфейс, а не его реализация.
Ты чего сейчас сказал?
Контрат шире чем интерфейс. Например интерфейс не может описать сайд-эффекты.
Для ORMов контракт обычно такой — ты работает с коллекцией объектов в памяти, а потом вызываешь функцию сохранения изменений в БД. В интерфейсе сохранение никак не фигурирует. И ты можешь ошибочно подумать, что таблица в базе эквивалентна List<T>, хотя это совсем не так.
B>>>Реализация в виде хранилища в памяти тут просто удобная плюшка для ранних этапов разработки и юнит-тестов. G>>Само по себе добавление репозитория на ранних этапах — бесполезное усложнение кода. Можно банально обращаться к статическим спискам в памяти пока не появится необходимость сохранять данные. B>У вас десять классов, работающих с хранилищем объектов типа А. Что проще — поменять в одном месте реализацию интерфейса хранилища объектов, или поменять во всех местах работу с ним со списка на что-то иное?
Кто тебе сказал про десятки классов?
B>P.S. Давайте для более конструктивного разговора уточним позиции. Я не утверждаю, что репозиторий нужен всегда — скорее, я имею в виду, что у этого паттерна есть смысл и область применения, поэтому утверждение что он "не нужен вообще" не является истинным и связано, скорее, с непониманием этого смысла и области применения.
Я утверждаю, что у этого паттерна нет области применения, потому что для БД есть ORM, а для остальных случаев repository не подходит.
Здравствуйте, Sharov, Вы писали:
S>Здравствуйте, gandjustas, Вы писали:
Q>>>Зачем вообще тогда нужна архитектура по, разделение интерфейсов и прочее, прочее. Мы ведь про архитектуру говорим или нет? Тогда вообще ни чего не нужно, можно писать как бог на душу положит. G>>Архитектура это не тогда, когда много паттернов, а когда сделано ровно столько, сколько нужно, чтобы решить задачу и не изобретать велосипеды. S>Для этого и придуманы паттерны. Современная архитектура -- это взаимодействие паттерноподобных сущностей, абстракций. А гофосккие паттерны -- платоновский идеал.
Для этого придуманы библиотеки и компоненты, а паттерны нужны когда готовых средств нет.
Но огромное количество программистов вместо использования готового лепят паттерны, а потом в них заворачивают готовые компоненты, так как свою реализацию написать не способны и называют это архитектурой.
S>>Для этого и придуманы паттерны. Современная архитектура -- это взаимодействие паттерноподобных сущностей, абстракций. А гофосккие паттерны -- платоновский идеал. G>Для этого придуманы библиотеки и компоненты, а паттерны нужны когда готовых средств нет.
Пол-правды. Заиграть вместе придуманные библиотеки и компоненты тоже надо. Вот тут многие паттерны и пригождаются.
Здравствуйте, Sharov, Вы писали:
S>Здравствуйте, gandjustas, Вы писали:
S>>>Для этого и придуманы паттерны. Современная архитектура -- это взаимодействие паттерноподобных сущностей, абстракций. А гофосккие паттерны -- платоновский идеал. G>>Для этого придуманы библиотеки и компоненты, а паттерны нужны когда готовых средств нет. S>Пол-правды. Заиграть вместе придуманные библиотеки и компоненты тоже надо. Вот тут многие паттерны и пригождаются.
Но не repository, о нем же разговор, не?
Здравствуйте, Sharov, Вы писали:
S>Пол-правды. Заиграть вместе придуманные библиотеки и компоненты тоже надо. Вот тут многие паттерны и пригождаются.
Из практики — наоборот.
Хорошие библиотеки просто подключаются и используются. А вот если автор был укушен Фаулером, то без костылей, которые превращают сфероконину в рабочий код, не обойтись.
Я ещё не видел ни одного случая, когда дизайн "от паттернов" не разбивался бы вдребезги при попытке реального использования. Даже если общий дизайн отлично продуман и за идеями есть солидный бэкграунд, всё равно даже простейшие вещи неизбежно требуют обкладывания хелперами.
Желающие поспорить могут посмотреть на популярность Rx, TPL DataFlow или CodeContracts.
Здравствуйте, Sinix, Вы писали:
S>Здравствуйте, Sharov, Вы писали:
S>>Пол-правды. Заиграть вместе придуманные библиотеки и компоненты тоже надо. Вот тут многие паттерны и пригождаются. S>Из практики — наоборот.
"Многие паттерны" следует заменить на "некоторые паттерны", согласен. Архитектуры бывают разные и иногда это не просто подключил 10 сторонних библиотек и используешь.
S>Хорошие библиотеки просто подключаются и используются. А вот если автор был укушен Фаулером, то без костылей, которые превращают сфероконину в рабочий код, не обойтись.
1)Архитектуры бывают разные и иногда это не просто подключил 10 сторонних библиотек и используешь.
2)Библиотеки, за исключением базовых типа io, маршалинга, синх. примитиовов и проч. не из воздуха берутся.
S>Я ещё не видел ни одного случая, когда дизайн "от паттернов" не разбивался бы вдребезги при попытке реального использования. Даже если общий дизайн отлично продуман и за идеями есть солидный бэкграунд, всё равно даже простейшие вещи неизбежно требуют обкладывания хелперами.
Это уже здесь обсуждалось раз 100500. Я ни в коем случае(!!!) не призываю разрабатывать от паттернов. Но. Это типовые решения -- раз, это некоторый язык общения разработчиков -- два. А mvc это вообще основа всех основ. На этом форуме все это обсуждалось 3-4 года назад и хватит.
S>Желающие поспорить могут посмотреть на популярность Rx, TPL DataFlow или CodeContracts.
Если я правильно понял Ваш посыл, то:
1) этот список можно долго дополнять;
2) смысл сравнивать слабый маркетинг и инженерные решения?
Если было бы надо, ms на силу впарило бы это все. Желания не було. Вот можно подумать win32 гений инженерной мысли, однако люди-то пользовались.
ЗЫ:Вот я это написал, и как водится перечитал сообщения на которое отвечаю -- что в этом списке делает TPL, у него вроде все неплохо? Я точно правильно понял Ваш посыл?
Здравствуйте, Sharov, Вы писали:
S>Это уже здесь обсуждалось раз 100500. Я ни в коем случае(!!!) не призываю разрабатывать от паттернов. Но. Это типовые решения -- раз, это некоторый язык общения разработчиков -- два. А mvc это вообще основа всех основ. На этом форуме все это обсуждалось 3-4 года назад и хватит.
Аминь!
Здравствуйте, Sharov, Вы писали:
S>1)Архитектуры бывают разные и иногда это не просто подключил 10 сторонних библиотек и используешь.
Если библиотеку писали люди, осилившие FDG — именно что подключается и используется. Посмотри на сам фреймворк — полно отличных примеров и хорошего дизайна, и хорошего, но перенавороченного. А вот примеры из разряда "не делайте так вообще" по пальцам пересчитать можно и в основном это или наследство от fw 1.0 или последствия попытки поиграть в "мы модные и современные" с .Net Core.
S>2)Библиотеки, за исключением базовых типа io, маршалинга, синх. примитиовов и проч. не из воздуха берутся.
Да ладно. Публичное API, если его вообще делают целенаправленно, а не постфактум — именно что набор хороших идей с других похожих библиотек + правки по опыту догфудинга. Проблемы в основном возникают, когда решения перетягиваются в лоб с других платформ людьми, которые дотнет знают слабовато. Вот тогда да — обнять и плакать
S>>Желающие поспорить могут посмотреть на популярность Rx, TPL DataFlow или CodeContracts.
S>Если я правильно понял Ваш посыл, то: S>2) смысл сравнивать слабый маркетинг и инженерные решения?
Не, я именно про удобство использования — все вышеперечисленные требуют держать в голове ментальную модель самой библиотеки (местами крайне нелогичную) и пересказывать свои хотелки в терминах этой модели. Что ставит однозначный крест на сколько-нибудь широком использовании.
Ради справедливости, Rx сам по себе очень даже неплох, а свежие версии Code Contracts в принципе почти пригодны к использованию в продакшне. Но задел на старте что там, что там был прокакан (пардон мой французский) прям образцово. А проблема всё та же, что сейчас с .Net Core — внезапно™ выяснилось, что идея забить на реальные сценарии использования немножко не работает.
S>Если было бы надо, ms на силу впарило бы это все. Желания не було. Вот можно подумать win32 гений инженерной мысли, однако люди-то пользовались.
Угу. И сколько таких мазохистов осталось после появления хоть какой-то альтернативы?
S>ЗЫ:Вот я это написал, и как водится перечитал сообщения на которое отвечаю -- что в этом списке делает TPL, у него вроде все неплохо? Я точно правильно понял Ваш посыл?
Не TPL, а TPL Dataflow. У них своя атмосфера