Со всем согласен.
W>Ты имел дело с базами, используемыми несколькими приложениями, да еше написанными на разных языках? Наверняка имел. Там не было ни одной хранимки?
Сейчас вам возразят, что для интеграции приложений шаринг базы данных не самый удачный подход. Лучше либо API аля wcf сервися, а еще лучше message based подход поверх какого-нибудь rabbitmq
Здравствуйте, Gattaka, Вы писали:
G>Сейчас вам возразят, что для интеграции приложений шаринг базы данных не самый удачный подход. Лучше либо API аля wcf сервися, а еще лучше message based подход поверх какого-нибудь rabbitmq
Я говорю не про интеграцию, а про накопленные данные, которые нужны разным приложениям. А другие приложения их пополняют. Против API и message based ничего не имею, но ситуации разные бывают.
Здравствуйте, wildwind, Вы писали:
W>Я говорю не про интеграцию, а про накопленные данные, которые нужны разным приложениям. А другие приложения их пополняют. Против API и message based ничего не имею, но ситуации разные бывают.
Здравствуйте, Gattaka, Вы писали: G>Сейчас вам возразят, что для интеграции приложений шаринг базы данных не самый удачный подход.
Конечно. Даже с одним приложением всегда есть риск разъехаться в версиях базы и клиента. А когда у нас N приложений, да ещё и на разных языках, то обязательно нужен App Server между данными и клиентами, который гарантирует консистентность бизнес-логики.
В таком сценарии использование ХП — это попытка превратить RDBMS в тот самый апп-сервер. Т.е. клиентам закрывают доступ к таблицам; в лучшем случае даём read-only, хотя даже это адски опасно (потому что всегда есть риск, что мы добавили колоночку типа IsDeleted, а где-то в углу завалялся клиент на дельфи, который ничего про неё не знает, и продолжает хреначить репорты с неуловимо отличающимися от официальных цифр данными).
Пусть фигачат хранимки.
Тут мы быстро приезжаем в то, что SQL Server — это плохой AppServer. Во-первых, у него неудачный протокол взаимодействия. Он категорически не может работать с недоверенными клиентами — достаточно сделать begin tran, выполнить процедурку, и оставить соединение открытым, чтобы все остальные ушли курить.
Во-вторых, стандартные ХП написаны в соответствии с парадигмой RPC, неработоспособность которой в сетях уже не обсосал только ленивый.
Банальная штука — ну вот есть у вас процедура, которая должна помечать узлы (или что вы там рассказывали про 700000 записей в своей задаче?...).
Вот я её с клиента позвал. А в ответ мне прилетает connection reset by peer. Что-то там в сеточке взглюкнуло. Что мне делать? Транзакция сработала или таки нет?
Для борьбы с этим 15 лет назад придумали REST, где можно обеспечить идемпотентность.
Вот вы сходу сможете написать свою процедуру идемпотентной? А как отличить идемпотентную от безопасной, и обе от небезопасной?
В итоге, написание клиента, который имеет гарантированную семантику, превращается из лёгкого и приятного занятия в титанический труд по оборачиванию вызовов во всяческие стратегии. Либо имеем приложение, которое работает кое-как — то есть периодически его надо перезапускать, и руками/глазами смотреть, что из последних действий надо повторять.
Чтобы сделать к SQL Server RESTful API на ХП, надо много и упорно трудиться. И всё равно получится не так хорошо, как поверх существующих платформ. Не обязательно WCF — выбор сейчас богатый.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, Gattaka, Вы писали: G>>Сейчас вам возразят, что для интеграции приложений шаринг базы данных не самый удачный подход. S>Конечно. Даже с одним приложением всегда есть риск разъехаться в версиях базы и клиента. А когда у нас N приложений, да ещё и на разных языках, то обязательно нужен App Server между данными и клиентами, который гарантирует консистентность бизнес-логики.
Ну так проблема версий сервера везде существует. Разве не может получится разных версий API и клиентов? Запросто... В БД вы просто делаете таблицу с текущим номером версии схемы и остальные приложения в эту таблицу смотрят. Делов то... В случае с сервером с АPI используется аналогичный подход, так что это не то чем уж так разительно подходы отличаются.
S>В таком сценарии использование ХП — это попытка превратить RDBMS в тот самый апп-сервер. Т.е. клиентам закрывают доступ к таблицам; в лучшем случае даём read-only, хотя даже это адски опасно (потому что всегда есть риск, что мы добавили колоночку типа IsDeleted, а где-то в углу завалялся клиент на дельфи, который ничего про неё не знает, и продолжает хреначить репорты с неуловимо отличающимися от официальных цифр данными). S>Пусть фигачат хранимки.
DML — нужно запрещать... У вас ведь с App сервером тоже никто контракт внезапно поменять не может. Добавить поле в DTO IsDeleted?
S>Тут мы быстро приезжаем в то, что SQL Server — это плохой AppServer. Во-первых, у него неудачный протокол взаимодействия. Он категорически не может работать с недоверенными клиентами — достаточно сделать begin tran, выполнить процедурку, и оставить соединение открытым, чтобы все остальные ушли курить. S>Во-вторых, стандартные ХП написаны в соответствии с парадигмой RPC, неработоспособность которой в сетях уже не обсосал только ленивый. S>Банальная штука — ну вот есть у вас процедура, которая должна помечать узлы (или что вы там рассказывали про 700000 записей в своей задаче?...). S>Вот я её с клиента позвал. А в ответ мне прилетает connection reset by peer. Что-то там в сеточке взглюкнуло. Что мне делать? Транзакция сработала или таки нет? S>Для борьбы с этим 15 лет назад придумали REST, где можно обеспечить идемпотентность. S>Вот вы сходу сможете написать свою процедуру идемпотентной? А как отличить идемпотентную от безопасной, и обе от небезопасной? S>В итоге, написание клиента, который имеет гарантированную семантику, превращается из лёгкого и приятного занятия в титанический труд по оборачиванию вызовов во всяческие стратегии. Либо имеем приложение, которое работает кое-как — то есть периодически его надо перезапускать, и руками/глазами смотреть, что из последних действий надо повторять. S>Чтобы сделать к SQL Server RESTful API на ХП, надо много и упорно трудиться. И всё равно получится не так хорошо, как поверх существующих платформ. Не обязательно WCF — выбор сейчас богатый.
Зато есть преимущества, которые никто больше не может перекрыть. Это скорость. И огромная куча функционала под капотом. Мне, например, нравится пример с коллекцией в памяти, которую куча потоков модифицирует в памяти. Как организоывать блокировки? Для каждой строчки read-write lock, а блокировки на диапозоны, а что насчет эскалации блокировок. В SQL Server этот код уже написан, отлажен и работает максимально эффективно. Если вы будете делать что-то аналогичное, то либо потратите кучу времени и напишите кучу кода, либо получите неэффективное решение.
В случае с SQL Server у вас данные в едином месте и управляются единым кодом — там все максимально эффективно, нет лишних сериализаций, переливаний из сущностей в DTO и т.п.
Здравствуйте, wildwind, Вы писали:
W>Странно слышать столь категоричные утверждения от человека с большим опытом. Хранимки это API к базе, один из видов.
Задача базы данных надёжно хранить данные и обеспечивать к ним быстрый доступ, а не представлять собой кривеньский API безнеслогики.
W>Ты имел дело с базами, используемыми несколькими приложениями, да еше написанными на разных языках? Наверняка имел. Там не было ни одной хранимки?
Были. Уже нету. Для нескольких приложений всегда можно написать общий модуль. Для разнородной системы соответственно какой-ниубдь веб-сервер или сервер приложений.
W>А масштабируемость вот при чем. В процессе масштабирования обязательно наступает период, когда нужно выжать из СУБД максимум, чтобы оттянуть апгрейд железа. Начинается поиск вещей, которые эффективнее выполнить внутри базы, чем гонять данные по сети и растягивать транзакции. И ради эффективности приходится жертвовать читаемостью, сопровождаемостью и еще чем-то из чеклиста "идеальный проект". А хранимки позволяют это смягчить. Если их не использовать, то получишь те же "хранимки", но обфусцированные, хранящиеся в коде и создаваемые каждый раз на время выполнения. Что еще хуже.
Толи в этой, толи в соседней теме я уже говорил, что прекрасно справляюсь с такими задачами без всяких сохранённых процедур. Без затягивания данных на клиента, эффективно внутри базы и без жертв типа читаемость и сопровождаемость.
W>Их как, тоже нельзя?
Это кто будет поддерживать? DBA или девелопер?
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, Sinclair, Вы писали:
S>Тут мы быстро приезжаем в то, что SQL Server — это плохой AppServer. Во-первых, у него неудачный протокол взаимодействия. Он категорически не может работать с недоверенными клиентами
Стоп, а в какой момент наш клиент вдруг стал недоверенным? Тот же клиент, не использующий хранимки, будет доверенным? Что-то я теряю твою мысль.
S>достаточно сделать begin tran, выполнить процедурку, и оставить соединение открытым, чтобы все остальные ушли курить.
Это и с аппсервером может случиться из-за бага.
S>Вот я её с клиента позвал. А в ответ мне прилетает connection reset by peer. Что-то там в сеточке взглюкнуло. Что мне делать? Транзакция сработала или таки нет?
Если явный коммит не подтвержден, значит не сработала. Есть другие варианты?
И опять же, в чем разница между хранимкой, батчем и серией простых SQL операторов?
Здравствуйте, IT, Вы писали:
W>>Ты имел дело с базами, используемыми несколькими приложениями, да еше написанными на разных языках? Наверняка имел. Там не было ни одной хранимки? IT>Были. Уже нету. Для нескольких приложений всегда можно написать общий модуль. Для разнородной системы соответственно какой-ниубдь веб-сервер или сервер приложений.
Можно. Только стоит ли?
IT>Толи в этой, толи в соседней теме я уже говорил, что прекрасно справляюсь с такими задачами без всяких сохранённых процедур. Без затягивания данных на клиента, эффективно внутри базы и без жертв типа читаемость и сопровождаемость.
Ты, как автор linq2db, не показатель.
IT>Это кто будет поддерживать? DBA или девелопер?
И тот и другой может, по обстоятельствам. А какая разница?
G>Так ли плохо реализовывать бизнес логику в высокопроизводительных хранимых процедурах?
Бизнес-логика имеет свойство часто меняться, и кто должен изменения вносить в ХП?
В итоге все выльется в то, что пользователи будут выгружать плоские таблицы сырых данных простым запросом, типа select * from ..., в Excel и уже в Excel'е выкручивать из них, что им нужно, а хранимки так и останутся никому не нужные.
Здравствуйте, wildwind, Вы писали:
W>Можно. Только стоит ли?
Если единственная альтернатива — ХП, то вне всякого сомнения.
IT>>Толи в этой, толи в соседней теме я уже говорил, что прекрасно справляюсь с такими задачами без всяких сохранённых процедур. Без затягивания данных на клиента, эффективно внутри базы и без жертв типа читаемость и сопровождаемость. W>Ты, как автор linq2db, не показатель.
Я это всё делал за долго до линка.
IT>>Это кто будет поддерживать? DBA или девелопер? W>И тот и другой может, по обстоятельствам.
А отвечать кто будет? Тоже по обстоятельствам?
W>А какая разница?
Разница такая. Если DBA мне не мешает, то пусть занимается своими DBA'скими штучками на чём угодно. Если же поддержкой этого кода буду заниматься я, то никаких ХП.
Если нам не помогут, то мы тоже никого не пощадим.
S>foreach(var employee in Db.GetAllEmployees())
S>{
S> if (employee.CurrentPosition = position)
S> {
S> var c = Db.FindContractByEmployee(employee);
S> c.AdjustSalary(c.CurrentSalary + c.CurrentSalary * 0.10, effectiveDate);
S> }
S>}
S>
Подозрительная у вас rich model... В частности вызов метод Db.FindContractByEmployee(employee)
foreach(var employee in Db.GetAllEmployees())
{
if (employee.CurrentPosition = position)
{
var c = employee.Contracts.FirstOrDefault();// Либо Where... все обеспечивается ORM. С linq2db такой код не получится писать я так понимаю. Есть там LazyLoad?
c.AdjustSalary(c.CurrentSalary + c.CurrentSalary * 0.10, effectiveDate);
}
}
Здравствуйте, Gattaka, Вы писали:
G>Ну так проблема версий сервера везде существует. Разве не может получится разных версий API и клиентов? Запросто... В БД вы просто делаете таблицу с текущим номером версии схемы и остальные приложения в эту таблицу смотрят. Делов то...
Проблема не в этом, а в том, что логика в каждом из приложений реализована немножко по-другому. В одном округляется до 2х знаков после запятой, а в другом — до 4х. G>В случае с сервером с АPI используется аналогичный подход, так что это не то чем уж так разительно подходы отличаются.
Нет, в случае с сервером нельзя забыть "посмотреть в таблицу", потому что версия API уезжает в сервер в обязательном порядке в составе URL.
И даже если вы первую версию АПИ выпустили не подумав про версионирование, то всегда можете положить новый API "рядом" с существующим.
G>DML — нужно запрещать... У вас ведь с App сервером тоже никто контракт внезапно поменять не может. Добавить поле в DTO IsDeleted?
А при чём тут DTO? Мы добавили в схему поле isDeleted, и подпилили код единственного апп-сервера так, чтобы при попытке прочитать такой ресурс получалось 410 Gone, а не данные.
Если внутри апп-сервер устроен нормально (например, вместо чистого sql использует linq), то мы фильтрацию по isDeleted = 0 ставим в единственном месте, которое отвечает за возврать IQueryable<MyEntity> MyEntities. И имеем желаемый накал.
G>Зато есть преимущества, которые никто больше не может перекрыть. Это скорость.
Скорость чего? И по сравнению с чем? Скорость исполнения? Я вас разочарую — ХП исполняется настолько же быстро, сколько и эквивалентный ей SQL батч.
Скорость написания — в разы хуже, потому что язык хреновый. С# по скорости написания корректного кода уделывает любой диалект SQL. G>И огромная куча функционала под капотом. Мне, например, нравится пример с коллекцией в памяти, которую куча потоков модифицирует в памяти. Как организоывать блокировки? Для каждой строчки read-write lock, а блокировки на диапозоны, а что насчет эскалации блокировок. В SQL Server этот код уже написан, отлажен и работает максимально эффективно. Если вы будете делать что-то аналогичное, то либо потратите кучу времени и напишите кучу кода, либо получите неэффективное решение.
Если честно, то это плохой пример. Для коллекции в памяти иметь словарик rw-локов безо всякой иерархии окажется на несколько порядков эффективнее SQL Server. Просто потому, что он упирается в IOPS диска, а коллекция в памяти — в ширину шины.
Но дело не в этом, а в том, что никто не предлагает отказаться от SQL Server. Просто хранимки в нём для бизнес-логики не нужны. Бизнес-логика пусть будет в сервере приложений, который должен отправлять в сервер нужные нам батчи. Вместо хранимки на 50 килобайт с кучей ветвлений и corner cases у нас будут уезжать 5 килобайт стейтментов, которые делают то же самое.
G>В случае с SQL Server у вас данные в едином месте и управляются единым кодом — там все максимально эффективно, нет лишних сериализаций, переливаний из сущностей в DTO и т.п.
Вообще-то, максимально эффективно SQL Server работает только в рамках стейтментов. В рамках ХП есть много типичных приёмов для просада производительности.
К примеру, т.к. в SQL нет способа, например, передать "стейтмент" как аргумент метода, то для обобщения кода, который должен работать с разными источниками данных, обычно предварительно сливают промежуточные данные во временную таблицу, чтобы потом над ней уже выполнить общую часть алгоритма. Это второй (после курсоров) способ убить производительность сервера на корню. В linq таких ограничений нету, и мы можем на ходу генерировать нужные нам стейтменты. Это позволяет сочетать выразительную мощь современного языка программирования общего назначения с вычислительной эффективностью сиквельного оптимизатора запросов. Итоговая производительность будет лучше, чем у чистых хранимок.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Gattaka, Вы писали:
G>Подозрительная у вас rich model... В частности вызов метод Db.FindContractByEmployee(employee) G>
G>foreach(var employee in Db.GetAllEmployees())
G>{
G> if (employee.CurrentPosition = position)
G> {
G> var c = employee.Contracts.FirstOrDefault();// Либо Where... все обеспечивается ORM. С linq2db такой код не получится писать я так понимаю. Есть там LazyLoad?
G> c.AdjustSalary(c.CurrentSalary + c.CurrentSalary * 0.10, effectiveDate);
G> }
G>}
G>
Спасибо за исправление. Lazy Load в linq2db нет, и слава богу. Вы понимаете, чем ужасен этот код?
Если посмотреть на его исполнение под SQL Profiler, то волосы зашевелятся даже там, где их нет.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, Gattaka, Вы писали:
G>>Подозрительная у вас rich model... В частности вызов метод Db.FindContractByEmployee(employee) G>>
G>>foreach(var employee in Db.GetAllEmployees())
G>>{
G>> if (employee.CurrentPosition = position)
G>> {
G>> var c = employee.Contracts.FirstOrDefault();// Либо Where... все обеспечивается ORM. С linq2db такой код не получится писать я так понимаю. Есть там LazyLoad?
G>> c.AdjustSalary(c.CurrentSalary + c.CurrentSalary * 0.10, effectiveDate);
G>> }
G>>}
G>>
S>Спасибо за исправление. Lazy Load в linq2db нет, и слава богу. Вы понимаете, чем ужасен этот код? S>Если посмотреть на его исполнение под SQL Profiler, то волосы зашевелятся даже там, где их нет.
Ну да... у меня может и шевелятся Но есть сторонники, которые начнут доказывать, что это база данных виновата... Давайте на MongoDB переходить, там тормозов нет.
Здравствуйте, wildwind, Вы писали: W>Стоп, а в какой момент наш клиент вдруг стал недоверенным? Тот же клиент, не использующий хранимки, будет доверенным? Что-то я теряю твою мысль.
Никакому удалённому клиенту доверять нельзя. Доверенным для RDBMS может быть AppServer, потому что разрабатываем и развёртываем его мы, вместе с базой.
Все остальные клиенты — неизвестное зло.
Они будут выполнять delete * from users where 1=1 и прочее, если им это всё не запретить.
S>>достаточно сделать begin tran, выполнить процедурку, и оставить соединение открытым, чтобы все остальные ушли курить. W>Это и с аппсервером может случиться из-за бага.
Из-за бага в клиенте — нет. Мы полностью читаем запрос перед началом его исполнения. Ситуации типа "сидим, курим, ждём клиента" у нас в принципе быть не может (ну, если архитектор апп.сервера не полный идиот).
Если такое случилось в апп-сервере — мы его чиним. Он под нашим контролем.
W>Если явный коммит не подтвержден, значит не сработала. Есть другие варианты?
Конечно есть. Во-первых, мы вызвали процедуру с автокоммитом. Во-вторых, как вы отличите ситуацию "сервер не подтвердил транзакцию" от "клиент не получил отправленное подтверждение"? W>И опять же, в чем разница между хранимкой, батчем и серией простых SQL операторов?
Речь про разницу между SQL и HTTP как протоколами взаимодействия клиент-сервер.
С точки зрения попытки реализовать сервер приложений на SQL хранимки — это практически единственный способ хоть как-то инкапсулировать бизнес-логику. Выставлять внешним клиентам интерфейс в виде голых таблиц для вызова "серий простых SQL операторов" — это настолько плохая идея, что её вообще обсуждать не стоит.
Единственная альтернатива хранимкам — это публиковать rest-like интерфейс на основе view с instead of триггерами.
Но это, имхо, слишком радикально, чтобы стать мейнстримом
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
G>>Зато есть преимущества, которые никто больше не может перекрыть. Это скорость. S>Скорость чего? И по сравнению с чем? Скорость исполнения? Я вас разочарую — ХП исполняется настолько же быстро, сколько и эквивалентный ей SQL батч. S>Скорость написания — в разы хуже, потому что язык хреновый. С# по скорости написания корректного кода уделывает любой диалект SQL. G>>И огромная куча функционала под капотом. Мне, например, нравится пример с коллекцией в памяти, которую куча потоков модифицирует в памяти. Как организоывать блокировки? Для каждой строчки read-write lock, а блокировки на диапозоны, а что насчет эскалации блокировок. В SQL Server этот код уже написан, отлажен и работает максимально эффективно. Если вы будете делать что-то аналогичное, то либо потратите кучу времени и напишите кучу кода, либо получите неэффективное решение. S>Если честно, то это плохой пример. Для коллекции в памяти иметь словарик rw-локов безо всякой иерархии окажется на несколько порядков эффективнее SQL Server. Просто потому, что он упирается в IOPS диска, а коллекция в памяти — в ширину шины.
Итак у вас уже словарик rw-локов нужно написать, не много пока. Ну а как вы будете делать блокировки диапозонов? Это еще придумать надо и написать... А будут ли у вас блокировки о намереньях? А эскалации блокировок у вас будут или все будет по простому и как следствие неэффективно? А средства диагностики у вас какие на коллекции какие будут? Дедлоки как ловить? А что если ваша коллекция не влазит в оперативную память целиком, но вы активно работаете с некоторой частью, то есть имеется активная и пасивная части. Пасивная спокойно никому не мешая может лежать на диске. SQL Server это предоставляет. А фрагментация памяти? Если у вас в середине удаляются записи, сколько коллекция памяти будет занимать? Одним словом, написать что-то похожее на SQL Server сложно и в итоге вы получите SQL Server, только на C# и с багами...
Здравствуйте, Gattaka, Вы писали:
G>Итак у вас уже словарик rw-локов нужно написать, не много пока. Ну а как вы будете делать блокировки диапозонов? Это еще придумать надо и написать... G>А будут ли у вас блокировки о намереньях? А эскалации блокировок у вас будут или все будет по простому и как следствие неэффективно? А средства диагностики у вас какие на коллекции какие будут? Дедлоки как ловить? А что если ваша коллекция не влазит в оперативную память целиком, но вы активно работаете с некоторой частью, то есть имеется активная и пасивная части. Пасивная спокойно никому не мешая может лежать на диске. SQL Server это предоставляет. А фрагментация памяти? Если у вас в середине удаляются записи, сколько коллекция памяти будет занимать? Одним словом, написать что-то похожее на SQL Server сложно и в итоге вы получите SQL Server, только на C# и с багами...
Вы это к чему? Я не предлагаю заиенить SQL Server, вы спорите о чём-то не том. Для того, что делает SQL Server, альтернативы, в общем-то нет. Только другие RDBMS того же класса.
А вот для того, чему хватит коллекции в памяти, SQL Server будет оверкиллом. С этим лучше заранее смириться, иначе вся жизнь уйдёт на борьбу с ветряными мельницами.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, Gattaka, Вы писали: HBM>>>только что касается выборки реляционных данных. HBM>>>в остальном мы получаем кучу проблем. HBM>>>- реализовывать сложную логику в разы сложнее и код становится страшным G>>Сказки про страшный код. S>К сожалению, это не сказки. В SQL отвратительные возможности по декомпозиции. Появление table-valued функций немножко улучшило ситуацию, но недостаточно радикально. S>Поэтому типичная бизнес-логика на SQL — это бесконечные повторы однообразных оборотов типа "where (t1.OwnerID = @userID or t1.GroupIP = @userGroupId) inner join ... ... where (t2.OwnerID = @userID or t2.GroupIP = @userGroupId)". Это тяжело отлаживать (к примеру, для SQL Server интерактивный отладчик появился уже после того, как я перестал на нём программировать, а для остальных СУБД, как я понимаю, такого до сих пор нет), легко ошибиться, и нет статической проверки корректности компилятором.
S>Поэтому при прочих равных я предпочту эту бизнес-логику видеть написанной на Linq, где можно с одной стороны писать декларативные стейтменты в стиле SQL, не задуряясь порядком обхода джойнов, а с другой стороны есть все плюшки декомпозиции современного ЯП.
Это все вопросы привычки. У меня коллеги тоже не могут читать код на C# if(isValid), нужно писать if(isValid == true). Я нормально читаю, как и другие мои некоторые коллеги. Если посмотреть на C++, так там вобще жесть... Я уже очень давно на С++ не писал и меня он уже пугает. Что касается SQL, то когда то и я думал как вы, но после нескольких лет работы фактически SQL программистом, спокойно читаю код. Меня не смущают повторяющиеся условия, наоборот это удобно — ты сразу все видишь.
Привычка не более...
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, wildwind, Вы писали: W>>Стоп, а в какой момент наш клиент вдруг стал недоверенным? Тот же клиент, не использующий хранимки, будет доверенным? Что-то я теряю твою мысль. S>Никакому удалённому клиенту доверять нельзя. Доверенным для RDBMS может быть AppServer, потому что разрабатываем и развёртываем его мы, вместе с базой. S>Все остальные клиенты — неизвестное зло. S>Они будут выполнять delete * from users where 1=1 и прочее, если им это всё не запретить.
Можно правами и ролями пользователей базы разрулить если очень хочется...
S>>Поэтому при прочих равных я предпочту эту бизнес-логику видеть написанной на Linq, где можно с одной стороны писать декларативные стейтменты в стиле SQL, не задуряясь порядком обхода джойнов, а с другой стороны есть все плюшки декомпозиции современного ЯП. G>Это все вопросы привычки. У меня коллеги тоже не могут читать код на C# if(isValid), нужно писать if(isValid == true). Я нормально читаю, как и другие мои некоторые коллеги. Если посмотреть на C++, так там вобще жесть... Я уже очень давно на С++ не писал и меня он уже пугает. Что касается SQL, то когда то и я думал как вы, но после нескольких лет работы фактически SQL программистом, спокойно читаю код. Меня не смущают повторяющиеся условия, наоборот это удобно — ты сразу все видишь. G>Привычка не более...
Это не вопросы привычки. Это вопросы эффективности работы. Зачем заставлять себя писать полсотни килобайт там, где можно написать пять килобайт?
Я когда начинал осваивать SQL, то думал как вы. А после нескольких лет работы фактически SQL программистом начал видеть его недостатки.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.