metaclass: (Default)
metaclass ([personal profile] metaclass) wrote2013-04-03 01:06 am

В Советской Белоруссии SQL разжигает айседа

http://theiced.livejournal.com/238346.html
Собственно, про кобол я не знаю, на дельфи пишу уже 15 лет и никак избавится от него не могу (слишком много легаси кода), а вот про SQL я с ним не согласен.
Сам по себе SQL очень хорошо подходит для генерации отчетов. Если отчет сводится к фильтрации-сортировке-группировке множеств - идеально. С рекурсивными CTE - еще и деревья можно обрабатывать, не особо включая мозг. Всунув поверх этого минимальных размеров постобработку на какой-нибудь функциональщине, можно сделать почти любой отчет, пришедший в голову свихнувшимся на Excel выпускникам нархоза, работающим в минстате, минфине и МНС.

Но когда доходит до процедурных расширений, API между СУБД и клиентскими приложениями или каких-нибудь вещей, которые забыли вовремя добавить в стандарт - начинается полная, немыслимая жопа.
Например, проклятая тема - генерация автоинкрементных ключей и возвращение значений автоматически заполненных полей. Кто во что горазд - identity, генераторы, sequence, функции (в каждой СУБД названные по разному), returning, заебы на тему "вызывать в той же транзакции и сессии" и прочая и прочая. Про вариации на тему "вернуть поле, которое заполняется автоматически, но не является ключом/identity" лучше даже не думать.
Неудивительно, что люди при первой же возможности сбегают в ORM (которые являются уже второй производной от всего этого маразма и несут на себе его неизгладимый след).

[identity profile] fraks-nsk.livejournal.com 2013-04-03 06:13 am (UTC)(link)
Какую пачку SQL?
Один select и один update.

[identity profile] norguhtar.livejournal.com 2013-04-03 06:21 am (UTC)(link)
Давайте последовательно посмотрим на вопрос. У вас select и update пишется на каждую форму которая представляет собой сущность так ведь? И таких форм у вас может быть не одна так?

[identity profile] fraks-nsk.livejournal.com 2013-04-03 06:31 am (UTC)(link)
Не совсем.
Форма в которой редактируются поля записи - для каждого типа объектов обычно одна.
Запросы тогда лежат на этой форме.

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

У меня нет нигде редактирование в гриде. Редактирование только в отдельной форме которая раскрывает эту запись по полям. И такая форма в которой реализуется редактирование - одна на каждый тип объекта.
А вот запрашивать данные используя много типов объектов - это как правило на каждой форме свой запрос. Но для таких форм не надо ничего объявлять, просто пишется запрос который автоматом создаст потребные поля в датасетике. Вызываем метод в датасетике подсовывая ему объект Query - оно и выполняется и отображается.

[identity profile] norguhtar.livejournal.com 2013-04-03 06:36 am (UTC)(link)
Вот все что вы описываете и есть ORM. Разница между стандартным ORM и вашим в том что в случае подключении стороннего разработчика или передачи кода вашего проекта другому разработчику ему придется изучать ваш код для понимания логики где тут что лежит. В случае стандартного ORM ему будет достаточно почитать спецификацию. Плюс все нормальные ORM позволяют модифицировать то как они лезут в базу. И да в 90% случаев они лезут в базу как вы бы сами полезли, а кода писать приходится существенно меньше.

[identity profile] fraks-nsk.livejournal.com 2013-04-03 06:53 am (UTC)(link)
ORM - это надо в программе завести классы аналогичные тем что имеются в базе. Т.е. дублирование.
Дальнейшая работа с этими классами подразумевает что они имеют заполненные поля. А заполнятся они могут как все сразу (это неэффективно) так и по одному полю (тоже неэффективно, но уже по другому). В итоге для работы с объектами в ОРМ либо тянется куча по большей части ненужных данных либо генерится туча запросов на каждый чих.

Далее, если мы работаем с выборками по сложным запросам - тут мы или лепим в ОРМ левые классы не имеющие реального отражения в БД либо тянем коллекции классов с опять же нахрена не нужными полями.

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

[identity profile] metaclass.livejournal.com 2013-04-03 06:59 am (UTC)(link)
Народ генерит базу из классов или маппингов. В первом случае класс засран по крышу аннотациями на полях, во втором - нам надо знать убогий синтаксис маппингов (в дополнение к sql и собственно ЯП)

[identity profile] theiced.livejournal.com 2013-04-03 07:06 am (UTC)(link)
есть ещё рубёвый вариант ;]

[identity profile] norguhtar.livejournal.com 2013-04-03 07:08 am (UTC)(link)

ORM - это надо в программе завести классы аналогичные тем что имеются в базе. Т.е. дублирование.
Дальнейшая работа с этими классами подразумевает что они имеют заполненные поля. А заполнятся они могут как все сразу (это неэффективно) так и по одному полю (тоже неэффективно, но уже по другому). В итоге для работы с объектами в ОРМ либо тянется куча по большей части ненужных данных либо генерится туча запросов на каждый чих.

А в формы вы не заводите и данные туда не отображаете да? Все святым духом делается? И в MVC частенько упоминаемые вами классы используются как формы. Может вы мат. часть подучите а?


Для того что бы работать полностью через ОРМ надо грубо говоря вытащить всю базу на клиента и распихать по объектам, что с одной стороны совершенно бессмысленно нагрузит клиента а с другой - низведет сервер до тупого хранилища.

Учите мат. часть. Вы мягко говоря не правы. ORM это маппинг объектов а не вытаскивание данных из базы. Вы этот маппинг делаете каждый раз когда данные селекта показываете в форме.

(no subject)

[identity profile] fraks-nsk.livejournal.com - 2013-04-03 07:16 (UTC) - Expand

(no subject)

[identity profile] norguhtar.livejournal.com - 2013-04-03 07:18 (UTC) - Expand

(no subject)

[identity profile] vp.livejournal.com - 2013-04-03 09:32 (UTC) - Expand

(no subject)

[identity profile] norguhtar.livejournal.com - 2013-04-03 09:48 (UTC) - Expand

[identity profile] fraks-nsk.livejournal.com 2013-04-03 01:39 pm (UTC)(link)
Еще кстати такой момент - все что получено на клиента - по определению устарело. Что бы знать наверняка что данные еще не протухли - надо принимать специальные меры или согласиться с тем что данные могут быть протухшими. Вытаскивание данных в ОРМ - складировать протухшую инфу или напрягать программу и сервер на отслеживание актуальности данных.

[identity profile] norguhtar.livejournal.com 2013-04-03 01:43 pm (UTC)(link)
Вы про что ORM умеет транзакции тоже не слышали да?

(no subject)

[identity profile] fraks-nsk.livejournal.com - 2013-04-03 15:03 (UTC) - Expand

(no subject)

[identity profile] norguhtar.livejournal.com - 2013-04-03 15:22 (UTC) - Expand

(no subject)

[identity profile] fraks-nsk.livejournal.com - 2013-04-03 15:35 (UTC) - Expand

(no subject)

[identity profile] norguhtar.livejournal.com - 2013-04-03 15:43 (UTC) - Expand

(no subject)

[identity profile] fraks-nsk.livejournal.com - 2013-04-03 15:57 (UTC) - Expand

(no subject)

[identity profile] norguhtar.livejournal.com - 2013-04-03 16:09 (UTC) - Expand

(no subject)

[identity profile] fraks-nsk.livejournal.com - 2013-04-03 16:18 (UTC) - Expand

(no subject)

[identity profile] norguhtar.livejournal.com - 2013-04-03 17:19 (UTC) - Expand

(no subject)

[identity profile] fraks-nsk.livejournal.com - 2013-04-03 17:46 (UTC) - Expand

(no subject)

[identity profile] norguhtar.livejournal.com - 2013-04-04 02:27 (UTC) - Expand

(no subject)

[identity profile] fraks-nsk.livejournal.com - 2013-04-04 02:46 (UTC) - Expand

(no subject)

[identity profile] norguhtar.livejournal.com - 2013-04-04 03:08 (UTC) - Expand

(no subject)

[identity profile] fraks-nsk.livejournal.com - 2013-04-04 03:21 (UTC) - Expand

(no subject)

[identity profile] norguhtar.livejournal.com - 2013-04-04 03:30 (UTC) - Expand

(no subject)

[identity profile] fraks-nsk.livejournal.com - 2013-04-04 04:13 (UTC) - Expand

(no subject)

[identity profile] norguhtar.livejournal.com - 2013-04-04 04:36 (UTC) - Expand

(no subject)

[identity profile] fraks-nsk.livejournal.com - 2013-04-03 16:04 (UTC) - Expand

(no subject)

[identity profile] norguhtar.livejournal.com - 2013-04-03 16:20 (UTC) - Expand

(no subject)

[identity profile] fraks-nsk.livejournal.com - 2013-04-03 16:31 (UTC) - Expand

(no subject)

[identity profile] norguhtar.livejournal.com - 2013-04-03 17:29 (UTC) - Expand

(no subject)

[identity profile] fraks-nsk.livejournal.com - 2013-04-03 17:47 (UTC) - Expand

(no subject)

[identity profile] norguhtar.livejournal.com - 2013-04-04 02:28 (UTC) - Expand

(no subject)

[identity profile] fraks-nsk.livejournal.com - 2013-04-04 02:48 (UTC) - Expand

(no subject)

[identity profile] norguhtar.livejournal.com - 2013-04-04 03:09 (UTC) - Expand

[identity profile] fraks-nsk.livejournal.com 2013-04-03 06:43 am (UTC)(link)
Вот процедура обновления списка региональных агентов.

procedure TFrmAgent.F5;
begin
CDV.RowSavePosition; {сохраним текущую позицию}
{}
CDS.ExecSelect(QSel);
CDV.Sync;
{}
CDV.RowRestorePositionID; {восстановим позицию курсора если она была}
end;

А вот процедура чтения данных по одному региональному агенту, для редактирования.
Справочник элементарный, типа id, name, поэтому даже форму ему для редактирования делать не стал.

procedure TFrmAgent.F2; {редактирование элемента справочника}
var
id: integer;
sname: string;
iRow: cardinal; {текущая выбранная строка в дереве}
begin
if not CDV.RowSelected(iRow) then Exit; {если ни одна строка не выбрана}
{на CDS.Count > 0 можно уже не анализировать, иначе бы ничего не было выбрано}
id := CDS.ReadIntegerFN(iRow, 'ID');
QS.ParamByName('id').AsInteger := id;
QS.ExecQuery;
if QS.EOF then Exit;
sname := QS.FieldByName('name').AsString;
TransRC.Commit;
{}
if not InputQuery(Caption, 'Редактирование регионального агента', sname) then Exit;
{}
QU.ParamByName('id' ).AsInteger := id;
QU.ParamByName('name').AsString := sname;
Open_Query(QU);
TransRC.Commit;
F5; {позиционирование на старый ID - внутри}
end;

[identity profile] vp.livejournal.com 2013-04-03 07:09 am (UTC)(link)
У тебя логика работы смешана с кодом ФОРМЫ на ПАСКАЛЕ!!

Щас позову Айсда, не уходи..

:)

[identity profile] fraks-nsk.livejournal.com 2013-04-03 07:18 am (UTC)(link)
Зови, мне не жалко.

Если логика работы используется более чем в одном месте - то я выношу это в отдельное место. Если эта форма - единственное место где у меня работа с этим объектом - нахрена мне это разделять? Что бы каноны соблюсти?

[identity profile] vp.livejournal.com 2013-04-03 09:31 am (UTC)(link)
Конечно! :)

[identity profile] theiced.livejournal.com 2013-04-03 07:23 am (UTC)(link)
а чего меня звать, я тут. но я даже не буду ЭТО комментировать, поделка на уровне студента рти/сотрудника нии гит с 40летним стажем. неподдерживаемо, немэйнтабельно, нерасширяемо, нетестируемо и не работает. такой код имеет исключительно один "плюс" - мудака его написавшего так просто с работы не попрёшь.

[identity profile] vp.livejournal.com 2013-04-03 09:38 am (UTC)(link)
Хотя на самом деле задача диктуется масштабом. Если налабать что-то разово и действительно нерасширяемо - можно не говородить огород с обобщением.

(no subject)

[identity profile] theiced.livejournal.com - 2013-04-04 02:13 (UTC) - Expand

[identity profile] woldemar kuchelbeker (from livejournal.com) 2013-04-03 09:48 am (UTC)(link)
сохранения-рабочего-места-driven-development

(no subject)

[identity profile] jakobz.livejournal.com - 2013-04-03 20:19 (UTC) - Expand

[identity profile] fraks-nsk.livejournal.com 2013-04-03 03:05 pm (UTC)(link)
Посмотрел на код и не понял про что ты говоришь.
Какая логика работы? Тут вся логика - прочитать поле NAME, и записать его обратно, если редактирование было завершено.

[identity profile] norguhtar.livejournal.com 2013-04-03 03:45 pm (UTC)(link)
Вы явно незнакомы с паттерном MVC. Сходите познакомьтесь.

[identity profile] prepor.livejournal.com 2013-04-03 07:09 pm (UTC)(link)
Вы покажите ваши тесты на это и все вопросы сразу отпадут. Этим умникам лишь бы попиздеть, а то что писать работающий, тестируемый и соответсвенно поддерживаемый код можно по-разному им не в домек.

(no subject)

[identity profile] theiced.livejournal.com - 2013-04-03 19:15 (UTC) - Expand

(no subject)

[identity profile] prepor.livejournal.com - 2013-04-03 19:17 (UTC) - Expand

[identity profile] vp.livejournal.com 2013-04-04 07:01 am (UTC)(link)
У меня еще претензия к названию методов: F2, F5
Они никак не отражают сути того, что делают эти методы.
далее, в методе F2 у вас несколько раз используются одни и те же строковые константы: 'id', 'name'. Положено такие вещи выносить хотя бы константы на уровне класса.
Комментарии в конце строки, заключенные в {} - неоправданы. 100 лет как для этой цели используется синтаксис комментариев с //
Конструкция if .. then Exit в одну строку. Правильный формат - Exit переносится на следующую строку с отступом как на следующий блок кода.


[identity profile] fraks-nsk.livejournal.com 2013-04-04 08:17 am (UTC)(link)
>> У меня еще претензия к названию методов: F2, F5
>> Они никак не отражают сути того, что делают эти методы.

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

Во многих программах нажатие кнопки F5 производит обновление данных в окне. Именно это и делает эта функция. Первоначальное это заполнение или обновление, без разницы. Стоя на гриде с данными юзер нажимает F5 и он обновляется новыми данными с сервера.

F2 - аналогично - стоя на гриде с данными вызываем просмотр и редактирование свойств объекта который отображается текущей записью.

[identity profile] vp.livejournal.com 2013-04-04 08:37 am (UTC)(link)
>На самом деле именно суть они и отображают.

Суть = словесное название того действия, которое делает метод. F2 - это не действие, не такого слова. То, что вы назвали, должно было у вас называться .Refresh() или как-то так.
F2 - .Save()

>Мне так не нравится, читается хуже.
>Я если переношу действие на вторую строку - то вместе с then

Есть отраслевые стандарты. Ваш код потом будет тяжело воспринимать.
Я сам таким грешил раньше.


(no subject)

[identity profile] fraks-nsk.livejournal.com - 2013-04-04 08:45 (UTC) - Expand

(no subject)

[identity profile] berezovsky.livejournal.com - 2013-04-04 08:48 (UTC) - Expand

(no subject)

[identity profile] fraks-nsk.livejournal.com - 2013-04-04 08:53 (UTC) - Expand

(no subject)

[identity profile] vp.livejournal.com - 2013-04-04 09:04 (UTC) - Expand

[identity profile] evil-invader.livejournal.com 2013-04-04 11:48 am (UTC)(link)
Т.е. кроме F5 или F2 эти же самые действия по-другому вызвать нельзя? (Например из выпадающего меню)

(no subject)

[identity profile] fraks-nsk.livejournal.com - 2013-04-05 01:16 (UTC) - Expand

(no subject)

[identity profile] fraks-nsk.livejournal.com - 2013-04-05 09:11 (UTC) - Expand

[identity profile] fraks-nsk.livejournal.com 2013-04-04 08:22 am (UTC)(link)
>> Конструкция if .. then Exit в одну строку. Правильный формат - Exit переносится на следующую строку с отступом как на следующий блок кода.

Мне так не нравится, читается хуже.
Я если переношу действие на вторую строку - то вместе с then

if 111
then d := 1;

а если есть begin end - то по другому
if 111 then begin
d := 1;
c := 2;
end;{}