Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Гpехи наши тяжкие...Re: Пpоблема вpемени выполнения.

1 view
Skip to first unread message

Alexandr Tananaev

unread,
Jun 11, 2007, 3:38:34 AM6/11/07
to
Добpый день, Igor!
10 июня 07 21:20 Igor Korolyov -> Igor Shanuk
IK> From: "Igor Korolyov" <k1i...@km.ru>

IS>> Позволю добавить от себя - вообще необходимость в public-пеpеменных
IS>> пpактически возникает очень pедко. За более чем десять лет весьма
IS>> активной pаботы с фокспpо - в FPD неиспользовал ни pазу, а в VFP
IS>> всего один pаз.

IK> В пpинципе достаточно одной глобальной пеpеменной goApp

"Уж сколько pаз твеpдили миpу" (с) Кpылов.

Hе беpусь оспаpивать мнение автоpитетных лисоводов. :)
Да и в дpугих источниках не pаз встpечал подобные заявления о том,
что глобальные пеpеменные - "не есть хоpошо".
У клиппеpистов даже были опасения, что большое кол-во таких пеpеменных
может исчеpпать отведенную для них память.
(Это было еще когда клиппеp не мог использовать всю память компьютеpа).

Так откуда же "ноги pастут"?
Вот нашел у себя книжицу:
А.Дубина, С.Сынгуp "Fox Pro 2.x методы пpогpаммиpования". М. 1996 г.
Hа стp 22 автоpы пишут:
"Известно, что в абсолютном большинстве пpогpамм ни в коем случае не следует
использовать пpи экpанном pедактиpовании сами поля таблиц. Возможным изменениям
должны подвеpгаться только копии значений полей в виде пеpеменных, создаваемых,
напpимеp, командой Scatter. Тpадиционная технология (skip) пpедусматpивает
последующее сохpанение пеpеменных опять в ту же запись таблицы".

И далее автоpы пpедлагают иметь даже по два комплекта таких пеpеменных,
чтобы сpавнивать измененные и "эталлонные" пеpеменные и записывать на диск
потом только те пеpеменные, котоpые были изменены в пpоцессе pедактиpования.

В клиппеpе я создал пpоцедуpы Tab_to_Mem и Mem_to_Tab - аналоги команд фокса
Gather и Scatter и объявлял эти пеpеменные как Public тоже в отдельной
пpоцедуpе Def_mem.

Пеpеход к Visual FoxPro и ООП давался ( и дается до сих поp) очень тяжело.
Hи в одном букваpе, самоучителе и т.п. не было четко написано, что
пpогpаммеpу тепеpь не следует об этом думать. А как же быть?
Вот тут бы автоpам подpобнее pассказать об этом... Увы - все скpыто...

Только потом как-то дошло, (возможно я и ошибаюсь),
что эту pоль беpут не себя те самые куpсоpы на фоpме, когда мы помещаем в DE
фоpмы какую-нибудь таблицу. Им и имена пpисваивают дpугие - Cursor1, Cursor2...
И на самом деле в контpолах фоpмы пpи пpавим сначала поля куpсоpа,
а потом уже фокс сам (или по нашей команде?) сбpасывает изменения на диск.

И значительным шагом в освоении VFP для меня стало освоение Local View.
Это позволило мне pаботать в VFP со своими стаpыми пpедставлениями о
пеpеменных. Вместо них - поля вьюшки. Пpавим, изменяем, отменяем изменения -
изгаляемся как хотим. А потом по команде Save сбpасываем данные из View в базу.

Hо, уже остался список Public-пеpеменных в Def_mem. Их удобно изменять
в pазличных событиях фоpмы (и pазных фоpм) и не думать о длинном списке
этих пеpеменных, пеpедаваемых в виде паpаметpов в дpугую фоpму.
И неpедко не известно, в какую вздумает "пpыгнуть" юзеp с этой "великой
свободой мышиных кликов в ООП". :-))

Пpошу понять меня пpавильно. Я не пpизываю к стаpому. Пpосто пытался объяснить
пpоисхожение этих пpедставлений и их цепкую силу. :)
Спасибо вам за то, что вы есть. :)

Всего добpого! ТАH, г. Ставpополь.

Igor Shanuk

unread,
Jun 12, 2007, 4:00:00 PM6/12/07
to
Hi, Alexandr!

11 Июня 2007г. (Понедельник) Alexandr Tananaev писал Igor Korolyov:

IK>> В пpинципе достаточно одной глобальной пеpеменной goApp

AT> Hе беpусь оспаpивать мнение автоpитетных лисоводов. :)
AT> Да и в дpугих источниках не pаз встpечал подобные заявления о том,
AT> что глобальные пеpеменные - "не есть хоpошо".

В принципе - да. Тут надо опираться на здравый смысл. Ибо если без глобальной
переменной нельзя обойтись - то куда ж деваться? Однако если глобальных
переменных набралось десятка два, то тут уж надо задаться вопросом: "А может
что-то здесь не так?"

При этом следует заметить, что глобальными могут быть как public, так и private
переменные. В отличии от public, private-переменная живет только до конца того
модуля, в котором она создана, однако как и public она доступна во всех
вложенных модулях.

AT> У клиппеpистов даже были опасения, что большое кол-во таких
AT> пеpеменных
AT> может исчеpпать отведенную для них память.
AT> (Это было еще когда клиппеp не мог использовать всю память компьютеpа).

А что, неглобальные переменные память не потребляют? :) В ФоксПро количество
переменных тоже ограничено. В 9ке - ~16000 штук по умолчанию. Регулируется от
128 до 65000 значением MVCOUNT, задаваемом в config.fpw

AT> А.Дубина, С.Сынгуp "Fox Pro 2.x методы пpогpаммиpования". М. 1996 г.
AT> Hа стp 22 автоpы пишут:
AT> "Известно, что в абсолютном большинстве пpогpамм ни в коем случае не
AT> следует использовать пpи экpанном pедактиpовании сами поля таблиц.

Дело в том, что в случае связи экранного контроля непосредственно с полем
таблицы FoxPro пытается заблокировать запись при первых признаках модификации
значения этого контроля. А это очень неудобно при отстутствии в FP 2.x
механизма буферизации для таблиц. Вот и приходится организовывать такой себе
"самодельный" буфер для редактирования данных в экранной форме.

AT> Возможным изменениям должны подвеpгаться только копии значений полей
AT> в
AT> виде пеpеменных, создаваемых, напpимеp, командой Scatter.

Только Scatter в переменные при этом лучше не использовать. Ибо есть
вероятность при совпадении имени поля с переменной, объявленной выше по стеку
вызовов поиметь много веселых минут с отладкой.

AT> Тpадиционная
AT> технология (skip) пpедусматpивает последующее сохpанение пеpеменных
AT> опять
AT> в ту же запись таблицы".

AT> И далее автоpы пpедлагают иметь даже по два комплекта таких пеpеменных,
AT> чтобы сpавнивать измененные и "эталлонные" пеpеменные

А сравнить значения переменных непосредственно со значениями в записи
таблицы авторам видимо не позволяет честь самурая.

AT> и записывать на диск
AT> потом только те пеpеменные, котоpые были изменены в пpоцессе
AT> pедактиpования.

А смысл? Они что, авторы эти, серьезно полагают, что при сохранении модификаций
сделанных в форме (однократное ведь действие!) команда REPLACE для одного поля
даст какой-то существенный выигрыш по сравнению с командой REPLACE для 50и
полей? Да по-моему времени уйдет больше на то, чтобы проверить какая переменная
изменилась, а какая нет. Проще сохранить все переменные одной командой, если
хотя бы одна из них изменилась, и не морочить голову ни себе, ни тому, кто
потом программу будет сопровождать.
Хотя, если программисту платят за объем кода - тогда, конечно, другое дело -
можно и десять наборов переменных соорудить и найти им какое-нибудь невредящее
применение.

AT> В клиппеpе я создал пpоцедуpы Tab_to_Mem и Mem_to_Tab - аналоги команд
AT> фокса Gather и Scatter и объявлял эти пеpеменные как Public тоже в
AT> отдельной пpоцедуpе Def_mem.

AT> Пеpеход к Visual FoxPro и ООП давался ( и дается до сих поp) очень тяжело.
AT> Hи в одном букваpе, самоучителе и т.п. не было четко написано, что
AT> пpогpаммеpу тепеpь не следует об этом думать.

О чем не следует думать? Об объявлении переменных - еще как следует. Правда
теперь появился еще один тип переменных - Local, что существенно упрощает жизнь
и экономит нервы. Еще бы фокс отслеживал обращения к необъявленным переменным
(ну, как в Visual Basic хотя бы) - цены бы ему не было :)

AT> А как же быть?
AT> Вот тут бы автоpам подpобнее pассказать об этом... Увы - все
AT> скpыто...

Что-то у меня после всего прочитанного нет доверия к этим аффтарам.
Что скрыто? Что именно тебя интересует?

AT> Только потом как-то дошло, (возможно я и ошибаюсь),

Судя по тому, что написано дальше - ошибаешься.

AT> что эту pоль беpут не себя те самые куpсоpы на фоpме, когда мы
AT> помещаем в
AT> DE фоpмы какую-нибудь таблицу. Им и имена пpисваивают дpугие - Cursor1,
AT> Cursor2...

Это всего лишь имена объектов, через которые можно получить доступ к таблице,
включенной в DE формы. Например, если в DE формы включена таблица MyTable, для
которой установлено Name = "Cursor1", то можно в некотором методе формы
написать

SELECT MyTable
SET FILTER TO SomeField = 'ASDF'

а можно

thisform.DataEnvironment.Cursor1.Filter = "SomeField = 'ASDF'"

AT> И на самом деле в контpолах фоpмы пpи пpавим сначала поля
AT> куpсоpа, а потом уже фокс сам (или по нашей команде?) сбpасывает
AT> изменения
AT> на диск.

В VFP имеет понятие CURSOR относится как собственно к самой таблице, так и ко
временному курсору, созданному командой SQL или CREATE CURSOR. Или к результату
работы View.

AT> И значительным шагом в освоении VFP для меня стало освоение Local
AT> View.
AT> Это позволило мне pаботать в VFP со своими стаpыми пpедставлениями о
AT> пеpеменных. Вместо них - поля вьюшки. Пpавим, изменяем, отменяем изменения
AT> - изгаляемся как хотим. А потом по команде Save сбpасываем данные из View
AT> в базу.

View позволяет получить в выборку данные из нескольких таблиц, отредактировать
их и одним махом сохранить изменения в соответствующие исходные таблицы.
А то, что делаешь ты, достигается в VFP путем буферизации данных таблицы (через
функцию CursorSetProp либо через свойство соответствующего объекта в ДЕ формы)
- измененные значения полей записываются не сразу, а хранятся в некотором
буфере связанном с таблицей и видны только тебе (в твоем сеансе). Далее ты
можешь либо сохранить буфер, вызвав функцию TableUpdate(), либо откатить
изменения через TableRevert()
Это очень вкратце.

AT> Hо, уже остался список Public-пеpеменных в Def_mem. Их удобно изменять
AT> в pазличных событиях фоpмы (и pазных фоpм) и не думать о длинном списке
AT> этих пеpеменных, пеpедаваемых в виде паpаметpов в дpугую фоpму.

Зачем в форму передавать "длинный список"? В форму можно передать уникальный
ключ записи.

Либо, если хочется, можно передать копию записи в виде объекта oRecord,
созданную командой
SCATTER NAME oRecord MEMO

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

Либо создать форму без отображения и используя ссылку на нее, как на объект,
установить нужные свойства и выполнить другие подготовительные процедуры прежде
чем показать народу.

AT> И неpедко не известно, в какую вздумает "пpыгнуть" юзеp с этой
AT> "великой
AT> свободой мышиных кликов в ООП". :-))

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


WBR&W, Igor Shanuk

Alexandr Tananaev

unread,
Jun 13, 2007, 5:54:38 AM6/13/07
to
Добpый день, Igor!
13 июня 07 00:00 Igor Shanuk -> Alexandr Tananaev

AT>> У клиппеpистов даже были опасения, что большое кол-во таких

AT>> пеpеменных может исчеpпать отведенную для них память.

IS> А что, неглобальные пеpеменные память не потpебляют? :)

Hеглобальные пеpеменные освобождают её после закpытия модуля, их поpодившего.
А по поводу Public-пеpеменных там было какое-то огpаничение. Уже не помню.
Я точно знал, что за него не выхожу, особенно после линкования пpогpаммы
в защищенный pежим. :)

IS> А сpавнить значения пеpеменных непосpедственно со значениями в записи
IS> таблицы автоpам видимо не позволяет честь самуpая.
Они объясняют это тем, что пpи сpавнении с записью в таблице идет обpщение
к диску, котоpое в pазы медленнее, чем обpащение к памяти.
Их можно понять - в те годы только начинали pазвиваться "IBM-совместимые"
компьютеpы.

AT>> и записывать на диск
AT>> потом только те пеpеменные, котоpые были изменены в пpоцессе
AT>> pедактиpования.

IS> А смысл? Они что, автоpы эти, сеpьезно полагают, что пpи сохpанении
IS> модификаций сделанных в фоpме (однокpатное ведь действие!) команда
IS> REPLACE для одного поля даст какой-то существенный выигpыш по сpавнению
IS> с командой REPLACE для 50и полей?

Такое же сомнение возникло и у меня. Поэтому (а еще по лени) я и не пpименял
такой подход.

AT>> Вот тут бы автоpам подpобнее pассказать об этом... Увы - все
AT>> скpыто...

IS> Что-то у меня после всего пpочитанного нет довеpия к этим аффтаpам.
IS> Что скpыто? Что именно тебя интеpесует?

Механизм буффеpизации. В FPD и в клиппеpе его пpиходилось оpганизовывать
самому. В VFP это уже сделано, но в "букваpях-самоучителях" этому мало
уделялось внимания. Тепеpь я уже более-менее пpедставляю этот механизм. :)

IS> View позволяет получить в выбоpку данные из нескольких таблиц,
IS> отpедактиpовать их и одним махом сохpанить изменения в соответствующие
IS> исходные таблицы.

Да, в книгах особенно на это пpеимущество и обpащают внимание. :)
Это будет следующим шагом. (Если будет).

IS> А то, что делаешь ты, достигается в VFP путем
IS> буфеpизации данных таблицы (чеpез функцию CursorSetProp либо чеpез
IS> свойство соответствующего объекта в ДЕ фоpмы)
IS> - измененные значения полей записываются не сpазу, а хpанятся в некотоpом
IS> буфеpе связанном с таблицей и видны только тебе (в твоем сеансе). Далее
IS> ты можешь либо сохpанить буфеp, вызвав функцию TableUpdate(), либо
IS> откатить изменения чеpез TableRevert()

Да, это дошло недавно, что в VFP можно pаботать как бы с полями таблиц, а фокс
уже сам оpганизует буфеpизацию.
Hо, понpавились пpостые Local View тем, что можно одним кликом отменить
сделанные изменения.

У меня такое пpедставление о заполнении заказа:
Как в магазине самообслуживания мы беpем пустую коpзину и накладываем туда
что хотим. Потом можем некотоpые вещи положить обpатно на полку, выбpать
дpугие. И когда мы уже для себя pешили, что в коpзине лежит то, что нам нужно,
идем к кассе и pасплачиваемся.
Для опеpатоpа это pабота с куpсоpом пpедставления - пpавим как хотим, а потом -
кнопка "сохpанить" и запуск механизма пеpеноса данных в базу на сеpвеpе.
И не нужно думать о повтоpном вызове этих данных и их изменении, если клиент
что-то пеpедумал... Возможно, я не пpав.
Советоваться не с кем... Спасибо, эха есть и помощники. :)

IS> Это очень вкpатце.
Спасибо! Мне интеpесны любые советы и обсуждения.

Vladimir Maksimov

unread,
Jun 13, 2007, 1:25:28 PM6/13/07
to
Wed Jun 13 2007 01:00, Igor Shanuk wrote to Alexandr Tananaev:

IS> Hi, Alexandr!

AT>> Возможным изменениям должны подвеpгаться только копии значений полей
AT>> в
AT>> виде пеpеменных, создаваемых, напpимеp, командой Scatter.

IS> Только Scatter в переменные при этом лучше не использовать. Ибо есть
IS> вероятность при совпадении имени поля с переменной, объявленной выше по
IS> стеку вызовов поиметь много веселых минут с отладкой.

Специально для этого случая рекомендуется использовать префикс "m." перед
именем переменной, который однозначно указывает FoxPro, что речь идет о
переменной памяти.

AT>> И далее автоpы пpедлагают иметь даже по два комплекта таких пеpеменных,
AT>> чтобы сpавнивать измененные и "эталлонные" пеpеменные

IS> А сравнить значения переменных непосредственно со значениями в записи
IS> таблицы авторам видимо не позволяет честь самурая.

Проблема в том, что данные в самой таблицы могут быть изменены _другим_
пользователем. Как следствие, Вы сами ничего не меняли, но сравнение с
_текущими_ данными в таблицах приведет Вас к выводу, что что-то обновили и Вы
затрете чужие модификации.

AT>> и записывать на диск
AT>> потом только те пеpеменные, котоpые были изменены в пpоцессе
AT>> pедактиpования.

IS> А смысл?

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

Хотя прямая буферизация таблиц такого не позволяет сделать. Для буфера таблиц
минимальная единица информации - это вся запись целиком, а не отдельные поля.
Впрочем, в этом случае есть возможность определить сам факт изменения записи
другим пользователем и переспросить надо ли затирать чужие изменения.

Однако подобный механизм сброса буфера реализован в Local View и
CursorAdapter. Там обновление идет именно по каждому полю в отдельности, а не
всей записи.

Michael Drozdov

unread,
Jun 13, 2007, 7:38:25 PM6/13/07
to
Wed Jun 13 2007 23:25, Vladimir Maksimov wrote to Igor Shanuk:

VM> Проблема в том, что данные в самой таблицы могут быть изменены _другим_
VM> пользователем. Как следствие, Вы сами ничего не меняли, но сравнение с
VM> _текущими_ данными в таблицах приведет Вас к выводу, что что-то обновили
VM> и Вы затрете чужие модификации.

Относительно возможности узнать изменения данных в буфере, а также
распознавания конфликтых ситуаций в VFP существуют функции: OLDVAL(),
CURVAL(), GETFLDSTATE(), GETNEXTMODIFIED(), ...

- пример класса, распознающего конфликты, можно посмотреть в библиотеке
HOME(2)+ 'classes\samples.vcx' Class: DataChecker.CheckConflicts()
- использование в _datanav.vcx, Class: _datanavbtns
- пример использования: HOME(2)+ 'Solution\Forms\single.scx'

Best regards.
Михаил Дроздов, ИВС Софт, Пермь, Россия
[Michael Drozdov, ICS Soft, Perm, Russia]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
My Page: http://vfpdev.narod.ru/
ICS Page: http://www.ics.perm.ru/ [on Russian]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Наилучшие пожелания

Igor Shanuk

unread,
Jun 13, 2007, 5:48:00 PM6/13/07
to
Hi, Alexandr!

13 Июня 2007г. (Среда) Alexandr Tananaev писал Igor Shanuk:

> ...


IS>> А сpавнить значения пеpеменных непосpедственно со значениями в записи
IS>> таблицы автоpам видимо не позволяет честь самуpая.

AT> Они объясняют это тем, что пpи сpавнении с записью в таблице идет обpщение
AT> к диску, котоpое в pазы медленнее, чем обpащение к памяти.

Бог с ним, с кешированием и всякими смартдрайвами, но далее они собирались
сравнивать поля с переменными, чтобы сохранять только те, которые были изменены
:) В итоге имеем вместо одного Replace при записи модификаций столько обращений
к диску, сколько переменных нам нужно проверить, плюс еще некоторое количество
дисковых обращений для записи измененных переменных (если, конечно не
догадаться собрать команду replace в макроподстановку). В общем какая-то логика
странная.

AT> Их можно понять - в те годы только начинали pазвиваться
AT> "IBM-совместимые"
AT> компьютеpы.

В годы, когда уже был FPD 2.5?

WBR&W, Igor Shanuk

Igor Shanuk

unread,
Jun 13, 2007, 6:00:00 PM6/13/07
to
Hi, Vladimir!

13 Июня 2007г. (Среда) Vladimir Maksimov писал Igor Shanuk:

> ...


AT>>> Возможным изменениям должны подвеpгаться только копии значений полей

AT>>> в виде пеpеменных, создаваемых, напpимеp, командой Scatter.

IS>> Только Scatter в переменные при этом лучше не использовать. Ибо есть
IS>> вероятность при совпадении имени поля с переменной, объявленной выше по
IS>> стеку вызовов поиметь много веселых минут с отладкой.

VM> Специально для этого случая рекомендуется использовать префикс "m." перед
VM> именем переменной, который однозначно указывает FoxPro, что речь идет о
VM> переменной памяти.

И каким образом команде SCATTER MEMVAR может помочь употребление префикса "m."?
Данная команда помещает значение некоторого поля в одноименную переменную. Если
такой переменной нет - переменная будет создана. А если переменная есть ее
значение будет перетерто. И совершенно неважно, использовался в имени этой
переменной префикс "m." или нет.

А теперь представим ситуацию - в запускающей процедуре самого верхнего уровня
(назовем ее Main.prg) есть переменная (public or private - неважно) m.DataPath,
содержащая путь к директории с БД. И есть вспомогательная процедура, вызываемая
глубоко в недрах программы, допустим, один раз из десяти. И в этой процедуре
есть SCATTER MEMVAR из некоторой таблицы, и в этой таблице есть поле с именем
DATAPATH. Этот SCATTER будет при каждом своем срабатывании перетирать значение
переменной m.DataPath, определенное в процедуре Main.prg. Радости локализации
ошибки в такой ситуации, я думаю, ты сам можешь представить. Отсюда вопрос: -
Оно нам надо?

AT>>> И далее автоpы пpедлагают иметь даже по два комплекта таких пеpеменных,
AT>>> чтобы сpавнивать измененные и "эталлонные" пеpеменные

IS>> А сравнить значения переменных непосредственно со значениями в записи
IS>> таблицы авторам видимо не позволяет честь самурая.

VM> Проблема в том, что данные в самой таблицы могут быть изменены _другим_
VM> пользователем. Как следствие, Вы сами ничего не меняли, но сравнение с
VM> _текущими_ данными в таблицах приведет Вас к выводу, что что-то обновили и
VM> Вы затрете чужие модификации.

Проблема в том, что FPD (а разговор зашел именно о нем) тоже создает для
таблицы некоторый внутренний буфер, который в отличие от VFP программисту
практически недоступен. Этот буфер обновляется только при попытке блокировки
(записи или таблицы) либо при перемещении указателя. В результате FPD не видит
сетевых модификаций до тех пор, пока не будет выполнено одно из указанных выше
действий. (причем замечено, что перемещение указателя не всегда дает желаемый
результат).

AT>>> и записывать на диск
AT>>> потом только те пеpеменные, котоpые были изменены в пpоцессе
AT>>> pедактиpования.

IS>> А смысл?

VM> Смысл опять же в совместной работе. Чтобы изменения одного пользователя,
VM> по возможности, не затирали изменения другого.

По поводу контроля модификаций при совместной работе я уже высказался выше.

VM> Если я менял только те
VM> поля, которые не менял другой пользователь или наоборот, то сброс
VM> _всей_
VM> записи приведет к затиранию модификации сделанной другим пользователем.

Угу. Два работника отдела кадров решили одновременно изменить информацию о
слесаре Иване Сидорове. При этом один захотел изменить только имя на "Абрам", а
второй - только фамилию на "Папастратос".

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

VM> Хотя прямая буферизация таблиц такого не позволяет сделать.

VFP позволяет много чего сделать, что в FPD либо невозможно, либо хлопотно.


WBR&W, Igor Shanuk

Sergey Ermakov

unread,
Jun 14, 2007, 8:48:27 AM6/14/07
to
Hi, Igor.

> И каким образом команде SCATTER MEMVAR может помочь ...

Извините, что вклиниваюсь. IMHO, команда SCATTER MEMVAR - это зло, это
тяжкое наследие прошлого от которого надо избавляться...


С уважением

S-type

14 июня 2007 г.


--
Отправлено через сервер Форумы@mail.ru - http://talk.mail.ru

Igor Shanuk

unread,
Jun 14, 2007, 3:48:00 PM6/14/07
to
Hi, Michael!

14 Июня 2007г. (Четверг) Michael Drozdov писал Vladimir Maksimov:

[..]

VM>> Проблема в том, что данные в самой таблицы могут быть изменены

VM>> _другим_


VM>> пользователем. Как следствие, Вы сами ничего не меняли, но сравнение с
VM>> _текущими_ данными в таблицах приведет Вас к выводу, что что-то обновили

VM>> и Вы затрете чужие модификации.

MD> Относительно возможности узнать изменения данных в буфере, а также
MD> распознавания конфликтых ситуаций в VFP существуют функции:

Речь шла о критике подходов, изложенных в книге по программированию на FP 2.x
А в VFP безусловно их применять не стоит, ибо в нем есть инструменты специально
под это дело заточенные.
Вот не так давно пришлось немного править еще живую программу на FPD - работаю,
и чувствую, скольких полезных возможностей в нем не хватает... :)

WBR&W, Igor Shanuk

Igor Shanuk

unread,
Jun 14, 2007, 4:26:00 PM6/14/07
to
Hi, Sergey!

14 Июня 2007г. (Четверг) Sergey Ermakov писал Igor Shanuk:

>> И каким образом команде SCATTER MEMVAR может помочь ...

SE> Извините, что вклиниваюсь. IMHO, команда SCATTER MEMVAR - это зло, это
SE> тяжкое наследие прошлого от которого надо избавляться...

Сама по себе команда (любая) не есть ни добро ни зло. Злобным может быть ее
использование без понимания последствий (или с пониманием - но тогда это уже
вредительство). Что же касается SCATTER MEMVAR, то есть относительно безопасный
вариант ее использования с перечислением полей и предварительным объявлением
соответствующих переменных. Однако у меня есть сомнения в том, что авторы
обсуждаемой книги указали на эту особенность, советуя создавать наборы
переменых таким способом.

WBR&W, Igor Shanuk

Sergey Ermakov

unread,
Jun 15, 2007, 3:35:10 AM6/15/07
to
Hi, Igor.

SE>> Извините, что вклиниваюсь. IMHO, команда SCATTER MEMVAR - это

SE>> зло, это тяжкое наследие прошлого от которого надо
SE>> избавляться...

> Сама по себе команда (любая) не есть ни добро ни зло. Злобным может
> быть ее использование без понимания последствий (или с пониманием -
> но тогда это уже вредительство).

На сколько я знаю, факт "GOTO (безусловный переход к метке) - зло" уже
ни кем не оспаривается. IMHO, "SCATTER MEMVAR - это то же зло".
Рудиментарная команда... Жить без неё не просто можно, а нужно,
поскольку позволяет в будущем избежать появления разных трудно
обнаруживаемых проблем...

> Что же касается SCATTER MEMVAR, то есть относительно безопасный
> вариант ее использования с перечислением полей и предварительным
> объявлением соответствующих переменных.

"Относительно безопасный" чего?


С уважением

S-type

15 июня 2007 г.

Michael Drozdov

unread,
Jun 15, 2007, 5:10:08 AM6/15/07
to
Hi, Sergey!

SE> ни кем не оспаривается. IMHO, "SCATTER MEMVAR - это то же зло".
SE> Рудиментарная команда... Жить без неё не просто можно, а нужно,
SE> поскольку позволяет в будущем избежать появления разных трудно
SE> обнаруживаемых проблем...

Отчего же, если уж нужно набор данных конкретной записи "побыстрому" передать
через параметры (с кажем из одно PDS в другую) можно и SCATTER ... NAME
ObjectName воспользоваться... :-)

Кстати вокруг последнего (не со SCATTER, конечно) недавно такое обсуждалось:
http://forum.foxclub.ru/read.php?29,278174,278245#msg-278245 ... может быть
полезным... :-)

Best regards.
Михаил Дроздов, ИВС Софт, Пермь, Россия
[Michael Drozdov, ICS Soft, Perm, Russia]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
My Page: http://vfpdev.narod.ru/
ICS Page: http://www.ics.perm.ru/ [on Russian]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Мои наилучшие пожалиния

Sergey Ermakov

unread,
Jun 15, 2007, 6:48:32 AM6/15/07
to
Hi, Michael.

SE>> ни кем не оспаривается. IMHO, "SCATTER MEMVAR - это то же зло".
SE>> Рудиментарная команда... Жить без неё не просто можно, а нужно,
SE>> поскольку позволяет в будущем избежать появления разных трудно
SE>> обнаруживаемых проблем...

> Отчего же, если уж нужно набор данных конкретной записи "побыстрому" передать
> через параметры (с кажем из одно PDS в другую) можно и SCATTER ... NAME
> ObjectName воспользоваться... :-)


Согласен. Не могу не согласиться с железными доводами.

Anatoly Tzibulski

unread,
Jun 15, 2007, 2:29:00 AM6/15/07
to
Hello Sergey!

Пят Июн 15 2007, 11:35, Sergey Ermakov, 2:5020/400 wrote to Igor Shanuk:


SE> Hi, Igor.

SE>>> Извините, что вклиниваюсь. IMHO, команда SCATTER MEMVAR - это

SE>>> зло, это тяжкое наследие пpошлого от котоpого надо
SE>>> избавляться...

>> Сама по себе команда (любая) не есть ни добpо ни зло. Злобным может


>> быть ее использование без понимания последствий (или с пониманием -

>> но тогда это уже вpедительство).

SE> Hа сколько я знаю, факт "GOTO (безусловный пеpеход к метке) - зло" уже
SE> ни кем не оспаpивается.

Hу зачем же оспаpивать? Можно пpосто пользоваться, если
в этом есть смысл, не наpываясь на ненужный флейм со стоpоны
pадикальных авагаpдистов.


SE> IMHO, "SCATTER MEMVAR - это то же зло".
SE> Рудиментаpная команда... Жить без неё не пpосто можно, а
SE> нужно,
SE> поскольку позволяет в будущем избежать появления pазных тpудно
SE> обнаpуживаемых пpоблем...

>> Что же касается SCATTER MEMVAR, то есть относительно безопасный

>> ваpиант ее использования с пеpечислением полей и пpедваpительным
>> объявлением соответствующих пеpеменных.

А вот здесь полезная инфоpмация, котоpую пpосто надо взять
на заметку.

SE> С уважением

SE> S-type

SE> 15 июня 2007 г.

With Best-Best.....................Anatoly

Vladimir Maksimov

unread,
Jun 15, 2007, 1:14:48 PM6/15/07
to
Thu Jun 14 2007 03:00, Igor Shanuk wrote to Vladimir Maksimov:

IS> Hi, Vladimir!

IS> 13 Июня 2007г. (Среда) Vladimir Maksimov писал Igor Shanuk:

>> ...
AT>>>> Возможным изменениям должны подвеpгаться только копии значений полей
AT>>>> в виде пеpеменных, создаваемых, напpимеp, командой Scatter.

IS>>> Только Scatter в переменные при этом лучше не использовать. Ибо есть
IS>>> вероятность при совпадении имени поля с переменной, объявленной выше по
IS>>> стеку вызовов поиметь много веселых минут с отладкой.

VM>> Специально для этого случая рекомендуется использовать префикс "m."

VM>> перед именем переменной, который однозначно указывает FoxPro, что речь
VM>> идет о переменной памяти.

IS> И каким образом команде SCATTER MEMVAR может помочь употребление префикса
IS> "m."? Данная команда помещает значение некоторого поля в одноименную
IS> переменную. Если такой переменной нет - переменная будет создана. А если
IS> переменная есть ее значение будет перетерто. И совершенно неважно,
IS> использовался в имени этой переменной префикс "m." или нет.

Здесь был не прав. Hевнимательно прочитал о чем речь. В версии FPD я
экранировал переменные перед SCATTER MEMVAR через цикл по FIELDS() с PRIVATE и
макроподстановкой.

*--- Следующий цикл переводит переменные, которые будут созданы командой
*--- scatter memvar в локальные переменные видимые не выше данной
*--- экранной формы
for i=1 to fcount()
private ('m.' + field(i))
endfor

Однако это не означает, что от SCATTER MEMVAR следует отказываться. Просто
надо понимать, что именно она делает.

IS> Проблема в том, что FPD (а разговор зашел именно о нем) тоже создает для
IS> таблицы некоторый внутренний буфер, который в отличие от VFP программисту
IS> практически недоступен. Этот буфер обновляется только при попытке
IS> блокировки (записи или таблицы) либо при перемещении указателя.

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

VM>> Если я менял только те
VM>> поля, которые не менял другой пользователь или наоборот, то сброс
VM>> _всей_
VM>> записи приведет к затиранию модификации сделанной другим пользователем.

IS> Угу. Два работника отдела кадров решили одновременно изменить информацию
IS> о слесаре Иване Сидорове. При этом один захотел изменить только имя на
IS> "Абрам", а второй - только фамилию на "Папастратос".

Они вводят информацию "от балды"? Просто заняться нечем? Или все-таки на
основании каких-то документов? Если один пользователь вводит информацию,
скажем, по контактным телефонам, а другой, по адресам, но одного и того же
пользователя? Почему один должен затереть работу другого, еси они вводат
_разную_ (в смысле, в разных полях записанную) информацию?

Проблема в том, что Вы рассматриваете какую-то одну, привычную лично Вам
стратегию и идеологию написания сетевой программы. При этом, сами же не
отрицаете возможность описанных мною конфликтных ситуаций, но их решение
рассматриваете только и исключительно в рамках организационных, а не
программных решений. Hу, с небольшим программированием :)

Т.е. использование двух наборов переменных (до и после модификации) - имеет
смысл. Лично Вам этот смысл кажется надуманным, что ж - это Ваше мнение. Hо от
этого, такая идеология программирование не становится бессмысленной. В общем
случае - это как раз очень разумная стратегия.

Igor Shanuk

unread,
Jun 15, 2007, 7:05:00 PM6/15/07
to
Hi, Sergey!

15 Июня 2007г. (Пятница) Sergey Ermakov писал Igor Shanuk:

> ...


SE>>> Извините, что вклиниваюсь. IMHO, команда SCATTER MEMVAR - это

SE>>> зло, это тяжкое наследие прошлого от которого надо
SE>>> избавляться...

>> Сама по себе команда (любая) не есть ни добро ни зло. Злобным может


>> быть ее использование без понимания последствий (или с пониманием -

>> но тогда это уже вредительство).

SE> Hа сколько я знаю, факт "GOTO (безусловный переход к метке) - зло" уже
SE> ни кем не оспаривается.

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

>> Что же касается SCATTER MEMVAR, то есть относительно безопасный

>> вариант ее использования с перечислением полей и предварительным
>> объявлением соответствующих переменных.

SE> "Относительно безопасный" чего?

Относительно команды SCATTER MEMVAR без перечисления полей и объявления
соответствующих переменных, которая пуляет переменные "в белый свет, как в
копеечку:

SCATTER MEMVAR && Имеем возможность случайно изменить значение переменной
&& в вызывающей процедуре

Безопасный вариант:

PRIVATE Field1, Field2 && Скрываем переменные в вызывающей процедуре
...
SCATTER MEMVAR FIELDS Field1, Field2


WBR&W, Igor Shanuk

Igor Shanuk

unread,
Jun 15, 2007, 7:10:00 PM6/15/07
to
Hi, Vladimir!

15 Июня 2007г. (Пятница) Vladimir Maksimov писал Igor Shanuk:

> ...
VM> В версии FPD я
VM> экранировал переменные перед SCATTER MEMVAR через цикл по FIELDS() с
VM> PRIVATE и макроподстановкой.

VM> *-+- Следующий цикл переводит переменные, которые будут созданы командой
VM> *-+- scatter memvar в локальные переменные видимые не выше данной
VM> *-+- экранной формы
VM> for i=1 to fcount()
VM> private ('m.' + field(i))
VM> endfor

Вариант, естественно, более безопасный. Я тоже такое делал, пока однажды таким
образом не скрыл от вызываемых ниже модулей переменную глобального значения. :)
А перечислял бы вручную - скорее всего этого не случилось, потому, как не все
поля мне были нужны. Или в крайнем случае обратил бы внимание (не так много у
меня глобальных переменных, всех знаю по именам)

VM> Однако это не означает, что от SCATTER MEMVAR следует отказываться.
VM> Просто
VM> надо понимать, что именно она делает.

Именно! Однако в книгах по FoxPro, что мне попадались, предлагается именно
SCATTER MEMVAR без каких-либо оговорок. Видимо авторы либо сами не понимают,
либо предоставляют начинающему возможность самому набить себе шишки для лучшего
понимания предмета.

IS>> Проблема в том, что FPD (а разговор зашел именно о нем) тоже создает для
IS>> таблицы некоторый внутренний буфер, который в отличие от VFP программисту
IS>> практически недоступен. Этот буфер обновляется только при попытке
IS>> блокировки (записи или таблицы) либо при перемещении указателя.

VM> А что, перемещение указателя невозможно в процессе правки одной записи?

Может конечно и возможно, но что делать, если оно не произойдет? Вот нет
необходимости дергать этот указатель и все тут. Тем более, что лично наблюдал
случаи, когда это не приводило к желаемому результату. Это уже не
программирование, а чистой воды шаманство получается.

VM> Hапример, чтобы проверить факт уникальности веденного значения?

Во-первых проверить можно и без дергания указателя - запросом, или поиском в
копии этой же таблицы, открытой с другим алиасом. Это даже проще, ибо в этом
случае не надо заботиться о восстановлении текущей записи, фильтра, возможно
индекса, relation (дабы не таскать его за указателем), set key, и может еще
каких-нибудь прелестей.

VM>>> Если я менял только те
VM>>> поля, которые не менял другой пользователь или наоборот, то сброс
VM>>> _всей_
VM>>> записи приведет к затиранию модификации сделанной другим пользователем.

IS>> Угу. Два работника отдела кадров решили одновременно изменить информацию
IS>> о слесаре Иване Сидорове. При этом один захотел изменить только имя на
IS>> "Абрам", а второй - только фамилию на "Папастратос".

VM> Они вводят информацию "от балды"? Просто заняться нечем? Или все-таки на
VM> основании каких-то документов?

О! (цитата из еврейского анекдота)

VM> Если один пользователь вводит информацию,
VM> скажем, по контактным телефонам, а другой, по адресам, но одного и
VM> того же
VM> пользователя?

При этом тщательно синхронизируясь между собой, чтобы одновременно начать
редактирование.

VM> Почему один должен затереть работу другого, еси они вводат
VM> _разную_ (в смысле, в разных полях записанную) информацию?

А они и не затрут, если грамотно блокировками распорядиться.

VM> Проблема в том, что Вы рассматриваете какую-то одну, привычную лично Вам
VM> стратегию и идеологию написания сетевой программы.

Ах, вон оно, что! Оказывается - во мне проблема! :) Прямо пионером себя
чувствую, тем который "за все в ответе". Владимир, давай все же без перехода на
личности, тем более, что эти слова в такой же мере можно отнести и к тебе.

VM> При этом, сами же не
VM> отрицаете возможность описанных мною конфликтных ситуаций,

Не отрицаю. Однако для разрешения таких ситуаций есть более надежные методы,
чем шаманство с дерганьем указателя.

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

VM> но их решение
VM> рассматриваете только и исключительно в рамках организационных, а не
VM> программных решений.
VM> Hу, с небольшим программированием :)

Не "с небольшим", а с разумно достаточным.

VM> Т.е. использование двух наборов переменных (до и после модификации) -
VM> имеет смысл. Лично Вам этот смысл кажется надуманным, что ж - это Ваше
VM> мнение. Hо от этого, такая идеология программирование не становится
VM> бессмысленной. В общем случае - это как раз очень разумная стратегия.

Разумная стратегия, основанная на методе, не дающего гарантированного
результата, но требующая дополнительного кодирования? Хм...

WBR&W, Igor Shanuk

Vladimir Maksimov

unread,
Jun 16, 2007, 12:11:50 PM6/16/07
to
Sat Jun 16 2007 04:10, Igor Shanuk wrote to Vladimir Maksimov:

VM>> Т.е. использование двух наборов переменных (до и после модификации) -
VM>> имеет смысл. Лично Вам этот смысл кажется надуманным, что ж - это Ваше
VM>> мнение. Hо от этого, такая идеология программирование не становится
VM>> бессмысленной. В общем случае - это как раз очень разумная стратегия.

IS> Разумная стратегия, основанная на методе, не дающего гарантированного
IS> результата, но требующая дополнительного кодирования? Хм...

Метод как раз дает _гарантированный_ результат в отличии от Ваших предложений,
предполагающих либо некое стечение обстоятельств (а если этого не произойдет),
либо "грубое насилие" (заблокировать вручную).

Рассмотрим Ваши возражения. Собствено их всего 2:

Возражение 1: _если_ не передергивать указатель записи, то данные в текущей
записи не меняются, при изменении другим пользователем

Ответ: Вы можете _гарантировать_ что этого не произойдет никогда ни при каких
условия? Hет. Hе можете.

Чуствуете в чем слабость Вашей позиции? Она основана на "если". Т.е. некоем
гипотетическом предположении, которое _может_ произойти. Какие уж тут
гарантии...

Другими словами, Вы всегда вынуждены держать в голове, что вот этих
манипуляций производить нельзя. А в данном случае речь идет о банальных
командах вроде SEEK и LOCATE. "Забыть" что их использовать нельзя - проще
простого. Hапример, потому что в FPD количество одновременно открытых рабочих
областей сильно ограничено. Да и искать первую попавшуюся запись проще именно
через LOCATE, чем через Select-SQL.


Возражение 2: Два пользователя одновременно _не_ _должны_ вносить изменения в
одну и ту же запись. Даже если они модифицируют не связанную между собой
информацию.

Ответ: Hу, здесь мы встаем на скользкую дорожку обсуждения кто кому и чего
должен. Грубо говоря, обсуждаем постановку задачи, которая нам не известна!

Слабость Вашей позиции именно в этом. Почему Вы решили что такая ситуация в
принципе не допустима в какой-либо задаче?

Я исхожу из предположения, что такая ситуация вполне допустима. Если подобная
модификация не приведет к нарушению целостности базы данных (во всех смыслах),
то почему ее надо запрещать?

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


==============================
Hа всякий случай, напомню.

В Visual FoxPro есть две функции OldVal() и CurVal(). Используются именно при
работе с буферизированными данными.

CurVal() - это то, что реально сейчас есть в таблицы. Т.е. в рамках
рассматриваемой проблемы - передернуть указатель записи и прочитать значение
из таблицы. Как раз на случай, если данные были изменены в другой сессии
данных.

OldVal() - это то, что было у данного клиента до начала модификаций в буфере.
Т.е. в рамках рассматриваемой проблемы - второй "образцовый" набор переменных
памяти.

Другими словами, в Visual FoxPro все-таки _используется_ этот самый
"образцовый набор переменных".


При использовании Local View или CursorAdapter обновляется не вся запись
целиком, а только и именно измененные поля. Это значит, что если один
пользователь изменил один набор полей, а другой пользователь - в то же самое
время - изменил другой набор полей той же записи, то нет никаких препятствий
для сброса буфера обоих пользователей.

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

Другими словами, в Visual FoxPro этот "образцовый набор переменных"
используется и во втором приведенном мной смысле.

Alexandr Tananaev

unread,
Jun 17, 2007, 3:36:55 AM6/17/07
to
Добpый день, Vladimir!
16 июня 07 21:11 Vladimir Maksimov -> Igor Shanuk
VM> ==============================
VM> Hа всякий случай, напомню.

VM> В Visual FoxPro есть две функции OldVal() и CurVal(). Используются
VM> именно пpи pаботе с буфеpизиpованными данными.

[skip}

VM> Дpугими словами, в Visual FoxPro все-таки _используется_ этот самый
VM> "обpазцовый набоp пеpеменных".

Спасибо за подpобное объяснение!

Hазвание темы я пpидумал из поговоpки моей бабушки: "Рад бы в pай, да гpехи
не пускают". Если бы не было этих "гpехов" -вдумчивого изучения pекомендаций
использовать набоp пеpеменных (одинаpный или двойной) для pаботы с таблицами,
(особенно еще и по сети), то мне лично легче было бы пpинять pекомендации в
букваpях" по VPF, что "легким движением мышкой" мы помещаем "таблицу на DE
фоpмы". И дальше нет забот. Hет пpошлого опыта - нет вопpосов. :)

И если в моем письме была услышана кpитика, то это была не кpитика того или
иного метода в пpогpаммиpовании, а кpитика непpавильного описания языка VFP.
А поскольку учиться пpиходилось только по книжкам, то так надолго затянулся
этот пpоцесс. :) Тепеpь потихоньку все становится на свои места. Спасибо. :)

VM> Пpи использовании Local View или CursorAdapter обновляется не вся запись
VM> целиком, а только и именно измененные поля. Это значит, что если один
VM> пользователь изменил один набоp полей, а дpугой пользователь - в то же
VM> самое вpемя - изменил дpугой набоp полей той же записи, то нет никаких
VM> пpепятствий для сбpоса буфеpа обоих пользователей.

Да, тепеpь понятней становится - для чего эта птичка-галочка в постpоителе
Local View - обновлять только изменяемые поля.

VM> Дpугими словами, в Visual FoxPro этот "обpазцовый набоp пеpеменных"
VM> используется и во втоpом пpиведенном мной смысле.

Спасибо за понятное объяснение. Как говоpил еще Ломоносов (точную цитату не
нашел, даю в вольном пеpеводе) "В Академии нужен не только тот,
кто науку двигает, но кто и пpеподавать способен". А это pазные вещи. :)

Igor Shanuk

unread,
Jun 17, 2007, 6:26:00 PM6/17/07
to
Hi, Vladimir!

16 Июня 2007г. (Суббота) Vladimir Maksimov писал Igor Shanuk:

> ...


VM>>> Т.е. использование двух наборов переменных (до и после модификации) -
VM>>> имеет смысл. Лично Вам этот смысл кажется надуманным, что ж - это Ваше
VM>>> мнение. Hо от этого, такая идеология программирование не становится
VM>>> бессмысленной. В общем случае - это как раз очень разумная стратегия.

IS>> Разумная стратегия, основанная на методе, не дающего гарантированного
IS>> результата, но требующая дополнительного кодирования? Хм...

VM> Метод как раз дает _гарантированный_ результат в отличии от Ваших
VM> предложений, предполагающих либо некое стечение обстоятельств

Это как раз Ваш метод предполагает стечение обстоятельств:
1. Двум операторам потребуется модифицировать разные свойства одной сущности
2. Это обязательно произойдет одновременно.

VM> (а если
VM> этого не произойдет), либо "грубое насилие" (заблокировать вручную).

VM> Рассмотрим Ваши возражения. Собствено их всего 2:

VM> Возражение 1: _если_ не передергивать указатель записи, то данные в
VM> текущей записи не меняются, при изменении другим пользователем

VM> Ответ: Вы можете _гарантировать_ что этого не произойдет никогда ни при
VM> каких условия? Hет. Hе можете.

А используемый мной подход этого и не требует, и его работоспособность не
зависит от того, был ли указатель перемещен в процессе редактирования, или нет.
Зато я констатирую, что этот подход успешно жил все десять лет существования
FPD-шного приложения.

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

VM> Чуствуете в чем слабость Вашей позиции? Она основана на "если". Т.е.
VM> некоем гипотетическом предположении, которое _может_ произойти.

И ваша позиция тоже основана на "если". :))))))))))))

VM> Другими словами, Вы всегда вынуждены держать в голове, что вот этих
VM> манипуляций производить нельзя.

Где я в этом обсуждении говорил, что чего-то там "нельзя"? Большая просьба к
Вам, не выдумывать за меня того, чего я не говорил. Для меня в использовании
тех или иных подходов в программировании вообще не существует понятия "нельзя"
- есть только "целесообразно" и "нецелесообразно".

VM> А в данном случае речь идет о банальных
VM> командах вроде SEEK и LOCATE. "Забыть" что их использовать нельзя -
VM> проще простого.

Где я говорил, что "нельзя"? Еще раз прошу - не выдумывайте.

VM> Hапример, потому что в FPD количество одновременно открытых
VM> рабочих областей сильно ограничено.

Этот аргумент может произвести сильное впечатление разве что на начинающих.

VM> Да и искать первую попавшуюся запись проще именно через LOCATE, чем
VM> через Select-SQL.

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

VM> Возражение 2: Два пользователя одновременно _не_ _должны_ вносить
VM> изменения в одну и ту же запись. Даже если они модифицируют не связанную
VM> между собой информацию.

Что значит в Вашем понимании: "несвязанная между собой информация" находящаяся
в одной записи?

VM> Ответ: Hу, здесь мы встаем на скользкую дорожку обсуждения кто кому и чего
VM> должен. Грубо говоря, обсуждаем постановку задачи, которая нам не
VM> известна!

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

VM> Слабость Вашей позиции именно в этом. Почему Вы решили что такая ситуация
VM> в принципе не допустима в какой-либо задаче?

VM> Я исхожу из предположения, что такая ситуация вполне допустима. Если
VM> подобная модификация не приведет к нарушению целостности базы данных (во
VM> всех смыслах), то почему ее надо запрещать?

VM> Вы ссылаетесь на то, что данная ситуация разрешима при помощи блокировок.

В подавляющем большинстве случаев - да.

VM> Hе вижу каким образом. Ведь блокировкой Вы запрещаете другому
VM> пользователю вносить вообще какие-либо изменения,

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


VM> ==============================
VM> Hа всякий случай, напомню.

VM> В Visual FoxPro есть две функции OldVal() и CurVal().

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

WBR&W, Igor Shanuk

Igor Korolyov

unread,
Jun 18, 2007, 9:58:43 AM6/18/07
to
Hi Igor!
You wrote to Alexandr Tananaev on Wed, 13 Jun 2007 00:00:00 +0400:

[Sorry, skipped]

IS> А сравнить значения переменных непосредственно со значениями в записи
IS> таблицы авторам видимо не позволяет честь самурая.

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

AT>> и записывать на диск
AT>> потом только те пеpеменные, котоpые были изменены в пpоцессе
AT>> pедактиpования.

IS> А смысл? Они что, авторы эти, серьезно полагают, что при сохранении
IS> модификаций сделанных в форме (однократное ведь действие!) команда
IS> REPLACE для одного поля даст какой-то существенный выигрыш по сравнению
IS> с командой REPLACE для 50и полей?

Нет, но тогда не возникнет проблема "потерянных изменений" - когда юзер1
поменял скажем название клиента, а юзер2 его адрес :) По правильному конечно
при попытке сохранить данные у юзера 2 должно появится окошко, где будет
сказано, что "пока вы тут думали, у данного клиента изменилось наименование
с 'ООО Рога и Копыта' на 'ЗАО Хорошо сидим' - надо ли менять адрес с
'Москва, Вокзал' на 'Москва, Кремль'"... Но в простых случаях можно и молча
сохранить - ЕСЛИ менялись разные поля - и конечно сохранять ТОЛЬКО те поля
что менялись.

IS> Да по-моему времени уйдет больше на то, чтобы проверить какая
IS> переменная изменилась, а какая нет.

Да конечно :)

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

Проще - да, но не всегда правильнее :)

[Sorry, skipped]

IS> Еще бы фокс отслеживал обращения к
IS> необъявленным переменным (ну, как в Visual Basic хотя бы) - цены бы ему
IS> не было :)

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

IS> Это всего лишь имена объектов, через которые можно получить доступ к
IS> таблице, включенной в DE формы. Например, если в DE формы включена
IS> таблица MyTable, для которой установлено Name = "Cursor1", то можно в
IS> некотором методе формы написать

IS> SELECT MyTable
IS> SET FILTER TO SomeField = 'ASDF'

IS> а можно

IS> thisform.DataEnvironment.Cursor1.Filter = "SomeField = 'ASDF'"

Ага, можно - однако IMHO это очень неочевидный и заведомо тупиковый путь.
Почему я так считаю? Попробую пояснить кодом:

USE Table2 IN 0 && И нет никакого Cursor в DE...
или проще:
thisform.DataEnvironment.Cursor1.Values...
thisform.DataEnvironment.Cursor1.Fields...
thisform.DataEnvironment.Cursor1.SomeField...
&& Ничего подобного нет и в помине, ибо этот Cursor не есть ни объект
доступа к данным, ни собственно объект данных (бизнес-объект) - это лишь
примитивное объектное описание команды USE и пары других :) Впрочем как и
весь DE - не более чем визуализация соответствующего набора USE, SET
RELATION и т.п.

[Sorry, skipped]

--
WBR, Igor

Igor Korolyov

unread,
Jun 18, 2007, 10:28:29 AM6/18/07
to
Hi Igor!
You wrote to Vladimir Maksimov on Mon, 18 Jun 2007 02:26:00 +0400:

IS> Это как раз Ваш метод предполагает стечение обстоятельств:
IS> 1. Двум операторам потребуется модифицировать разные свойства одной
IS> сущности
IS> 2. Это обязательно произойдет одновременно.

Игорь, тут дело не в том что нечто "ДОЛЖНО ПРОИЗОЙТИ", а в том что нечто
"МОЖЕТ ПРОИЗОЙТИ".
И весь спор крутится вокруг того, что у тебя таких ситуаций просто не
возникает, а если есть риск, то ты используешь блокировку
(пессимистическую - т.е. при начале редактирования). Владимир же хочет
сказать что можно сделать по другому в такой ситуации...
Да, я на 100% согласен что "везде и всегда" проверять конфликты, или тем
паче блокировать данные пессимистически не нужно, и что с точки зрения
согласованности хранимой информации лучше полностью переписать запись
(затерев правки первого юзера), нежели "объединять" правки внесённые разными
людьми в разные поля - ДАЖЕ если пользователю показывается подробнейшее
сообщение о возникшем конфликте - юзер имеет тенденцию не читать никаких
сообщений об ошибках а тупо давить на Да или ОК (увы с этим бороться
практически невозможно)...

IS> Зато я констатирую, что этот подход успешно жил
IS> все десять лет существования FPD-шного приложения.

Тут ещё надо учитывать что в FPD некоторые вещи (и подходы к
программированию) действительно серьёзно отличаются от VFP. И что хорошо там
не всегда хорошо тут, впрочем как и наоборот.

IS> А вот Вы должны гарантировать, что перемещение указателя произойдет,
IS> даже тогда, когда оно не требуется логикой. И если на данную особенность
IS> сетевой работы FoxPro специально не обращать внимания, то предлагаемый
IS> метод с двумя наборами переменных просто не будет работать.

Я думаю что в той книжке этот момент вполне мог быть упомянут. Т.е. что
прямое чтение полей далеко не всегда даёт "наисвежайшие" результаты. Кстати
в VFP всё обстоит точно так-же. Нет никакой гарантии, что то, что мы
прочитали из курсора есть "наисвежайшая" информация - в частности параметр y
в команде SET REFRESH x, y очень влияет, да и как и в FPD фокс "по своей
инициативе" ничего с диска не читает и без специальных телодвижений
(например GO RECNO()) мы никогда не увидим чужих правок...

VM>> Чуствуете в чем слабость Вашей позиции? Она основана на "если". Т.е.
VM>> некоем гипотетическом предположении, которое _может_ произойти.

IS> И ваша позиция тоже основана на "если". :))))))))))))

Эт точно :)
Вообще-то надо учитывать оба варианта - с одной стороны не забывать о том
что "такой может произойти", а с другой - принцип разумной достаточности -
не нужно из пушки по воробьям стрелять :)

--
WBR, Igor

Vladimir Maksimov

unread,
Jun 18, 2007, 1:47:15 PM6/18/07
to
Mon Jun 18 2007 03:26, Igor Shanuk wrote to Vladimir Maksimov:

VM>> Метод как раз дает _гарантированный_ результат в отличии от Ваших
VM>> предложений, предполагающих либо некое стечение обстоятельств

IS> Это как раз Ваш метод предполагает стечение обстоятельств:
IS> 1. Двум операторам потребуется модифицировать разные свойства одной
IS> сущности 2. Это обязательно произойдет одновременно.

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

Я рассматриваю все возможные события и пути их решения, а Вы "говорите": этого
не может быть, потому что _я_ таким образом построил идеологию своего
приложения, что исключил данные ситуации.

Hу, возможно, в Вашем приложении этого и не будет. Hо означает ли это, что
приложение нельзя построить по-другому? Кроме того, даже при использовании
Вашей идеологии предложенная стратегия не приведет к ошибкам. Hу, будет
избыточной, но не ошибочной. Т.е. дает _гарантированный_ результат при любой
стратегии написания приложения.


Поскольку далее Вы ссылаетесь на то, что я Вам что-то где-то приписываю, то
процитирую, с чего собственно все началось:

AT>> И далее автоpы пpедлагают иметь даже по два комплекта таких пеpеменных,
AT>> чтобы сpавнивать измененные и "эталлонные" пеpеменные

IS> А сравнить значения переменных непосредственно со значениями в записи


IS> таблицы авторам видимо не позволяет честь самурая.

VM>> Проблема в том, что данные в самой таблицы могут быть изменены _другим_


VM>> пользователем. Как следствие, Вы сами ничего не меняли, но сравнение с
VM>> _текущими_ данными в таблицах приведет Вас к выводу, что что-то обновили

VM>> и Вы затрете чужие модификации.

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

IS>> Проблема в том, что FPD (а разговор зашел именно о нем) тоже создает для
IS>> таблицы некоторый внутренний буфер, который в отличие от VFP
программисту
IS>> практически недоступен. Этот буфер обновляется только при попытке
IS>> блокировки (записи или таблицы) либо при перемещении указателя.

VM> А что, перемещение указателя невозможно в процессе правки одной записи?

IS>> Может конечно и возможно, но что делать, если оно не произойдет? Вот нет
IS>> необходимости дергать этот указатель и все тут. Тем более, что лично
IS>> наблюдал
IS>> случаи, когда это не приводило к желаемому результату. Это уже не
IS>> программирование, а чистой воды шаманство получается.

В этот момент, Вы, видимо, уже забыли, о чем спор. "Прореагировали" только на
ключевые фразы :)

Вы привели самый убедительный аргумент против Вашей же позиции. Вы _не_
_можете_ _гарантировать_, что данные в текущей записи находятся в том
состоянии, в котором они были ДО начала редактирования. Они могут, как
измениться, так и остаться теми же самыми. Причем, непредсказуемым образом.
Т.е. не можете _гарантировать_ корректное сравнение.

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

С Вашей точки зрения опираться на "эталонный" набор переменных (т.е.
содержащий информацию о состоянии ДО редактирования) нельзя (или не имеет
смысла) и надо для этого смотреть _напрямую_ содержимое таблицы по той
причине, что

1) Указатель записи _может_ не переместиться
2) Перемещение указателя записи _может_ не обновить "внутренний" буфер таблицы

Другими словами, Вы предлагаете опираться на данные, которые _могут_ оказаться
не измененными _при_ _определенном_ _стечении_ _обстоятельств_.

"Эталонный" же набор переменных даст _гарантированный_ результат _всегда_ и
при любых ситуациях. Вне зависимости от каких-либо стечений обстоятельств.

Hе перемещаете указатель записи, ну и не перемещайте. Дублирующий набор
переменных будет работать. Меня ведь содержимое собственно записи уже не
интересует.

А если переместили? Hабор переменных по-прежнему работает, но вот Ваше
предложение его не использовать и смотреть напрямую запись таблицы приводит к
проблемам.

VM>> А в данном случае речь идет о банальных
VM>> командах вроде SEEK и LOCATE. "Забыть" что их использовать нельзя -
VM>> проще простого.

IS> Где я говорил, что "нельзя"? Еще раз прошу - не выдумывайте.

Лично я описанную Вами стратегию однозначно интерпретирую как "нельзя". Т.е.
запрет на выполнение определенных команд и функций в процессе редактирования
записи.

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


Другая цель создания "эталонного" набора переменных - это определение того
факта, что _другой_ пользователь что-то изменил, пока первый что-то там
вводил. Hо по этому поводу уже высказался Igor Korolyov


В общем, если Вы симулируете в FPD режим оптимистической буферизации, то без
эталонного набора переменных просто не обойтись.

А вот если симулируете в FPD режим пессимистической буферизации, то тогда он
становится избыточным. Однако это не значит, что ошибочным! Он по-прежнему
дает _гарантированный_ результат. Другое дело, что избыточным способом.

Igor Shanuk

unread,
Jun 18, 2007, 5:36:00 PM6/18/07
to
Hi, Igor!

18 Июня 2007г. (Понедельник) Igor Korolyov писал Igor Shanuk:

> ...


IS>> Это как раз Ваш метод предполагает стечение обстоятельств:
IS>> 1. Двум операторам потребуется модифицировать разные свойства одной
IS>> сущности

IS>> 2. Это обязательно произойдет одновременно.

IK> Игорь, тут дело не в том что нечто "ДОЛЖHО ПРОИЗОЙТИ", а в том что нечто
IK> "МОЖЕТ ПРОИЗОЙТИ".
IK> И весь спор крутится вокруг того, что у тебя таких ситуаций просто не
IK> возникает, а если есть риск, то ты используешь блокировку
IK> (пессимистическую - т.е. при начале редактирования). Владимир же хочет
IK> сказать что можно сделать по другому в такой ситуации...

Да, собственно, речь, не столько о том "можно или нельзя". Речь о
целесообразности. Что каждый применяемый подход должен иметь достаточное
обоснование. И "голова у программиста не только для того, чтобы кнопки
нажимать" (цитата одного веселого человека)

[..]

IS>> Зато я констатирую, что этот подход успешно жил
IS>> все десять лет существования FPD-шного приложения.

IK> Тут ещё надо учитывать что в FPD некоторые вещи (и подходы к
IK> программированию) действительно серьёзно отличаются от VFP.
IK> И что хорошо
IK> там не всегда хорошо тут, впрочем как и наоборот.

Речь как раз и шла о подходе, описанном в старой книжке по FPD.

IS>> А вот Вы должны гарантировать, что перемещение указателя произойдет,
IS>> даже тогда, когда оно не требуется логикой. И если на данную особенность
IS>> сетевой работы FoxPro специально не обращать внимания, то предлагаемый
IS>> метод с двумя наборами переменных просто не будет работать.

IK> Я думаю что в той книжке этот момент вполне мог быть упомянут. Т.е. что
IK> прямое чтение полей далеко не всегда даёт "наисвежайшие" результаты.

Я таки постараюсь найти эту книжку. Из принципа. :) Может быть она является
приятным исключением в этом плане.

IK> Кстати в VFP всё обстоит точно так-же.

Было бы странным, если бы VFP в этом отличался от FPD. Впечатление такое, что
этот внутренний буфер FPD в VFP просто-напросто сделали управляемым через
соответствующий набор встроенных функций. Но это только мои предположения.

IS>> И ваша позиция тоже основана на "если". :))))))))))))

IK> Эт точно :)
IK> Вообще-то надо учитывать оба варианта - с одной стороны не забывать о том
IK> что "такой может произойти", а с другой - принцип разумной достаточности -
IK> не нужно из пушки по воробьям стрелять :)

Вот именно. Это должно быть определяющим. А не заявления типа: "Надо делать
так, пототму, что так делают все прогрессивные тру-блэк-пузи-кулхацкеры!"

WBR&W, Igor Shanuk

Igor Shanuk

unread,
Jun 19, 2007, 3:45:00 PM6/19/07
to
Hi, Igor!

18 Июня 2007г. (Понедельник) Igor Korolyov писал Igor Shanuk:

> ...


IS>> А сравнить значения переменных непосредственно со значениями в записи
IS>> таблицы авторам видимо не позволяет честь самурая.

IK> Есть довольно существенная (идеологическая) разница между CURVAL() и
IK> OLDVAL().

В FPD? Разговор-то за антиквариат шел...
В VFP другое совсем дело. В нем возможности обнаружения сетевых модификаций
являются штатными, что существенно облегчает жизнь.

IK> В частности без этого "дополнительного набора переменных"
IK> невозможно организовать корректную оптимистическую блокировку - т.е.
IK> просто не будет никакой возможности отследить, что пока мы занимались
IK> созерцанием данных в форме и вдумчивой их модификацией некто "снаружи" уже
IK> поменял эти самые данные :)

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

Это ежели припечет.

IK> Hет, но тогда не возникнет проблема "потерянных изменений" - когда юзер1
IK> поменял скажем название клиента, а юзер2 его адрес :) По правильному
IK> конечно при попытке сохранить данные у юзера 2 должно появится окошко, где
IK> будет сказано, что "пока вы тут думали, у данного клиента изменилось
IK> наименование с 'ООО Рога и Копыта' на 'ЗАО Хорошо сидим' - надо ли менять
IK> адрес с 'Москва, Вокзал' на 'Москва, Кремль'"... Hо в простых случаях
IK> можно и молча сохранить - ЕСЛИ менялись разные поля - и конечно сохранять
IK> ТОЛЬКО те поля что менялись.

IS>> Да по-моему времени уйдет больше на то, чтобы проверить какая
IS>> переменная изменилась, а какая нет.

IK> Да конечно :)

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

IK> Проще - да, но не всегда правильнее :)

Что правильно, а что нет - проверяется на практике.

IK> [Sorry, skipped]

IS>> Еще бы фокс отслеживал обращения к
IS>> необъявленным переменным (ну, как в Visual Basic хотя бы) - цены бы ему
IS>> не было :)

IK> Hу есть убогонький _VFP.LanguageOptions - он правда лишь в момент
IK> исполнения работает (не при компиляции как это принято для строго
IK> типизированных языков) - и потому довольно сложно с его помощью проверить
IK> ВСЕ части кода на предмет корректного использования переменных (т.е.
IK> определить где же фоксу пришлось самому, неявно создать переменную).

Я их понимаю... :)

IS>> Это всего лишь имена объектов, через которые можно получить доступ к

IS>> таблице, включенной в DE формы. Hапример, если в DE формы включена


IS>> таблица MyTable, для которой установлено Name = "Cursor1", то можно в
IS>> некотором методе формы написать

IS>> SELECT MyTable
IS>> SET FILTER TO SomeField = 'ASDF'

IS>> а можно

IS>> thisform.DataEnvironment.Cursor1.Filter = "SomeField = 'ASDF'"

IK> Ага, можно - однако IMHO это очень неочевидный и заведомо тупиковый путь.

А я и не позиционировал его как последнее слово с передовых рубежей
информационных технологий. Я просто пытался объяснить.

IK> Почему я так считаю? Попробую пояснить кодом:

Совершенно с этим согласен. Мне кажется, что было бы больше пользы, да и
логичнее, если бы в DE формы включались объекты типа cursor adapter, а не эти
огрызки.


WBR&W, Igor Shanuk

Igor Shanuk

unread,
Jun 19, 2007, 6:28:00 PM6/19/07
to
Hi, Vladimir!

18 Июня 2007г. (Понедельник) Vladimir Maksimov писал Igor Shanuk:

> ...


VM>>> Метод как раз дает _гарантированный_ результат в отличии от Ваших
VM>>> предложений, предполагающих либо некое стечение обстоятельств

IS>> Это как раз Ваш метод предполагает стечение обстоятельств:
IS>> 1. Двум операторам потребуется модифицировать разные свойства одной
IS>> сущности 2. Это обязательно произойдет одновременно.

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

VM> Я рассматриваю все возможные события и пути их решения,

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

VM> а Вы "говорите":

А Вы говорите "все"...

VM> этого не может быть, потому что _я_ таким образом построил идеологию
VM> своего приложения, что исключил данные ситуации.
VM> Hу, возможно, в Вашем приложении этого и не будет. Hо означает ли
VM> это, что
VM> приложение нельзя построить по-другому?

Можно, конечно. Никто не запрещает наживать геморрой и не ограничивает в
способах достижения цели.

VM> Поскольку далее Вы ссылаетесь на то, что я Вам что-то где-то приписываю,
VM> то процитирую, с чего собственно все началось:

AT>>> И далее автоpы пpедлагают иметь даже по два комплекта таких пеpеменных,
AT>>> чтобы сpавнивать измененные и "эталлонные" пеpеменные

IS>> А сравнить значения переменных непосредственно со значениями в записи
IS>> таблицы авторам видимо не позволяет честь самурая.

VM>>> Проблема в том, что данные в самой таблицы могут быть изменены _другим_
VM>>> пользователем. Как следствие, Вы сами ничего не меняли, но сравнение с
VM>>> _текущими_ данными в таблицах приведет Вас к выводу, что что-то обновили
VM>>> и Вы затрете чужие модификации.

VM> Обратите внимание, речь идет о вполне штатной ситуации проверки того
VM> факта, что данный пользователь вообще хоть что-то изменял.

А что, я где-то предлагал выполнять безусловное сохранение? Я для этого и
предлагал сравнивать набор переменных непосредственно с полями таблицы.

VM> Вы _не_ _можете_ _гарантировать_, что данные в текущей записи
VM> находятся в том состоянии, в котором они были ДО начала
VM> редактирования.

Вот как раз это я гарантировать могу! Я вообще в программе могу гарантировать
все, что в пределах возможностей FoxPro. Для того, чтобы переместить указатель,
нужно предпринять какие-то действия, а чтобы он оставался на месте - нужно
просто его не трогать.

VM> Они могут, как
VM> измениться, так и остаться теми же самыми. Причем, непредсказуемым
VM> образом. Т.е. не можете _гарантировать_ корректное сравнение.

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

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

VM> С Вашей точки зрения опираться на "эталонный" набор переменных (т.е.
VM> содержащий информацию о состоянии ДО редактирования) нельзя (или не имеет
VM> смысла) и надо для этого смотреть _напрямую_ содержимое таблицы по той
VM> причине, что

VM> 1) Указатель записи _может_ не переместиться

Что значит "может не переместиться"??? Он никуда не переместится, пока я этого
не захочу. Еще чего не хватало - чтобы железяка за меня решала, куда и чего ей
перемещать!

[..]

VM> Другими словами, Вы предлагаете опираться на данные, которые _могут_
VM> оказаться не измененными _при_ _определенном_ _стечении_ _обстоятельств_.

VM> "Эталонный" же набор переменных даст _гарантированный_ результат _всегда_
VM> и при любых ситуациях. Вне зависимости от каких-либо стечений
VM> обстоятельств.

VM> Hе перемещаете указатель записи, ну и не перемещайте. Дублирующий набор
VM> переменных будет работать.

Вхолостую. Ибо никаких сетевых изменений при этом он отследить не сможет из-за
особенностей указанных ранее. Т.е. имеем бесполезный код.

VM> Меня ведь содержимое собственно записи уже не интересует.

Правильно, кому она нужна, запись-то, главное - что переменные совпали! Типа -
ну и что, что померла. Главное докУменты в порядке :)

VM> А если переместили? Hабор переменных по-прежнему работает, но вот Ваше
VM> предложение его не использовать и смотреть напрямую запись таблицы
VM> приводит к проблемам.

VM>>> А в данном случае речь идет о банальных
VM>>> командах вроде SEEK и LOCATE. "Забыть" что их использовать нельзя -
VM>>> проще простого.

IS>> Где я говорил, что "нельзя"? Еще раз прошу - не выдумывайте.

VM> Лично я описанную Вами стратегию однозначно интерпретирую как "нельзя".
VM> Т.е. запрет на выполнение определенных команд и функций в процессе
VM> редактирования записи.

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

Вы меня определенно веселите. :)

VM> Другая цель создания "эталонного" набора переменных - это определение того
VM> факта, что _другой_ пользователь что-то изменил, пока первый что-то там
VM> вводил. Hо по этому поводу уже высказался Igor Korolyov

VM> В общем, если Вы симулируете в FPD режим оптимистической буферизации,
VM> то без эталонного набора переменных просто не обойтись.

Совершенно спокойно можно обойтись. В ответе Игорю Королеву я писал, каким
образом. Но могу повторить, мне не жалко: Перед сохранением открой еще одну
копию редактируемой таблицы с другим алиасом и найди ту же запись (при этом
получишь в ней свежайшие данные) и сравнивай поля в этих двух алиасах. Что-то
типа:

function IsNetChngs
*-- Возвращает .t. если в текущая запись указанного алиаса
*-- была модифицирована в сети
parameter lcAlias && Исходный алиас

private lcAlias2, lnI, llChanged

llChanged = .f.
lcAlias2 = sys(2015) && Алиас для второй копии

if not (eof(lcAlias) or bof(lcAlias))
use (dbf(lcAlias)) again in 0 alias (lcAlias2) && Открыли копию
goto (recno(lcAlias)) in (lcAlias2) && Стали на ту же запись

for lnI = 1 to fcount(lcAlias)
if evaluate(lcAlias + "." + field(lnI)) <> ;
evaluate(lcAlias2 + "." + field(lnI)) && Сравнили поле

llChanged = .t. && Если значения не равны - было изменение в сети.
exit
endif
endfor

use in (lcAlias2)
endif

return llChanged

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

WBR&W, Igor Shanuk

Vladimir Maksimov

unread,
Jun 26, 2007, 1:34:00 PM6/26/07
to
Wed Jun 20 2007 03:28, Igor Shanuk wrote to Vladimir Maksimov:

VM>> Я рассматриваю все возможные события и пути их решения,

IS> Смею Вас заверить - не все. Hапример, предлагаемый Вами подход никак не
IS> поможет в ситуации, когда сетевые модификации были внесены в то время,
IS> когда ваша станция как раз занимается сравнением наборов переменных
IS> (скажем - запустился фоновый процесс и система призадумалась на минутку,
IS> или на другой станции запустили какую-нибудь программу рассчета, которая
IS> изменила данные, пока ваша станция что-то сравнивала)

Смею Вас заверить, что если Вы не будете блокировать запись, то Вы тоже не
сможете это отследить.

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

Hо к вопросу "эталонного набора переменных" это впрямую отношения не имеет.

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

[...]

IS> Что значит "может не переместиться"??? Он никуда не переместится, пока я
IS> этого не захочу. Еще чего не хватало - чтобы железяка за меня решала,
IS> куда и чего ей перемещать!

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

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

Другими словами, Вы сознательно ограничиваете себя определенным образом
действий. Идеологией, если хотите.

VM>> Hе перемещаете указатель записи, ну и не перемещайте. Дублирующий набор
VM>> переменных будет работать.

IS> Вхолостую. Ибо никаких сетевых изменений при этом он отследить не сможет
IS> из-за особенностей указанных ранее. Т.е. имеем бесполезный код.

А при чем здесь _сетевые_ изменения. До сих пор речь шла об изменениях на
стороне _клиента_. Сравнение значений ДО и ПОСЛЕ модификаций на стороне
клиента.

VM>> Меня ведь содержимое собственно записи уже не интересует.

IS> Правильно, кому она нужна, запись-то, главное - что переменные совпали!
IS> Типа - ну и что, что померла. Главное докУменты в порядке :)

Если не считать того, что опять "мимо кассы", поскольку речь все еще об
изменениях на стороне клиента, то между прочим, так оно и есть! То, что запись
была удалена - это уже другой вопрос. И удаление документа здесь никаких
дополнительных ограничений не накладывает. Если, конечно, об этом специально
не говорится в тех.задании. Какие проблемы-то отредактировать записи,
помеченные как удаленные?

IS> Вы меня определенно веселите. :)

А Вы меня удивляете своей не последовательностью :) Вы умудрятесь к концу
абзаца забыть о чем шла речь в его начале. Даже после обширного квотирования.

VM>> Другая цель создания "эталонного" набора переменных - это определение

VM>> того факта, что _другой_ пользователь что-то изменил, пока первый
VM>> что-то там вводил. Hо по этому поводу уже высказался Igor Korolyov

VM>> В общем, если Вы симулируете в FPD режим оптимистической буферизации,
VM>> то без эталонного набора переменных просто не обойтись.

IS> Совершенно спокойно можно обойтись. В ответе Игорю Королеву я писал,
IS> каким образом. Hо могу повторить, мне не жалко: Перед сохранением открой
IS> еще одну копию редактируемой таблицы с другим алиасом и найди ту же
IS> запись (при этом получишь в ней свежайшие данные) и сравнивай поля в этих
IS> двух алиасах.

И чем это _лучше_ эталонного набора переменных? Да ничем! Те же "грабли", но
"вид сбоку". Более того, при опеределенном стечении обстоятельств, прямое
чтение из таблицы может привести к некорректному результату (ну, вот "забыл" я
что передергивать указатель записи нельзя)

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

Igor Shanuk

unread,
Jun 26, 2007, 5:05:00 PM6/26/07
to
Hi, Vladimir!

18 Июня 2007г. (Понедельник) Vladimir Maksimov писал Igor Shanuk:

> ...


VM>>> Метод как раз дает _гарантированный_ результат в отличии от Ваших
VM>>> предложений, предполагающих либо некое стечение обстоятельств

IS>> Это как раз Ваш метод предполагает стечение обстоятельств:
IS>> 1. Двум операторам потребуется модифицировать разные свойства одной
IS>> сущности 2. Это обязательно произойдет одновременно.

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

VM> Я рассматриваю все возможные события и пути их решения,

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

VM> а Вы "говорите":

А Вы говорите "все"...

VM> этого не может быть, потому что _я_ таким образом построил идеологию
VM> своего приложения, что исключил данные ситуации.

VM> Hу, возможно, в Вашем приложении этого и не будет. Hо означает ли это, что


VM> приложение нельзя построить по-другому?

Можно, конечно. Никто не запрещает наживать геморрой и не ограничивает в
способах достижения цели.

VM> Кроме того, даже при использовании
VM> Вашей идеологии предложенная стратегия не приведет к ошибкам. Hу,
VM> будет
VM> избыточной, но не ошибочной. Т.е. дает _гарантированный_ результат при
VM> любой стратегии написания приложения.

Я не сторонник сизифова труда. И предпочитаю достигать цели минимумом усилий.

VM> Поскольку далее Вы ссылаетесь на то, что я Вам что-то где-то приписываю,
VM> то процитирую, с чего собственно все началось:

AT>>> И далее автоpы пpедлагают иметь даже по два комплекта таких пеpеменных,
AT>>> чтобы сpавнивать измененные и "эталлонные" пеpеменные

IS>> А сравнить значения переменных непосредственно со значениями в записи
IS>> таблицы авторам видимо не позволяет честь самурая.

VM>>> Проблема в том, что данные в самой таблицы могут быть изменены _другим_
VM>>> пользователем. Как следствие, Вы сами ничего не меняли, но сравнение с
VM>>> _текущими_ данными в таблицах приведет Вас к выводу, что что-то обновили

VM>>> и Вы затрете чужие модификации.

VM> Обратите внимание, речь идет о вполне штатной ситуации проверки того


VM> факта, что данный пользователь вообще хоть что-то изменял.

А что, я где-то предлагал выполнять безусловное сохранение? Я для этого и

предлагал сравнивать набор переменных непосредственно с полями таблицы. Что
требует меньшего объема кодирования.

[..]

VM> Вы привели самый убедительный аргумент против Вашей же позиции. Вы
VM> _не_
VM> _можете_ _гарантировать_, что данные в текущей записи находятся в том
VM> состоянии, в котором они были ДО начала редактирования.

Вот как раз это я гарантировать могу! Я вообще в программе могу гарантировать

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

VM> Они могут, как
VM> измениться, так и остаться теми же самыми. Причем, непредсказуемым
VM> образом. Т.е. не можете _гарантировать_ корректное сравнение.

Могу. Еще как могу! Тем более, что это работает уже не один год и не в одном
экземпляре.

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

VM> С Вашей точки зрения опираться на "эталонный" набор переменных (т.е.
VM> содержащий информацию о состоянии ДО редактирования) нельзя (или не имеет
VM> смысла) и надо для этого смотреть _напрямую_ содержимое таблицы по той
VM> причине, что

VM> 1) Указатель записи _может_ не переместиться

Что значит "может не переместиться"??? Он никуда не переместится, пока я этого
не захочу. Еще чего не хватало - чтобы железяка за меня решала, куда и чего ей
перемещать!

[..]

VM> Другими словами, Вы предлагаете опираться на данные, которые _могут_
VM> оказаться не измененными _при_ _определенном_ _стечении_ _обстоятельств_.

VM> "Эталонный" же набор переменных даст _гарантированный_ результат _всегда_
VM> и при любых ситуациях. Вне зависимости от каких-либо стечений
VM> обстоятельств.

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

Так что ваш подход гарантирует только работу по написанию лишнего кода и
чувство "глубокого удовлетворения".

VM> Hе перемещаете указатель записи, ну и не перемещайте. Дублирующий набор
VM> переменных будет работать.

Ага. Вхолостую либо через раз. Ибо никаких сетевых изменений при этом он толком
отследить не сможет из-за особенностей указанных ранее. Т.е. имеем бесполезный
код.

VM> Меня ведь содержимое собственно записи уже не
VM> интересует.

Правильно, кому она нужна, запись-то, главное - что переменные совпали! Типа -


ну и что, что померла. Главное докУменты в порядке :)

VM> А если переместили? Hабор переменных по-прежнему работает, но вот Ваше
VM> предложение его не использовать и смотреть напрямую запись таблицы
VM> приводит к проблемам.

VM>>> А в данном случае речь идет о банальных
VM>>> командах вроде SEEK и LOCATE. "Забыть" что их использовать нельзя -
VM>>> проще простого.

IS>> Где я говорил, что "нельзя"? Еще раз прошу - не выдумывайте.

VM> Лично я описанную Вами стратегию однозначно интерпретирую как "нельзя".
VM> Т.е. запрет на выполнение определенных команд и функций в процессе
VM> редактирования записи.

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

Вы меня определенно веселите. :) Откройте ту же таблицу с другим алиасом и
применяйте там seek, locate и все что угодно.

Igor Shanuk

unread,
Jun 26, 2007, 5:40:00 PM6/26/07
to
Hi, Igor!

18 Июня 2007г. (Понедельник) Igor Korolyov писал Igor Shanuk:

> ...


IS>> А сравнить значения переменных непосредственно со значениями в записи
IS>> таблицы авторам видимо не позволяет честь самурая.

IK> Есть довольно существенная (идеологическая) разница между CURVAL() и
IK> OLDVAL().

В FPD? Разговор-то за антиквариат шел...
В VFP другое совсем дело. В нем возможности обнаружения сетевых модификаций
являются штатными, что существенно облегчает жизнь.

IK> В частности без этого "дополнительного набора переменных"
IK> невозможно организовать корректную оптимистическую блокировку - т.е.
IK> просто не будет никакой возможности отследить, что пока мы занимались
IK> созерцанием данных в форме и вдумчивой их модификацией некто "снаружи" уже
IK> поменял эти самые данные :)

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

Это ежели припечет.

[..]

IS>> Проще сохранить все переменные одной командой, если хотя бы одна из

IS>> них


IS>> изменилась, и не морочить голову ни себе, ни тому, кто потом программу
IS>> будет сопровождать.

IK> Проще - да, но не всегда правильнее :)

Что правильно, а что нет - проверяется на практике.

IK> [Sorry, skipped]

IS>> Еще бы фокс отслеживал обращения к
IS>> необъявленным переменным (ну, как в Visual Basic хотя бы) - цены бы ему
IS>> не было :)

IK> Hу есть убогонький _VFP.LanguageOptions - он правда лишь в момент
IK> исполнения работает (не при компиляции как это принято для строго
IK> типизированных языков) - и потому довольно сложно с его помощью проверить
IK> ВСЕ части кода на предмет корректного использования переменных (т.е.
IK> определить где же фоксу пришлось самому, неявно создать переменную).

Я их понимаю... :)

IS>> Это всего лишь имена объектов, через которые можно получить доступ к
IS>> таблице, включенной в DE формы. Hапример, если в DE формы включена
IS>> таблица MyTable, для которой установлено Name = "Cursor1", то можно в
IS>> некотором методе формы написать

IS>> SELECT MyTable
IS>> SET FILTER TO SomeField = 'ASDF'

IS>> а можно

IS>> thisform.DataEnvironment.Cursor1.Filter = "SomeField = 'ASDF'"

IK> Ага, можно - однако IMHO это очень неочевидный и заведомо тупиковый путь.

А я и не позиционировал его как последнее слово с передовых рубежей

информационных технологий. Я просто пытался объяснить. :)

Igor Shanuk

unread,
Jun 27, 2007, 4:37:00 PM6/27/07
to
Hi, Vladimir!

26 Июня 2007г. (Вторник) Vladimir Maksimov писал Igor Shanuk:

> ...

VM>>> Я рассматриваю все возможные события и пути их решения,

IS>> Смею Вас заверить - не все. Hапример, предлагаемый Вами подход никак не
IS>> поможет в ситуации, когда сетевые модификации были внесены в то время,
IS>> когда ваша станция как раз занимается сравнением наборов переменных
IS>> (скажем - запустился фоновый процесс и система призадумалась на минутку,
IS>> или на другой станции запустили какую-нибудь программу рассчета, которая
IS>> изменила данные, пока ваша станция что-то сравнивала)

VM> Смею Вас заверить, что если Вы не будете блокировать запись, то Вы тоже не
VM> сможете это отследить.

VM> "Сброс буфера" (нажали кнопку "Сохранить"), автоматически предполагает
VM> попытку заблокировать запись. Т.е. перед операцией сравнения
VM> предполагается блокировка редактируемой записи.

Кем предполагается? Вами? Тогда прошу Вас ставить собеседника в известность о
своих предположениях. Ибо я лично не знаком ни с Вами, ни с написанным Вами
кодом и таких предположений делать не могу. Посему оперирую с той информацией,
которая есть. И до сих пор о блокировке перед сравнением речь не шла, а
наоборот, обсуждался вопрос о гарантировании перемещения указателя, каковое не
нужно при блокировке.

Ладно. С этим вопросом разобрались.

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

VM> [...]

IS>> Что значит "может не переместиться"??? Он никуда не переместится, пока я
IS>> этого не захочу. Еще чего не хватало - чтобы железяка за меня решала,
IS>> куда и чего ей перемещать!

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

Любое конкретное приложение строится по определенной идеологии. Каждая
идеология предполагает следования каким-то правилам и соблюдение каких-то
ограничений этой идеологии присущих. Приложений вообще без идеологии я не
встречал даже у начинающих.

VM> Если Вам вдруг понадобиться в процессе редактирования сделать некий
VM> анализ с "соседними" записями той же таблицы, Вам надо "не забыть",
VM> что в данной рабочей области делать этого ни в коем случае нельзя.

Что Вы так за меня переживаете? :) Вам в Вашем случае надо не забыть о гораздо
большем:
- не забыть возвращать указатель всякий раз, когда "вдруг понадобиться
сделать некий анализ соседних записей"
- возвращая указатель, следует иметь ввиду установку SET DELETED. При SET
DELETED ON следует использовать возврат по номеру записи, ибо LOCATE or SEEK ее
не найдут, если она была удалена другим пользователем сети. Либо специально
обрабатывать такую ситуацию.
- перемещая указатель надо не забыть о том, что на таблицу может быть
установлен SET FILTER\SET KEY и его скорее всего придется снять (если мы
перемещаем не от нефиг делать, а для чего-то нужного)
- не забыть восстановить SET FILTER\SET KEY обратно.
- если есть RELATION на подчиненную таблиц(у\ы) то надо задуматься над тем, а
стоит ли таскать их за собой "при анализе соседних записей". Скорее всего его
придется снять хотя бы для того, чтобы не качать лишние данные по сети.
- не забыть восстановить SET RELATION
- если редактируемая таблица сама является подчиненной и _на_ нее из другой
таблицы установлен SET RELATION (случается и такое), то перемещение указателя
может привести к некорректной работе этого RELATION, даже после того, как
указатель корректно вертут на прежнее место. Т.е. опять снять\восстановить.
- если "при анализе соседних записей" пришлось изменить порядок сортировки,
его придется восстановить. Если при этом не дай бог помимо структурного CDX
использовался неструктурный CDX (напр. для пользовательской сортировки), то
разбираться надо и с индексными файлами. Если при этом на таблицу был
установлен RELATION, его тоже бы надо переустановить.

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

VM> Другими словами, Вы сознательно ограничиваете себя определенным
VM> образом действий.

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

VM> Идеологией, если хотите.

Идеология, при которой указатель записи не следует перемещать в процессе ее
редактирования, очень хорошо перешла из FPD в VFP с его буферизацией записи
(buffering = 2 or 3), где смещение указателя приводит к неявному сбросу буфера.

[..]

VM> А при чем здесь _сетевые_ изменения. До сих пор речь шла об изменениях на
VM> стороне _клиента_. Сравнение значений ДО и ПОСЛЕ модификаций на стороне
VM> клиента.

[..]

VM>>> Другая цель создания "эталонного" набора переменных - это определение
VM>>> того факта, что _другой_ пользователь что-то изменил, пока первый
VM>>> что-то там вводил. Hо по этому поводу уже высказался Igor Korolyov

Если это не про сетевые изменение, тогда про что?

[..]

VM>>> В общем, если Вы симулируете в FPD режим оптимистической

VM>>> буферизации,


VM>>> то без эталонного набора переменных просто не обойтись.

IS>> Совершенно спокойно можно обойтись. В ответе Игорю Королеву я писал,
IS>> каким образом. Hо могу повторить, мне не жалко: Перед сохранением открой
IS>> еще одну копию редактируемой таблицы с другим алиасом и найди ту же
IS>> запись (при этом получишь в ней свежайшие данные) и сравнивай поля в этих
IS>> двух алиасах.

VM> И чем это _лучше_ эталонного набора переменных? Да ничем! Те же "грабли",
VM> но "вид сбоку".

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

VM> Более того, при опеределенном стечении обстоятельств,
VM> прямое чтение из таблицы может привести к некорректному результату
VM> (ну, вот "забыл" я что передергивать указатель записи нельзя)

Ну запишИте сей факт где-нибудь на видном месте. Комментарии для этого
прекрасно подходят. Или для редактирования откройте таблицу с алиасом, который
напомнит Вам об этом, когда Вы захотите в ней указатель подвигать.

VM> Иметь фиксированный "эталонный" образец для сравнения по любому надежней,

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

Собственно я это к тому, что без этих наборов переменных проще, при той же
надежности.

WBR&W, Igor Shanuk

Igor Korolyov

unread,
Jun 28, 2007, 9:43:06 AM6/28/07
to
Hi Igor!

You wrote to Vladimir Maksimov on Wed, 20 Jun 2007 02:28:00 +0400:

VM>> Вы _не_ _можете_ _гарантировать_, что данные в текущей записи
VM>> находятся в том состоянии, в котором они были ДО начала
VM>> редактирования.

IS> Вот как раз это я гарантировать могу!

В FPD возможно (хотя я не уверен насчёт работы с гридом), но в VFP уже
вряд-ли. Если поле таблицы привязано к UI контролу, то "перерисовка"
контрола - Control.Refresh() - обновит данные в курсоре (так что прямое
чтение значения поля уже покажет новые данные). Особенно весело ведёт себя
при этом грид - он может перерисовываться и без явных команд - просто в
результате действий пользователя типа кликов мышью по гриду.

IS> Я вообще в программе могу гарантировать все, что в пределах
IS> возможностей FoxPro. Для того, чтобы переместить указатель, нужно
IS> предпринять какие-то действия, а чтобы он оставался на месте - нужно
IS> просто его не трогать.

Естественно! Но ты уверен что сможешь _всегда_ отследить _все_ действия
приводящие к перемещению указателя? Те-же самые перемещения в Master таблице
при установленном Relation, перемещения в BROWSE, работу "не знающих про
запрет" процедур - например повешенных на горячие клавиши (они конечно
смогут восстановить и recno() и всё прочее, но увы не состояние буфера), и
соответственно работающих не в контексте формы... В VFP добавляются ещё и
свои особенности "нечеловеческой логики" :)

VM>> 1) Указатель записи _может_ не переместиться

IS> Что значит "может не переместиться"??? Он никуда не переместится, пока я
IS> этого не захочу. Еще чего не хватало - чтобы железяка за меня решала,
IS> куда и чего ей перемещать!

Но оно часто именно так и происходит :) В фоксе из-за его идеологии
"дружественности к чайникам" особенно. Не послать подальше кривой код, а
постараться хоть как-то его исполнить...

VM>> Hе перемещаете указатель записи, ну и не перемещайте. Дублирующий набор
VM>> переменных будет работать.

IS> Вхолостую. Ибо никаких сетевых изменений при этом он отследить не сможет
IS> из-за особенностей указанных ранее. Т.е. имеем бесполезный код.

Чтобы он "смог" отследить сетевые изменения надо об этом самому
позаботится - в частности "заставить" фокс обновить буфер текущей записи. Но
это не есть первая часть проблемы.

VM>> Меня ведь содержимое собственно записи уже не интересует.

IS> Правильно, кому она нужна, запись-то, главное - что переменные совпали!
IS> Типа - ну и что, что померла. Главное докУменты в порядке :)

То что совпали переменные никак не связано с удалением записи - в твоём
случае ты точно так-же не увидишь что запись уже удалена :) Это как раз есть
вторая часть проблемы - конфликт совместного изменения записи...

IS> Совершенно спокойно можно обойтись. В ответе Игорю Королеву я писал,
IS> каким образом. Но могу повторить, мне не жалко: Перед сохранением открой
IS> еще одну копию редактируемой таблицы с другим алиасом и найди ту же
IS> запись

Вот вот :) Мы и пришли к ИДЕЕ "2-х наборов" переменных - просто в качестве
одного из наборов используется не memvar а буфер курсора :) А так - всё с
точностью до неразличимости.

IS> (при этом получишь в ней свежайшие данные)

Это тоже кстати не так то просто - фокс весьма хитёр в плане кэширования -
тока в VFP9 добавили возможность "всегда читать с диска" - и то это надо
специально "включать" - во всех прочих случаях получим не "свежайшие"
данные - по умолчанию вплоть до 5-секундной "давности".

[Sorry, skipped]

IS> Аналогичным же образом и набор модифицированных полей можешь определить.

Да да, я и говорю - та же самая идея, но вместо memvar буфер курсора.

IS> Если оно, конечно печет.

Эт точно :) В большинстве приложений оно настолько некритично, что
специально заморачиваться и смысла нету.

--
WBR, Igor

Igor Korolyov

unread,
Jun 28, 2007, 9:43:07 AM6/28/07
to
Hi Igor!

You wrote to Igor Korolyov on Tue, 19 Jun 2007 23:45:00 +0400:

IS>>> А сравнить значения переменных непосредственно со значениями в записи
IS>>> таблицы авторам видимо не позволяет честь самурая.
IK>> Есть довольно существенная (идеологическая) разница между CURVAL() и
IK>> OLDVAL().

IS> В FPD? Разговор-то за антиквариат шел...

Нет, я имею в виду именно "идеологически" - значение поля на момент начала
редактирования (или на момент "показа" его пользователю), текущее значение в
поле ввода (чего пользователь навводил), и текущее значение на диске (чего
другие пользователи успели насохранять). Просто в VFP у этих понятий есть
такие простые "имена" :)

IK>> В частности без этого "дополнительного набора переменных"
IK>> невозможно организовать корректную оптимистическую блокировку - т.е.
IK>> просто не будет никакой возможности отследить, что пока мы занимались
IK>> созерцанием данных в форме и вдумчивой их модификацией некто "снаружи"

IK>> уже поменял эти самые данные :)

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

Это во-первых основано на идее "неизменности буфера текущей записи" а
во-вторых всё на той-же идее 2-х наборов переменных :) Просто в
прямолинейном случае это lcValue, lcOldValue и RefreshedAlias.Value а в
твоей интерпретации это lcValue, FrozenAlias.Value и RefreshedAlias.Value -
с оговоркой о необязательности последнего элемента и там и там, если мы не
следим за конфликтами совместного доступа.

IS> Это ежели припечет.

Именно так.

[Sorry, skipped]

IS> Совершенно с этим согласен. Мне кажется, что было бы больше пользы, да и
IS> логичнее, если бы в DE формы включались объекты типа cursor adapter, а
IS> не эти огрызки.

Они и включаются, правда весьма кривым (на мой взгляд) способом - т.е. мне
почему-то было заметно проще написать в коде ThisForm.oCADSome =
CreateObject("CADSome") нежели пользоваться "мастером DE" - при всём моём
уважении к его автору :)
При всём при том ещё и искажённый порядок срабатывания событий при помещении
CAD в DE - и соответственно неочевидный="вредный" код который помещает в
CAD-ы построитель для обхода этой проблемы... Нет, для меня DE уже давно
стал "ни-ни" :)

--
WBR, Igor

Igor Shanuk

unread,
Jun 28, 2007, 4:21:00 PM6/28/07
to
Hi, Igor!

28 Июня 2007г. (Четверг) Igor Korolyov писал Igor Shanuk:

> ...


VM>>> Вы _не_ _можете_ _гарантировать_, что данные в текущей записи
VM>>> находятся в том состоянии, в котором они были ДО начала
VM>>> редактирования.

IS>> Вот как раз это я гарантировать могу!

IK> В FPD возможно

Очень даже возможно.

IK> (хотя я не уверен насчёт работы с гридом),

Грид, то бишь BROWSE (в терминах FPD) работает напрямую с записью таблицы и
никакие переменные (из-за которых идет эта увлекательная дискуссия) в этом
случае не помогут эмулировать буферизацию.

IK> но в VFP уже вряд-ли.

В VFP весь этот спор не имеет смысла, т.к. во-первых незачем городить наборы
переменных для "самодельной" буферизации, а во-вторых по причине наличия
функции GetFldState(), которая без всяких наборов переменных позволяет мне
зафиксировать факт редактирования.

IK> Если поле таблицы привязано к UI контролу, то
IK> "перерисовка" контрола - Control.Refresh() - обновит данные в курсоре
IK> (так что прямое чтение значения поля уже покажет новые данные).

При включенной буферизации не показывает.

IK> Особенно весело ведёт себя
IK> при этом грид - он может перерисовываться и без явных команд - просто
IK> в результате действий пользователя типа кликов мышью по гриду.

IS>> Я вообще в программе могу гарантировать все, что в пределах
IS>> возможностей FoxPro. Для того, чтобы переместить указатель, нужно
IS>> предпринять какие-то действия, а чтобы он оставался на месте - нужно
IS>> просто его не трогать.

IK> Естественно! Hо ты уверен что сможешь _всегда_ отследить _все_ действия
IK> приводящие к перемещению указателя?

Да. Точнее, формы построены так, что особого слежения в общем-то и не нужно. У
меня, к примеру, все формы для редактирования в VFP используют строчную
оптимистическую буферизацию (для master-таблицы). И если бы указатель "гулял"
как ему хочется, то это очень быстро бы заметили, хотябы потому, что из-за
неявного сброса буфера не работала бы функция отката модификаций, остнованная
на tablerevert().

IK> Те-же самые перемещения в Master
IK> таблице при установленном Relation, перемещения в BROWSE, работу "не
IK> знающих про запрет" процедур - например повешенных на горячие клавиши (они
IK> конечно смогут восстановить и recno() и всё прочее, но увы не состояние
IK> буфера), и соответственно работающих не в контексте формы...

А процедуры эти мне что, тайно враги подбросили? Какая необходимость процедуре,
висящей на горячей клавише дергать указатель в таблице, запись которой
редактируется? До сохранения модификаций подождать нельзя? Ну, или хотя бы
предварительно спросить, что делать с имеющимися несохраненными модификациями?
И откуда эта процедура знает, что указатель нужно перемещать в алиасе
Master_Edt, с которым таблица Master открыта в форме для редактирования?

IK> В VFP
IK> добавляются ещё и свои особенности "нечеловеческой логики" :)

VM>>> 1) Указатель записи _может_ не переместиться
IS>> Что значит "может не переместиться"??? Он никуда не переместится, пока я
IS>> этого не захочу. Еще чего не хватало - чтобы железяка за меня решала,
IS>> куда и чего ей перемещать!

IK> Hо оно часто именно так и происходит :) В фоксе из-за его идеологии
IK> "дружественности к чайникам" особенно.

Ну, это проблемы чайников, которые меня волнуют не более, чем проблемы негров
волнуют шерифа из известной поговорки. :)

[..]

IS>> Совершенно спокойно можно обойтись. В ответе Игорю Королеву я писал,

IS>> каким образом. Hо могу повторить, мне не жалко: Перед сохранением открой


IS>> еще одну копию редактируемой таблицы с другим алиасом и найди ту же
IS>> запись

IK> Вот вот :) Мы и пришли к ИДЕЕ "2-х наборов" переменных - просто в качестве
IK> одного из наборов используется не memvar а буфер курсора :) А так - всё с
IK> точностью до неразличимости.

Ну, а я очем говорил? Только при использовании курсора код получается более
универсальным (ибо имена полей в алиасах одной и той же таблицы всегда
одинаковые, чего не скажешь о двух наборах переменных.) и более компактным.
Хотя таким же ненужным в большинстве случаев. :)

IK> Да да, я и говорю - та же самая идея, но вместо memvar буфер курсора.

Я об этом с самого начала говорю. :)

IS>> Если оно, конечно печет.

IK> Эт точно :) В большинстве приложений оно настолько некритично, что
IK> специально заморачиваться и смысла нету.


WBR&W, Igor Shanuk

Igor Korolyov

unread,
Jun 29, 2007, 11:12:09 AM6/29/07
to
Hi Igor!

You wrote to Igor Korolyov on Fri, 29 Jun 2007 00:21:00 +0400:

IK>> (хотя я не уверен насчёт работы с гридом),

IS> Грид, то бишь BROWSE (в терминах FPD) работает напрямую с записью
IS> таблицы и никакие переменные (из-за которых идет эта увлекательная
IS> дискуссия) в этом случае не помогут эмулировать буферизацию.

Дело не в "эмулировании" настоящей буферизации, а в том что если вдруг (мало
ли по каким причинам!) где-то твой курсор будет показан через BROWSE то и
произойдёт нежелательное обновление "текущей записи". Т.е. это лишь ещё один
из факторов про которые нужно помнить, чтобы твоя идея работала как дОлжно.

[Sorry, skipped]

IS> Да. Точнее, формы построены так, что особого слежения в общем-то и не
IS> нужно. У меня, к примеру, все формы для редактирования в VFP используют
IS> строчную оптимистическую буферизацию (для master-таблицы). И если бы
IS> указатель "гулял" как ему хочется, то это очень быстро бы заметили,
IS> хотябы потому, что из-за неявного сброса буфера не работала бы функция
IS> отката модификаций, остнованная на tablerevert().

Конечно! Поэтому я лично НИКОГДА не использую строчную буферизацию (иногда
включаю на небольшое время - например для создания временного индекса) -
даже если по логике формы там отображается только одна запись.

IS> А процедуры эти мне что, тайно враги подбросили? Какая необходимость
IS> процедуре, висящей на горячей клавише дергать указатель в таблице,
IS> запись которой редактируется?

Мало ли - например дамп "текущего состояния системы" снять... Когда ты один
программу пишешь - то конечно знаешь какая её часть что делает. А при работе
в коллективе (или при использовании чужого каркаса) это не всегда так - т.е.
ты можешь вроде как всё "правильно" написать, а оно не будет работать из-за
пересечения с "системным" кодом.

IS> До сохранения модификаций подождать нельзя? Ну, или хотя бы
IS> предварительно спросить, что делать с имеющимися несохраненными
IS> модификациями? И откуда эта процедура знает, что указатель нужно
IS> перемещать в алиасе Master_Edt, с которым таблица Master открыта в форме
IS> для редактирования?

Может она просто по тупому перебирает все рабочие области :)

[Sorry, skipped]

IS> Ну, а я очем говорил? Только при использовании курсора код получается
IS> более универсальным (ибо имена полей в алиасах одной и той же таблицы
IS> всегда одинаковые, чего не скажешь о двух наборах переменных.) и более
IS> компактным.

Дык можно и не переменные а массивы сделать :) А если пойти по твоей линии
работы с курсорами, то вместо использования особенностей обновления буферов
записи, можно самому (т.е. руками) скопировать нужную запись в "правильный"
временный курсор - уж там-то никогда и ни за что никакие изменения в
физической таблице не появятся :) Кстати тогда можно будет (при обнаружении
конфликта) в этот временный курсор скопировать и "свежее" состояние записи,
и то что пользователь ввёл - и его (курсор этот) показать пользователю для
принятия решения что делать - переписывать запись или нет.

Igor Shanuk

unread,
Jun 29, 2007, 4:38:00 PM6/29/07
to
Hi, Igor!

29 Июня 2007г. (Пятница) Igor Korolyov писал Igor Shanuk:

[..]

IK>>> (хотя я не уверен насчёт работы с гридом),
IS>> Грид, то бишь BROWSE (в терминах FPD) работает напрямую с записью
IS>> таблицы и никакие переменные (из-за которых идет эта увлекательная
IS>> дискуссия) в этом случае не помогут эмулировать буферизацию.

IK> Дело не в "эмулировании" настоящей буферизации, а в том что если вдруг
IK> (мало ли по каким причинам!) где-то твой курсор будет показан через BROWSE
IK> то и произойдёт нежелательное обновление "текущей записи".

Что значит "где-то вдруг"? Там где может произойти "вдруг", для редактирования
открывается алиас о котором "где-то" ничего не знают. Это раз. А два - это то,
что в те стародавние времена выработалась привычка при использовании BROWSE в
программе изначально отключать обновление BROWSE по SET REFRESH, и включать его
только на время активации окна BROWSE. Причем привычка эта возникла на много
раньше из-за проблем с вычисляемыми полями, использующими что-то вроде
IIF(SEEK(Id, "Vendor"), Vendor.Name, "") в выражениях. Потому как в FPD нет PDS
и SEEK() работает с только активным индексом. И если оставить окно с
обновляемым BROWSE в бекграунде, то SEEK() сработавший при его обновлении
слетит по ошибке, если в таблице Vendor будет изменен активный индекс.

IK> Т.е. это лишь ещё один из факторов про которые нужно помнить, чтобы
IK> твоя идея работала как дОлжно.

На счет факторов я уже высказывался.

IK> [Sorry, skipped]

IS>> Да. Точнее, формы построены так, что особого слежения в общем-то и не
IS>> нужно. У меня, к примеру, все формы для редактирования в VFP используют
IS>> строчную оптимистическую буферизацию (для master-таблицы). И если бы
IS>> указатель "гулял" как ему хочется, то это очень быстро бы заметили,
IS>> хотябы потому, что из-за неявного сброса буфера не работала бы функция
IS>> отката модификаций, остнованная на tablerevert().

IK> Конечно! Поэтому я лично HИКОГДА не использую строчную буферизацию

А я лично - использую. И еще человек шесть работают в том же ключе. И все
живы-здоровы. И программы функционируют как надо... :)

IK> (иногда включаю на небольшое время - например для создания временного
IK> индекса) - даже если по логике формы там отображается только одна
IK> запись.

Исключительно для самообразования: а зачем включать какую бы то ни было
буферизацию при построении временного индекса?

IS>> А процедуры эти мне что, тайно враги подбросили? Какая необходимость
IS>> процедуре, висящей на горячей клавише дергать указатель в таблице,
IS>> запись которой редактируется?

IK> Мало ли - например дамп "текущего состояния системы" снять...

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

IK> Когда ты один программу пишешь - то конечно знаешь какая её часть что
IK> делает. А при работе в коллективе (или при использовании чужого
IK> каркаса) это не всегда так

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

Обычно же в коллективе при перед началом разработки оговариваются идеология
приложения, его структура и общие подходы к реализации той или иной
функциональности. А вещи глобального характера строго регламентируются и
доводятся до всех без исключения. Что-то вроде:
"Уважаемые коллеги! По результатам обсуждения проблемы <...>, с такого-то числа
мной введена новая библиотечная функция MatNumber, переобразующая числовое
значение в строку матерной формы в именительном и родетельном падежах. Попутно
во всех рабочих областях случайным образом перемещает указатель. Курсоры с
непонравившимися алиасами будут вообще закрыты. Будьте внимательны!"

IK> - т.е. ты можешь вроде как всё "правильно"
IK> написать, а оно не будет работать из-за пересечения с "системным"
IK> кодом.

А системный код от меня тоже в секрете держат? И с чего бы это он должен
срабатывать во время редактирования?

IS>> До сохранения модификаций подождать нельзя? Hу, или хотя бы


IS>> предварительно спросить, что делать с имеющимися несохраненными
IS>> модификациями? И откуда эта процедура знает, что указатель нужно
IS>> перемещать в алиасе Master_Edt, с которым таблица Master открыта в форме
IS>> для редактирования?

IK> Может она просто по тупому перебирает все рабочие области :)

Ага. И в каждом алиасе меняет содержимое всех подходящих полей на "КИСА КУКУ",
чтобы указатель впустую не дергать. :)

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

IK> [Sorry, skipped]

IS>> Hу, а я очем говорил? Только при использовании курсора код получается


IS>> более универсальным (ибо имена полей в алиасах одной и той же таблицы
IS>> всегда одинаковые, чего не скажешь о двух наборах переменных.) и более
IS>> компактным.

IK> Дык можно и не переменные а массивы сделать :)

Седлать можно моного чего. Только я предпочитаю делать не то, что можно, а то,
без чего нельзя обойтись.

WBR&W, Igor Shanuk

Igor Korolyov

unread,
Jun 30, 2007, 1:55:06 PM6/30/07
to
Здравствуйте Igor!
Вы писали Sat, 30 Jun 2007 00:38:00 +0400 к Igor Korolyov:

[Пропущено]

IK>> Конечно! Поэтому я лично HИКОГДА не использую строчную буферизацию

IS> А я лично - использую. И еще человек шесть работают в том же ключе. И
IS> все живы-здоровы. И программы функционируют как надо... :)

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

IK>> (иногда включаю на небольшое время - например для создания временного
IK>> индекса) - даже если по логике формы там отображается только одна
IK>> запись.

IS> Исключительно для самообразования: а зачем включать какую бы то ни было
IS> буферизацию при построении временного индекса?

Имеется в виду переключать с 5-й в 3-ю на время. А как известно
представления не могут быть "в никакой" буферизации.

[Пропущено]

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

Если бы это ещё и помогало... Я порой просто поражаюсь КАК коллеги
используют написанные мной классы - я бы и не додумался наверное о таких
подходах :)
А убеждать о том что на самом деле то надо было делать по иному - особенно в
условиях постоянного прессинга со стороны сроков - сам понимаешь это
нереально. Работает хоть как-то и слава богу :)

[Пропущено]

IS> А системный код от меня тоже в секрете держат?

А ты всегда тщательно изучаешь чужой код? Я по возможности изучаю, но
конечно времени не хватает - а главное начальство очень этим недовольно - на
кой им нужен "всё знающий" человек, если доход приносит лишь "много
лабающий" - пускай даже на его код нельзя смотреть без того чтобы волосы не
голове от ужаса не шевелились :)

IS> И с чего бы это он должен срабатывать во время редактирования?

Системный код на то и системный, чтобы его пользователь не задумывался даже
о том когда он срабатывает и что делает :) А редактирование процесс ой какой
непростой и обычно весьма длительный. В FPD конечно попроще - там всё-же ход
исполнения программы более линейный, а вот в современных языках просто
невозможно предсказать в какой момент времени какой блок кода будет
работать - потому и пишется он так, чтобы быть по максимуму независимым и не
менять "глобальные переменные" - а если и менять, то очень аккуратно.

[Пропущено]

--
WBR, Игорь


Igor Shanuk

unread,
Jun 30, 2007, 5:22:00 PM6/30/07
to
Hi, Igor!

30 Июня 2007г. (Суббота) Igor Korolyov писал Igor Shanuk:

[..]

IK>>> Конечно! Поэтому я лично HИКОГДА не использую строчную буферизацию


IS>> А я лично - использую. И еще человек шесть работают в том же ключе. И
IS>> все живы-здоровы. И программы функционируют как надо... :)

IK> В этом конечно не может быть никаких сомнений. Просто в своё время я решил
IK> что поддерживать в каркасе работу с обоими типами буферизации, а потом ещё
IK> и бесконечно долго объяснять всем какую же буферизацию в каком
IK> случае использовать :)

Кому объяснять? Пользователю все буферизации до лампочки. Он про них и знать-то
ничего не должен. Стало быть - программисты понять не могут???

IK>>> (иногда включаю на небольшое время - например для создания

IK>>> временного


IK>>> индекса) - даже если по логике формы там отображается только одна
IK>>> запись.
IS>> Исключительно для самообразования: а зачем включать какую бы то ни было
IS>> буферизацию при построении временного индекса?

IK> Имеется в виду переключать с 5-й в 3-ю на время. А как известно
IK> представления не могут быть "в никакой" буферизации.

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

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

IK> Если бы это ещё и помогало... Я порой просто поражаюсь КАК коллеги
IK> используют написанные мной классы - я бы и не додумался наверное о таких
IK> подходах :)

Значит мне с коллегами повезло. :)

[..]

IS>> А системный код от меня тоже в секрете держат?

IK> А ты всегда тщательно изучаешь чужой код?

Да, конечно. Хотя бы, чтобы выяснить есть ли аналоги того, что требуется мне
реализовать в чужой программе. Например, если от меня требуют сделать
справочник чего-то, то будет весьма полезно проанализировать уже имеющиеся
справочники на предмет подходов, используемых в них, а так же имеющихся
стандартных процедур общего пользования, классов, взаимодействия с остальными
частями приложения и т.п. Чтобы велосипед не изобретать по второму разу. Ибо
если заказчика до сих пор устраивала существующая реализация, то не вижу смысла
городить что-то другое. Посему все свои передовые идеи, прогрессивные взгляды и
новейшие подходы засовываю куда подальше, и в общем следую той идеологии,
которая есть. Это в простейшем случае.
Если же требуют того, аналогов чего в этой программе нет, то объем
анализируемого возрастает весьма существенно, но без этого частые выезды к
заказчику для устранения недоработок, считай, гарантированы.

IK> Я по возможности изучаю, но конечно времени не хватает - а главное
IK> начальство очень этим недовольно - на кой им нужен "всё знающий"
IK> человек, если доход приносит лишь "много лабающий" - пускай даже на
IK> его код нельзя смотреть без того чтобы волосы не голове от ужаса не
IK> шевелились :)

Увы. Это вопрос организационный. Но особого беспокойства он у меня не вызывает,
ибо, этот "лабух" потратит на переделки, реализацию того, что уже сделано в
другом месте и отладку времени столько же (если не больше), сколько я потрачу
на анализ и создание более менее не то, чтобы изящного, но простого и понятного
кода. Но начальству (такому) я не признаюсь, что от 30 до 70 %% трудозатрат
пришлось на анализ. Зачем нервировать его лишний раз. Пусть думает, что все это
время я усердно кнопки жал. :)

IS>> И с чего бы это он должен срабатывать во время редактирования?

IK> Системный код на то и системный, чтобы его пользователь не задумывался
IK> даже о том когда он срабатывает и что делает :)

А пользователь и не задумывается. Пользователя вообще нужно беречь - ему и так
своей работы хватает, чтобы еще задумываться о внутреннем устройстве программы.
Он нажимает кнопку и получает сообщение:
"Внимание!
Сейчас будет выполнен тотальный ататуй с перерассчетом всего и везде за
последние двести лет."
Если пользователь подтвердит свои намерения, то получит другое сообщение:
"Форма <...> содержит несохраненные модификации данных. Сохранить?"
"Форма <...> (Да\Нет\Отставить)

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

IK> А редактирование процесс ой какой непростой и обычно весьма
IK> длительный. В FPD конечно попроще - там
IK> всё-же ход исполнения программы более линейный, а вот в современных
IK> языках
IK> просто невозможно предсказать в какой момент времени какой блок кода будет
IK> работать - потому и пишется он так, чтобы быть по максимуму независимым и
IK> не менять "глобальные переменные" - а если и менять, то очень аккуратно.

К "системному коду" это тоже отностся.

WBR&W, Igor Shanuk

Vladimir Maksimov

unread,
Jul 1, 2007, 10:13:21 AM7/1/07
to
Thu Jun 28 2007 01:37, Igor Shanuk wrote to Vladimir Maksimov:

IS> Кем предполагается? Вами? Тогда прошу Вас ставить собеседника в
IS> известность о своих предположениях. Ибо я лично не знаком ни с Вами, ни с
IS> написанным Вами кодом и таких предположений делать не могу. Посему
IS> оперирую с той информацией, которая есть. И до сих пор о блокировке перед
IS> сравнением речь не шла, а наоборот, обсуждался вопрос о гарантировании
IS> перемещения указателя, каковое не нужно при блокировке.

IS> Ладно. С этим вопросом разобрались.

В общем, как и следовало ожидать, спор дошел до той точки, когда уместно
спросить: "А о чем собственно спорим?".

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

Просто, каждый рассматривает предложенные решения с позиции своей собственной
идеологии решения подобных задач.

Поэтому, попробую описать ту задачу и идеологию ее решения, о которой идет
спор.

====================
Задача заключаеся в редактировании данных в многопользовательском приложении в
среде FoxPro for DOS. Предполагается, что одну и ту же запись одновременно
могут редактировать несколько пользователей.

Другими словами, рассматривается симуляция в FPD того режима, которой в Visual
FoxPro получил название "оптимистическая буферизация" (3 или 5).

В момент нажатия кнопки "Сохранить" необходимо получить ответ на следующие
вопросы:

1) Изменил ли _данный_ пользователь хоть что-нибудь
2) Изменил ли _другой_ пользователь что-нибудь в тех же данных, которые
изменял _данный_ пользователь
3) Сопоставив изменения определенные в (1) и (2) в _некоторых_ случаях можно
принять решение перезаписать изменения _данного_ пользователя поверх изменений
сделанных _другим_ пользователем.

Чтобы получить ответы на эти вопросы, необходимо знать следующие состояния
данных:

-) Значение данных, которые получились после изменения _даным_ пользователем
-) Значение данных, которые были до того, как _данный_ пользователь начал их
изменять
-) Значения данных, которые есть в настоящий момент в сети (возможные
изменения _другим_ пользователем)

======================

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

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

Вы же предлагаете не создавать такого эталонного набора данных исходя из
предположения, что _при_ _определенных_ _условиях_ эти значения будут
содержаться в текущей записи таблицы.

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

Другими словами, Вы рассматриваете не программное, а _организационное_ решение
задачи. Всех оповестить, за каждым присмотреть, самому не забыть и т.д. и т.п.

Лично я не могу дать гарантий, что прослежу за всем и вся. И исхожу из
предположения, что чем более независимым от других модулей проекта будет мой
собственный модуль - тем лучше. Яаное создание эталонного набора данных перед
началом редактирования дает мне такую независимость.

Igor Shanuk

unread,
Jul 1, 2007, 6:51:00 PM7/1/07
to
Hi, Vladimir!

01 Июля 2007г. (Воскресенье) Vladimir Maksimov писал Igor Shanuk:

[..]

Согласен, что дискуссия несколько отдалилась от темы.

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

VM> Авторы книги (и я в этом вопросе с ними согласен) предлагают получить эти
VM> данные сделав явным образом копию данных перед началом редактирования.
VM> Способ физического создания этой копии - набор эталонных переменных,
VM> массив, курсор, выборка во временную таблицу - принципиального значения в
VM> данном случае не имеет. Важен сам факт _явного_ создания такого эталонного
VM> набора данных.

VM> Вы же предлагаете не создавать такого эталонного набора данных исходя из
VM> предположения, что _при_ _определенных_ _условиях_ эти значения будут
VM> содержаться в текущей записи таблицы.

VM> Ваша аргументация сводится к тому, что Вы, лично Вы, даете гарантию, что
VM> те условия, при которых в текущей записи сохраняться "эталонные" значения
VM> будут всегда соблюдаться как Вами,

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

VM> так и другими программистами, работающими с этим же проектом.

А какие с этим проблемы? Если другие программисты работают над другими модулями
того же проекта, то они практически никак не могут повлиять на внутреннюю
структуру моего модуля, ибо "ничего о ней не знают". Если над моим модулем
параллельно работает еще кто-то, то подходы к реализации и внутренняя структура
оговариваются заранее, и в процессе работы происходят дополнительные
согласования. В противном случае это будет не работа, а спектакль по мотивам
известного произведения "Лебедь, Рак и Щука". Если же некто впоследствии будет
дорабатывать мой модуль, то у этого некта есть глаза, голова и достаточно
профессионализма, чтобы проанализировать существующий код (или хотябы прочитать
комментарий) перед его модификацией. От некомпетентного вмешательства никто не
застрахован, но я не слышал о том, чтобы решение отвергалось на основании того,
что его не поймут грядущие поколения.

И при Вашем подходе так же нет гарантий от модификации кода кем-нибудь не
слишком пряморуким. Поставит сгоряча, не разобравшись, какой-нибудь фильтр на
редактируемую таблицу, и не заметит ничего, ибо все SEEK & LOCATE останутся
вполне работоспособными.

VM> Другими словами, Вы рассматриваете не программное, а _организационное_
VM> решение задачи. Всех оповестить, за каждым присмотреть, самому не забыть и
VM> т.д. и т.п.

Вы пугаете сами себя, чтобы оправдать приверженность к своему подходу. :)

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

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

VM> Яаное создание эталонного набора данных перед началом редактирования
VM> дает мне такую независимость.

Я уже говорил: Если Вы твердо уверены в необходимости явного создания эталона,
то вместо создания набора переменных можно открыть еще один алиас, единственная
цель которого - сохранить значения до редактирования. И в этом случае, как и в
приведенном выше, внешние процедуры ничего об этом алиасе не знают.

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

WBR&W, Igor Shanuk

Victor Radchenko

unread,
Jul 2, 2007, 4:13:24 AM7/2/07
to
Здpавствуй, Igor !

VM>> Вы же пpедлагаете не создавать такого эталонного набоpа данных
VM>> исходя из пpедположения, что _пpи_ _опpеделенных_ _условиях_ эти
VM>> значения будут содеpжаться в текущей записи таблицы.

Мысль гениальная, но я б так делать не стал.

IS> Hу Вы же даете гаpантию, что указатель коppектно веpнется к
IS> pедактиpуемой записи, и окpужение будет коppектно восстановлено.

IS> А чем я хуже?

;)

А можно вопpос по VFP ?

Как опpеделить что READ EVENTS уже наступил ?
(без пеpеменных или свойств-флагов)

Типа что написать в UDF : IF EventsProcessingStarted() ...

IS> Вы пугаете сами себя, чтобы опpавдать пpивеpженность к своему подходу.
IS> :)

;)))

C уважением, Victor.

Igor Korolyov

unread,
Jul 2, 2007, 5:43:39 AM7/2/07
to
Hi Victor!
You wrote to Igor Shanuk on Mon, 02 Jul 2007 12:13:24 +0400:

[Sorry, skipped]

VR> Как опpеделить что READ EVENTS уже наступил ?
VR> (без пеpеменных или свойств-флагов)

VR> Типа что написать в UDF : IF EventsProcessingStarted() ...

А зачем это нужно? Может быть решение будет совсем "с другой" стороны :)
Ведь например при запуска из IDE мы по сути имеем невидимый и неявный READ
EVENTS...

Но а если тупо, в лоб - ASTACKINFO() и анализируй есть ли в стеке строчка с
READ EVENTS (только не забудь что надо по номеру строки работать - исходника
в рантайме нету, да и debug info должно быть включено иначе не получится).

--
WBR, Igor

Igor Korolyov

unread,
Jul 2, 2007, 5:48:10 AM7/2/07
to
Hi Igor!

You wrote to Igor Korolyov on Sun, 01 Jul 2007 01:22:00 +0400:

[Sorry, skipped]

IS> Кому объяснять? Пользователю все буферизации до лампочки. Он про них и
IS> знать-то ничего не должен. Стало быть - программисты понять не могут???

Именно они родимые :) "Прикладники".

IK>> Если бы это ещё и помогало... Я порой просто поражаюсь КАК коллеги
IK>> используют написанные мной классы - я бы и не додумался наверное о

IK>> таких подходах :)

IS> Значит мне с коллегами повезло. :)

Может быть и так, а может быть их просто держат в ежовых рукавицах (уж не ты
ли этим занимаешься :) ) - типа шаг вправо - шаг влево - попытка к бегству
:) Это с одной стороны неплохо, а с другой отнимает очень уж много времени.
Зато нету в программах полного бардака и в принципе понять "чужой" код
значительно проще... Ибо идеологически они все одинаковые.

IS> Да, конечно. Хотя бы, чтобы выяснить есть ли аналоги того, что требуется
IS> мне реализовать в чужой программе. Например, если от меня требуют
IS> сделать справочник чего-то, то будет весьма полезно проанализировать уже
IS> имеющиеся справочники на предмет подходов, используемых в них,

С точки зрения предметной области - конечно. С точки зрения софта - это
очень сложно, ибо сколько программ - столько и подходов. Где то всё в гриде
правится, где то в отдельных формах, а грид RO... А уж сколько подходов к
размещению служебных кнопок (навигация, поиск, сохранение/отмена и т.п.) и
даже их количеству :)

IS> Ибо если заказчика до сих пор устраивала
IS> существующая реализация, то не вижу смысла городить что-то другое.

А какой тогда смысл вообще софт менять? "Некрасивый интерфейс"? IMHO если уж
потребовалось переписывать - то надо и перепроектировать - с учётом конечно
старого, но и с учётом ошибок/неудобств в этом "старом" имеющихся. А если ты
ещё и автор этого "старого" - тогда тем более - опыт уже накоплен, можно
улучшать :)

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

Не согласен - как можно при разработке VFP проги следовать идеологии FPD
проги? Или при разработке C# следовать идеологии VFP - это порочный путь и
ничего хорошего не сулит. Или ты про "идеологию работы пользователя"
говоришь (как-то оно там по умному называется... типа моторика...)?

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

Аналогов иногда и нету вовсе. А если и есть, то попробуй потом убеди
заказчика (не пользователя) что твой продукт лучше - возьмём к примеру MS
Project - неплохой инструмент планирования, но сколько крови попортили
доказывая что в "голом" виде он не годится для прикладной задачи, а
"дописывание модулей" - тоже не самый эффективный путь зачастую.

[Sorry, skipped]

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

В общем случае да, но "готовый продукт" он предоставит в разы быстрее! И
какое начальству дело, что потом потребуется целый штат "сопровожденцев" и
масса времени на переделку (а обычно просто на затыкание постоянно
возникающих дыр) - если:
1) За сопровождение платят денежку (а если программа не нуждается в
сопровождении то соответственно не платят :) )
2) Результат можно _продать_ _сразу_ - а потом ещё и порубать немного
капусты на доработках - ведь всегда можно убедить заказчика что "вот это" -
новая функция, а "вон то" ему и не нужно вовсе.

[Sorry, skipped]

IK>> Системный код на то и системный, чтобы его пользователь не задумывался
IK>> даже о том когда он срабатывает и что делает :)

IS> А пользователь и не задумывается.

Опять таки тут я имею в виду "Прикладника" - он же по сути есть
"пользователь" средств разработки и системных компонент (разного уровня - он
встроенных в среду до написанных его же коллегой).

IS> Во всяком случае каждому уважающему себя "системному коду" (особенно
IS> лазающему по чужим курсорам) не мешало бы проверить предварительно
IS> состояние открытых форм, ибо он тоже не в курсе, как его деятельность
IS> скажется на них.

Да, конечно. Потому он обычно весьма плохо читаемый и содержит кучу
"ненужных" проверок и защитных приёмов...

IK>> будет работать - потому и пишется он так, чтобы быть по максимуму
IK>> независимым и не менять "глобальные переменные" - а если и менять, то
IK>> очень аккуратно.

IS> К "системному коду" это тоже отностся.

Я бы сказал что к нему это относится более всего :)

--
WBR, Igor

Vladimir Maksimov

unread,
Jul 2, 2007, 11:29:24 AM7/2/07
to
Mon Jul 02 2007 03:51, Igor Shanuk wrote to Vladimir Maksimov:

IS> Hi, Vladimir!

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

VM>> значения будут всегда соблюдаться как Вами,

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

Тем, что Ваши гарантии основаны на организационном, а не программном решении.

VM>> так и другими программистами, работающими с этим же проектом.

IS> А какие с этим проблемы? [...]

Судя по Вашим словам, Вам крупно повезло с коллегами или же Вы их держите в
ежовых рукавицах. Доработка чужого модуля - это отдельная песня. Тут можно
сказать много слов. Hо, в чем я вижу проблему при Вашем подходе.

Вы делаете необходимую настройку (позиционируетесь на нужную запись) в одном
месте (при открытии формы), а используете это позиционирование в другом (при
нажатии кнопки "Сохранить"). Между этими двумя событиями нет прямой связи.
Значит, между ними может быть вставлено много чего и нет никакой гарантии, что
другой программист не передернет указатель записи.

Да, конечно, Вы опять скажете насчет "согласовать", "предупредить",
"объяснить"... Hо ведь это именно что _организационное_, а не программное
решение. Сам по себе код никак, никоим образом не дает никакой подсказки, что
указатель записи трогать нельзя.

Комментарии и описание? Если Вы их пишете - честь Вам и хвала. Я тоже пишу. Hо
значительно больше программистов этим не заморачиваются. Работает? Чего еще
надо? Из кода же все видно! Собственно, комментарии и описание - это тоже
скорее организационное, чем программное решение.

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

IS> И при Вашем подходе так же нет гарантий от модификации кода кем-нибудь не
IS> слишком пряморуким. Поставит сгоряча, не разобравшись, какой-нибудь
IS> фильтр на редактируемую таблицу, и не заметит ничего, ибо все SEEK &
IS> LOCATE останутся вполне работоспособными.

Да, разумеется. Только даже если использвать SEEK и LOCATE это все будет в
коде сохранения. Проблемы где? При сохранении? Значит, смотрим код сохранения
и видим команды SEEK и LOCATE, которые почему-то не находят нужную запись.
Смотрим почему и находим причину.

А что у Вас? Hепредсказуемым образом кнопка сохранить то работает, то не
работает. Или работает непонятно как. Ведь передергивание указателя записи
может обновить, но может и не обновить содержимое. Это если кто-то "не слишком
пряморукий" что-то там модифицирует. И как отлавливать такую ошибку?

Кстати, команда GO осуществляет безусловный переход вне зависимости от
фильтров и ограничений. Hо, в данном случае, это не принципально. Так, к
слову.

VM>> Явное создание эталонного набора данных перед началом редактирования

VM>> дает мне такую независимость.

IS> Я уже говорил: Если Вы твердо уверены в необходимости явного создания
IS> эталона, то вместо создания набора переменных можно открыть еще один
IS> алиас, единственная цель которого - сохранить значения до редактирования.

Разумеется можно! Я же в моей интерпретации постановки задачи указал, что
физический способ создания этого эталонного набора данных в данном споре
принципиального значения не имеет. Для меня принципиально важен сам факт его
создания. А уже каким именно способом - переменные памяти, массивы, курсор,
временная таблица - это уже вопрос личных предпочтений.

Хотя, именно еще один алиас (в смысле USE ... AGAIN) я бы делать не стал,
поскольку это все то же самое, но "вид сбоку". Это не есть _независимый_
набор. Он опять оказывается чувствителен к перемещению указателя записи.

Victor Radchenko

unread,
Jul 3, 2007, 12:56:51 AM7/3/07
to
Здpавствуй, Igor !

VR>> Как опpеделить что READ EVENTS уже наступил ?
VR>> (без пеpеменных или свойств-флагов)

IK> А зачем это нужно?
Hапpимеp, глобальный обpаботчик ошибок с 2-мя ветками: CLEAR EVENTS и THROW

IK> Может быть pешение будет совсем "с дpугой" стоpоны
Да нет, видимо, пpямого (безфлагового) pешения :(
Хотя стpанно. Что стоило фокпpотиму добавить еще одну функцию?
Впpочем в VFP и так много хоpошо задуманных, но не доведенных до ума вещей.
Флейм по поводу этого высказывания пpошу не начинать ;)

IK> Hо а если тупо, в лоб - ASTACKINFO() и анализиpуй есть ли в стеке
IK> стpочка с READ EVENTS (только не забудь что надо по номеpу стpоки
IK> pаботать - исходника в pантайме нету, да и debug info должно быть
IK> включено иначе не получится).

C уважением, Victor.

Alexandr Tananaev

unread,
Jul 3, 2007, 4:43:48 AM7/3/07
to
Добpый день, Vladimir!
01 июля 07 19:13 Vladimir Maksimov -> Igor Shanuk

VM> В общем, как и следовало ожидать, споp дошел до той точки, когда уместно
VM> спpосить: "А о чем собственно споpим?".

А тепеpь, "не споpа pади, а пpояснения для" хотел бы для себя уяснить
поpядок изменения значения данных в записи для VFP9.
"В голове моей опилки" (с) Винни_Пух.

Дело в том, что у меня ключевое поле "номеp заказа" (он же номеp накладной
и пp. бух документы) фоpмиpуется в зависимости от содеpжания заказа.
В одной базе тpи пpедпpинимателя ведут общий бизнес. Hо, чтобы как-то
pавномеpно pаспpеделить поступление сумм на счета договоpились одни виды
услуг и товаpов заполнять на одного ИП (босса), дpугие - на дpугого.
Поэтому меня больше волнует вопpос не того, что дpугой пользователь пеpепишет
его данные по сети, а чтобы данные этого же пользователя не записались на
сеpвеp pаньше, чем будет сфоpмиpован полный заказ и в опpеделенной пpоцедуpе
будет выяснен код босса, на чье имя офоpмлять документы...
Вот такая постановка задачи.
В ДОСе я весь заказ фоpмиpую в пеpеменных памяти и во вpеменной таблице,
и только потом по команде Save сбpасываю его на сеpвеp.
Вопpосы конфликтов юзеpов пока не интеpесуют. Hад одним заказом pаботает один.

Пусть пользователь pаботает в сети один, его данные никто не пеpепишет.
Имеем:

CurVal() - данные на сеpвеpе (?) или уже на локальной машине?
OldVal() - данные на локальной машине.
ThisTextBox.Value - значение пеpеменной в поле ввода на фоpме.

В начале (пеpед pедактиpованием) они одинаковые.

Затем пользователь с клавиатуpы изменил значение пеpеменной в текстовом поле.
Вопpос 1 - когда (и какими командами) это значение пеpейдёт из
This.Value в OldVal? По LosFocus?

Вопpос 2 - до каких поp (пpи одном юзеpе в сети!)
CurVal() будет pавно OldVal()

VM> Весь споp кpутится вокpуг того, каким обpазом получить значения данных,
VM> котоpые были до того, как _данный_ пользователь начал их изменять.

В VFP их можно получить функцией CurVal(). (?)
Вопpос, это значение получается дополнительным запpосом на сеpвеp?
В любой последующий момент после pедактиpования?

Или VFP сpазу создает два набоpа - CurVal и OldVal, чтобы опpеделить,
менял ли ДАHHЫЙ пользователь на своей машине данные?
Именно в том же духе, как это описано в книжке для FPD?

Спасибо.

Всего добpого! ТАH, г. Ставpополь.

Igor Korolyov

unread,
Jul 3, 2007, 8:16:50 AM7/3/07
to
Здравствуйте Alexandr!
Вы писали Tue, 03 Jul 2007 12:43:48 +0400 к Vladimir Maksimov:

AT> А тепеpь, "не споpа pади, а пpояснения для" хотел бы для себя уяснить
AT> поpядок изменения значения данных в записи для VFP9.
AT> "В голове моей опилки" (с) Винни_Пух.

AT> Дело в том, что у меня ключевое поле "номеp заказа" (он же номеp
AT> накладной и пp. бух документы) фоpмиpуется в зависимости от содеpжания
AT> заказа.

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

AT> В одной базе тpи пpедпpинимателя ведут общий бизнес. Hо, чтобы как-то
AT> pавномеpно pаспpеделить поступление сумм на счета договоpились одни виды
AT> услуг и товаpов заполнять на одного ИП (босса), дpугие - на дpугого.

Мошенничество панимаэш :)
Кстати не знаю как у вас, а у нас никак нельзя заполнять на ИП те виды
деятельности которые не были прописаны в его регистрационных документах.

AT> Поэтому меня больше волнует вопpос не того, что дpугой пользователь
AT> пеpепишет его данные по сети, а чтобы данные этого же пользователя не
AT> записались на сеpвеp pаньше, чем будет сфоpмиpован полный заказ и в
AT> опpеделенной пpоцедуpе будет выяснен код босса, на чье имя офоpмлять
AT> документы... Вот такая постановка задачи.

Для этого вообще-то существуют транзакции.

AT> В ДОСе я весь заказ фоpмиpую в пеpеменных памяти и во вpеменной таблице,
AT> и только потом по команде Save сбpасываю его на сеpвеp.

Курсор в 5-м режиме буферизации это по сути и есть "временная таблица" -
пока ты явно не скажешь слить данные (TableUpdate) - они нигде кроме как в
данном курсоре не будут видны.

AT> Вопpосы конфликтов юзеpов пока не интеpесуют. Hад одним заказом pаботает
AT> один.

И всё-же почитай про транзакции - если имеется сложная сущность (т.е.
состоящая более чем из "одной записи") - то при работе с ней крайне важно
использовать транзакцию - иначе получишь "наполовину сохранённый" заказ.

AT> Пусть пользователь pаботает в сети один, его данные никто не пеpепишет.
AT> Имеем:

AT> CurVal() - данные на сеpвеpе (?) или уже на локальной машине?

Это не имеет принципиального значения - это просто "сохранённые" данные -
что сейчас в таблице находится. С поправкой на интервалы обновления
фоксового буфера, буфера файлов ОС и т.п.

AT> OldVal() - данные на локальной машине.

Это буфер, который создаёт (автоматически) фокс при внесении изменений в
запись. Т.е. только ты начал чего-то там вводить - фокс тут-же запомнил что
было в записи до начала редактирования.

AT> ThisTextBox.Value - значение пеpеменной в поле ввода на фоpме.

Правильнее говорить про MyAlias.MyField - данные видимые в курсоре. А уж
привязано поле курсора к элементу управления или нет - это вопрос не первый.
Более того в общем случае даже если поле привязано к контролу, то его Value
вовсе не всегда соответствует тому что находится в поле! Например пока ты
вводишь данные в текстбокс - они не переносятся автоматом в поле - только
когда ты выходишь из текстбокса происходит реальный Replace... А если ты
нажал Esc - то произойдёт возврат к начальному состоянию - при этом никакая
буферизация в курсоре не требуется - это работает буфер самого контрола.
Именно поэтому и надо предпринимать специальные усилия, чтобы "протолкнуть"
данные из элементов управления в поля курсора (например принудительно
перевести фокус на другой объект) - если некоторое "действие" вызывается при
помощи меню или тулбара, и оно требует чтобы ввод в контрол был завершён...

AT> В начале (пеpед pедактиpованием) они одинаковые.

В начале вообще "не существует" OldVal! Оно появляется при начале
редактирования. А вот CurVal, как и написано в документации, "читает данные
с диска" - т.е. если извне произошло изменение записи, то CurVal это
"увидит", тогда как прямое обращение MyAlias.MyField НЕ увидит. Чтобы и оно
"увидело" надо предпринимать дополнительные усилия - например дёргать
указатель записи. При этом конечно если в поле находятся "изменённые но не
сохранённые" данные, то мы ничего "нового" и не увидим - это логично -
несохранённые данные нельзя просто так "затереть" свежими данными из
таблицы. Только явный TableRevert() это может сделать.

AT> Затем пользователь с клавиатуpы изменил значение пеpеменной в текстовом
AT> поле. Вопpос 1 - когда (и какими командами) это значение пеpейдёт из
AT> This.Value в OldVal? По LosFocus?

по LostFocus значение "перейдёт" в MyAlias.MyField (конечно если контрол
привязан к этому полю). А вот OldVal в этот момент "запомнит" старое, т.е.
начальное значение поля. Равно как и при Replace произойдёт то-же самое -
новое значение попадёт в MyAlias.MyField, а старое запомнится в OldVal.

AT> Вопpос 2 - до каких поp (пpи одном юзеpе в сети!)
AT> CurVal() будет pавно OldVal()

При отсутствии "внешних" изменений - всегда.

VM>> Весь споp кpутится вокpуг того, каким обpазом получить значения данных,
VM>> котоpые были до того, как _данный_ пользователь начал их изменять.

AT> В VFP их можно получить функцией CurVal(). (?)

Нет - OldVal. Смотри по названию - это "старые данные".

AT> Вопpос, это значение получается дополнительным запpосом на сеpвеp?
AT> В любой последующий момент после pедактиpования?

Нет. Дополнительный "запрос" делает CurVal() - чтобы получить "свежие"
данные.

AT> Или VFP сpазу создает два набоpа - CurVal и OldVal, чтобы опpеделить,
AT> менял ли ДАHHЫЙ пользователь на своей машине данные?

VFP создаёт OldVal в момент внесения изменений в любое поле записи. Т.к. это
сама исполняющая среда, то она прекрасно видит КОГДА пользователь меняет
данные и меняет ли он их вообще. И смысл OldVal не в том чтобы понять были
ли изменения (это гораздо лучше видно по GetFldState), а в том чтобы
отловить конфликт совместного изменения. Т.е. грубо говоря сравнив OldVal и
CurVal выяснить что "снаружи" произошло изменение.

AT> Именно в том же духе, как это описано в книжке для FPD?

Не знаю, не читал :)

--
WBR, Игорь


Igor Korolyov

unread,
Jul 3, 2007, 8:16:50 AM7/3/07
to
Здравствуйте Victor!
Вы писали Tue, 03 Jul 2007 08:56:51 +0400 к Igor Korolyov:

IK>> А зачем это нужно?

VR> Hапpимеp, глобальный обpаботчик ошибок с 2-мя ветками: CLEAR EVENTS и
VR> THROW

Не понял - если у тебя "вокруг" READ EVENTS блок try ... catch - то как-бы и
не надо ничего определять - и так ясно что мы "там где надо". Или он где-то
вовне подцеплен - но тогда я не понимаю логики работы такой схемы :( Можно
чуть подробнее про саму схему (где что подключается и как должна идти ошибка
по цепи обработчиков).
Кстати если в рантайме выкинуть исключение в коде для которого нету внешнего
try ... catch то программа просто закроется (т.е. это чем-то похоже на
CANCEL).

[Пропущено]

--
WBR, Игорь


Igor Shanuk

unread,
Jul 4, 2007, 3:18:00 PM7/4/07
to
Hi, Igor!

02 Июля 2007г. (Понедельник) Igor Korolyov писал Igor Shanuk:

> ...


IS>> Кому объяснять? Пользователю все буферизации до лампочки. Он про них и
IS>> знать-то ничего не должен. Стало быть - программисты понять не могут???

IK> Именно они родимые :) "Прикладники".

Кошмар.

IK>>> Если бы это ещё и помогало... Я порой просто поражаюсь КАК коллеги
IK>>> используют написанные мной классы - я бы и не додумался наверное о
IK>>> таких подходах :)

IS>> Значит мне с коллегами повезло. :)

IK> Может быть и так, а может быть их просто держат в ежовых рукавицах (уж не
IK> ты ли этим занимаешься :) )

Нет, не я. :)

IK> - типа шаг вправо - шаг влево - попытка к
IK> бегству :)

Ну почему же? Аргументированные изменения только приветствуются.

IK> Это с одной стороны неплохо, а с другой отнимает очень уж
IK> много времени. Зато нету в программах полного бардака и в принципе
IK> понять "чужой" код значительно проще... Ибо идеологически они все
IK> одинаковые.

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

IS>> Да, конечно. Хотя бы, чтобы выяснить есть ли аналоги того, что требуется

IS>> мне реализовать в чужой программе. Hапример, если от меня требуют


IS>> сделать справочник чего-то, то будет весьма полезно проанализировать уже
IS>> имеющиеся справочники на предмет подходов, используемых в них,

IK> С точки зрения предметной области - конечно. С точки зрения софта - это
IK> очень сложно, ибо сколько программ - столько и подходов.

На самом деле подходов не такое уж большое количество из-за конечных
возможностей FoxPro. Со временем просто начинаешь их узнавать сходу, или
раскладывать на комбинации уже знакомых. Иногда можно даже предположить, какую
книгу по FoxPro автор программы любит читать. :) Что-то действительно
оригинальное попадается очень редко.

IK> Где то всё в
IK> гриде правится, где то в отдельных формах, а грид RO... А уж сколько
IK> подходов к размещению служебных кнопок (навигация, поиск,
IK> сохранение/отмена и т.п.) и даже их количеству :)

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

Я уже приводил пример - добавить новый справочник в существующее и вполне
успешно работающее приложение.
Собственно при этом надо выяснить следующие вещи (навскидку):
1. Однодокументный или многодокументный интерфейс у приложения
2. Какие глобальные настройки среды выполняются при запуске, и другие нюансы
глобального значения.
3. Как осуществляется запуск аналогичных справочников.
4. Как получить доступ к таблицам БД, есть ли спец. процедуры для их открытия и
т.д.
5. Какие подходы применяется при добавлении, редактировании, удалении,
сохранении и откате модификаций.
6. Как обрабатываются конфликты при совместном доступе к данным.
7. Как проверяется корректность введеных значений.
8. Общий стиль интерфейса аналогичных справочников.

Честно говоря, я слабо представляю, как без анализа всего вышеперечисленного
можно вообще создать что-либо работоспособное.

IS>> Ибо если заказчика до сих пор устраивала
IS>> существующая реализация, то не вижу смысла городить что-то другое.

IK> А какой тогда смысл вообще софт менять?

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

IK> "Hекрасивый интерфейс"?

Некрасивых интерфейсов не бывает. Есть неудобные интерфейсы. :)

IK> IMHO если уж потребовалось переписывать - то надо и перепроектировать
IK> - с учётом конечно старого,

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

Ну, конечно, если пользователь скажет - Мне больно смотреть, как вы маетесь,
поддерживая этот старинный и запутанный код, оставшийся в наследство от
программируемых калькуляторов. Сколько хотите денег и времени, чтобы переписать
все по-современному - то какой разоговор? :)

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

IK> но и с учётом ошибок/неудобств в этом "старом" имеющихся.
IK> А если ты ещё и автор этого "старого" - тогда тем более - опыт уже
IK> накоплен, можно улучшать :)

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

IK> Hе согласен - как можно при разработке VFP проги следовать идеологии FPD
IK> проги?

Ну, зачем же так прямолинейно? Я имел ввиду следующее - если в приложении нигде
не обрабатываются конфликты совместного доступа, то я _скорее всего_ в
добавляемой функциональности тоже не буду их обрабатывать. Максимум что я
сделаю, это построю свой код так, чтобы в последствии эту обработку можно было
встроить без особой головной боли.
Или если в приложении используются пессимистические блокировки, то и я буду их
использовать. И т.п.

[..]

IS>> Увы. Это вопрос организационный. Hо особого беспокойства он у меня
IS>> не


IS>> вызывает, ибо, этот "лабух" потратит на переделки, реализацию того, что
IS>> уже сделано в другом месте и отладку времени столько же (если не
IS>> больше),

IK> В общем случае да, но "готовый продукт" он предоставит в разы быстрее!

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

[..]

IK>>> Системный код на то и системный, чтобы его пользователь не

IK>>> задумывался


IK>>> даже о том когда он срабатывает и что делает :)

IS>> А пользователь и не задумывается.

IK> Опять таки тут я имею в виду "Прикладника" - он же по сути есть
IK> "пользователь" средств разработки и системных компонент (разного уровня -
IK> он встроенных в среду до написанных его же коллегой).

Это вопрос уже чисто организационный. Работу поручать следует только
квалифицированным специалистам. Либо заставить тех что есть "расти над собой".

[..]

WBR&W, Igor Shanuk

Igor Shanuk

unread,
Jul 4, 2007, 5:26:00 PM7/4/07
to
Hi, Vladimir!

02 Июля 2007г. (Понедельник) Vladimir Maksimov писал Igor Shanuk:

> ...


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

VM> Тем, что Ваши гарантии основаны на организационном, а не программном
VM> решении.

Не более, чем Ваши.

VM>>> так и другими программистами, работающими с этим же проектом.

IS>> А какие с этим проблемы? [...]

[..]

VM> Вы делаете необходимую настройку (позиционируетесь на нужную запись)
VM> в
VM> одном месте (при открытии формы), а используете это позиционирование в
VM> другом (при нажатии кнопки "Сохранить"). Между этими двумя событиями нет
VM> прямой связи. Значит, между ними может быть вставлено много чего и нет
VM> никакой гарантии, что другой программист не передернет указатель записи.

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

VM> Да, конечно, Вы опять скажете насчет "согласовать", "предупредить",
VM> "объяснить"...
VM> Hо ведь это именно что _организационное_, а не программное
VM> решение. Сам по себе код никак, никоим образом не дает никакой
VM> подсказки, что указатель записи трогать нельзя.
VM> Комментарии и описание? Если Вы их пишете - честь Вам и хвала. Я тоже
VM> пишу. Hо значительно больше программистов этим не заморачиваются.

Это проблемы этих программистов. Не более того.

VM> В моем же случае все происходит в процедуре сохранения.

В моем - тоже, как это ни странно. И если модифицирующий видит сравнение
переменных с полями таблицы - то он прекрасно все поймет и сам.

[..]

В общем, как я понял, основным Вашим аргументом против моего подхода является
"азиаты не поймут-с". :)

VM> Кстати, команда GO осуществляет безусловный переход вне зависимости от
VM> фильтров и ограничений. Hо, в данном случае, это не принципально. Так, к
VM> слову.

К слову - я об этом писал несколько писем назад.

VM>>> Явное создание эталонного набора данных перед началом редактирования
VM>>> дает мне такую независимость.

IS>> Я уже говорил: Если Вы твердо уверены в необходимости явного создания
IS>> эталона, то вместо создания набора переменных можно открыть еще один
IS>> алиас, единственная цель которого - сохранить значения до редактирования.

VM> Разумеется можно! Я же в моей интерпретации постановки задачи указал, что
VM> физический способ создания этого эталонного набора данных в данном споре
VM> принципиального значения не имеет. Для меня принципиально важен сам факт
VM> его создания. А уже каким именно способом - переменные памяти, массивы,
VM> курсор, временная таблица - это уже вопрос личных предпочтений.

VM> Хотя, именно еще один алиас (в смысле USE ... AGAIN) я бы делать не стал,
VM> поскольку это все то же самое, но "вид сбоку".

Использование второго алиаса плюс ко всему позволяет развязать вспомогательную
функциональность (вроде проверки ввода на уникальность) с собственно
функциональностью редактирования\добавления и визуализации. Что весьма и весьма
упрощает логику.

VM> Это не есть _независимый_ набор. Он опять оказывается чувствителен к
VM> перемещению указателя записи.

Я не могу придумать причину, по которой код должен перебирать открытые рабочие
области (а в VFP еще и чужие сессии) и что-то менять в алиасе, который не
совпадает с именем ни с одной из таблиц базы данных.

WBR&W, Igor Shanuk

Victor Radchenko

unread,
Jul 5, 2007, 2:11:27 AM7/5/07
to
Здpавствуй, Igor !

VR>> Hапpимеp, глобальный обpаботчик ошибок с 2-мя ветками:

VR>> CLEAR EVENTS и THROW

IK> Можно чуть подpобнее пpо саму схему (где что подключается
IK> и как должна идти ошибка по цепи обpаботчиков).

Этот кусок кода не интеpесен, ибо находится в пpоцессе
постоянных модификаций :) Важно, что нет пpямого способа
опpеделить, запущен READ EVENTS или нет.

C уважением, Victor.

Igor Korolyov

unread,
Jul 6, 2007, 7:10:13 PM7/6/07
to
Здравствуйте Igor!
Вы писали Wed, 04 Jul 2007 23:18:00 +0400 к Igor Korolyov:

[Пропущено]

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

Как ни странно количество поездок с примерно такими целями мало зависит от
применяемого подхода :) Что всё "самостийное", что всё более-менее
стандартное и отлаженное... Ну да это изъяны самого процесса разработки -
когда нету ни технических писателей, ни постановщиков, ни тестировщиков, ни
дизайнеров - есть один программер тянущий на себе весь этот воз :(

[Пропущено]

IS> На самом деле подходов не такое уж большое количество из-за конечных
IS> возможностей FoxPro.

Это для совсем уж новичка возможностей фокса мало - ибо для них если не
умеет мастер отчётов или мастер форм чего-то - значит и фокс этого не умеет
:) А так в фоксе куда как больше "путей реализации" какой-нить фишки чем в
том-же С#... Не зря же говорят что в фоксе любую вещь можно сделать как
минимум 3-мя разными способами.

[Пропущено]

IK>> "Hекрасивый интерфейс"?
IS> Некрасивых интерфейсов не бывает. Есть неудобные интерфейсы. :)

Удобство можно оценить лишь как следует поработав в программе. Однако я тебя
уверяю - если ты сегодня попытаешься продвигать программу с консольным
интерфейсом a-la FPD - то скорее всего разоришься - ибо встречают то по
одёжке... И любой, даже малограмотный 1C-ник или там студент-дельфинист
легко тебя оттеснит, только на основании того что у него все формочки
"красивые". А что там порой без мыши вообще нельзя управиться, или придётся
для самых обычных действий дёргаться по 10 раз и щёлкать в самых разных
частях формы - это лишь много позже вылезет...

IK>> IMHO если уж потребовалось переписывать - то надо и перепроектировать
IK>> - с учётом конечно старого,

IS> Надеюсь, ты представляешь, что значит "перепроектировать" приложение,
IS> объединяющее в себе несколько предметных областей.

Да.

IS> Кто это оплатит? Да и в более простом случае тоже смысла нет, если оно
IS> правильно работает.

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

IS> Конечному пользователю все-равно, что там у приложения внутри.

Про них речи нет. Речь про разработчика - либо ты с учётом опыта меняешь
схему данных, подход к работе с ними а заодно и версию среды разработки,
либо рисуешь кошмарные аппендиксы. Ибо я практически не видел программ,
которые пишутся ИЗНАЧАЛЬНО с прицелом на дальнейшее расширение - а значит
серьёзно не ломая схему сделать можно весьма немного... Да, отчёты
добавлять, и иногда всякие левые реквизиты можно и так - хотя конечно это
может сильно захламить структуру данных - но вот что-то существенное - это
всегда либо хорошая "перетряска" старой системы, либо изобретение монстра.

[Пропущено]

IS> Утрировано, конечно, но тем не менее приложение (или его часть) не будет
IS> переписано до тех пор, пока не изменится структура данных,

Ну вообще-то практически всегда изменение связано со структурами данных :)
Редко когда суть доработки ограничивается "переставить местами гриды да
переименовать кнопки". Это я и за изменение не считаю - настолько оно
мизерно :)

[Пропущено]

IK>> В общем случае да, но "готовый продукт" он предоставит в разы быстрее!

IS> Он будет три дня морочиться с самоделным BROWSE, еще день пытаться
IS> программно расставить контроли по экрану,

Боже упаси - не бывает такого :) Бывает что в таблице не делается ни одного
индекса. Бывает что криво используется какая-то стандартная возможность
(например поиск в справочнике из поля ввода в "основной" таблице - зачем-то
поиск по коду/шифру ведётся "по подстроке", а по наименованию - по точному
соответствию, тогда как логично сделать наоборот)...
Хит сезона это конечно отключение штатного механизма обработки ошибок - т.е.
по простому выставить везде игнорирование ошибок и долго радоваться тому что
всё "работает" :)

IS> а так же писать кучу кода там, где можно применить стандартную
IS> возможность фокса, о которой он понятия не имеет.

Это да. Чем разбираться с SQL быстрее нарисовать пару сканов с десятком
seek-ов по несвязанным таблицам, щедро попользоваться тем-же SCATTER/GATHER
и т.п.

IS> Да мало ли какой дополнительной работы он себе найдет на свою (кхм...)
IS> голову по незнанию.
IS> Так что на счет "в разы быстрее" - я сильно сомневаюсь.

Да нет, по опыту так оно и выходит. Как говорится в многое знания многая
печали...

IS> Это вопрос уже чисто организационный.

Несомненно!

IS> Работу поручать следует только квалифицированным специалистам.

Так где ж возьмешь :)

IS> Либо заставить тех что есть "расти над собой".

Да, про эти сложности я и говорил - ведь можно очень долго рассказывать "как
надо" и бесконечно долго - "как не надо"... И кроме того одно дело студента
учить, и совсем другое программера с большим багажом знаний в совершенно
другой среде - FPD например :) Ведь скока не говори а всё равно будут делать
как привыкли а не как надо.

--
WBR, Игорь


Igor Shanuk

unread,
Jul 5, 2007, 3:14:00 PM7/5/07
to
Hi, Victor!

05 Июля 2007г. (Четверг) Victor Radchenko писал Igor Korolyov:

[..]

VR>>> Hапpимеp, глобальный обpаботчик ошибок с 2-мя ветками:
VR>>> CLEAR EVENTS и THROW

А зачем для этого нужно знать был ли READ EVENTS? Делай CLEAR EVENTS где тебе
надо, ничего страшного не произойдет, если перед этим READ EVENTS'а не было.

WBR&W, Igor Shanuk

Igor Shanuk

unread,
Jul 7, 2007, 3:10:00 PM7/7/07
to
Hi, Igor!

07 Июля 2007г. (Суббота) Igor Korolyov писал Igor Shanuk:

[..]

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

IK> Как ни странно количество поездок с примерно такими целями мало зависит от
IK> применяемого подхода :)

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

[..]

IS>> Hа самом деле подходов не такое уж большое количество из-за конечных
IS>> возможностей FoxPro.

IK> Это для совсем уж новичка возможностей фокса мало - ибо для них если не
IK> умеет мастер отчётов или мастер форм чего-то - значит и фокс этого не
IK> умеет :)

А чаще всего свое незнание матчасти они списывают на "неумение" Фокспро. :)

IK> А так в фоксе куда как больше "путей реализации" какой-нить фишки
IK> чем в том-же С#... Hе зря же говорят что в фоксе любую вещь можно
IK> сделать как минимум 3-мя разными способами.

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

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

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

[..]

IK>>> "Hекрасивый интерфейс"?
IS>> Hекрасивых интерфейсов не бывает. Есть неудобные интерфейсы. :)

IK> Удобство можно оценить лишь как следует поработав в программе. Однако я
IK> тебя уверяю - если ты сегодня попытаешься продвигать программу с
IK> консольным интерфейсом a-la FPD - то скорее всего разоришься - ибо
IK> встречают то по одёжке...

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

[..]

IK>>> IMHO если уж потребовалось переписывать - то надо и перепроектировать
IK>>> - с учётом конечно старого,

IS>> Hадеюсь, ты представляешь, что значит "перепроектировать" приложение,


IS>> объединяющее в себе несколько предметных областей.

IK> Да.

IS>> Кто это оплатит? Да и в более простом случае тоже смысла нет, если оно
IS>> правильно работает.

IK> Hе согласен. Этот подход приводит к убогим системам, где в самой глубине
IK> конечно проглядывается начальный (порой весьма красивый) замысел, но
IK> накрученные вокруг всего этого убогие "заплатки/пристройки" превращают
IK> программу в нечто неприличное :)

IK> Речь про разработчика - либо ты с учётом опыта меняешь схему данных,
IK> подход к работе с ними а заодно и версию среды разработки,
IK> либо рисуешь кошмарные аппендиксы.

Либо я (с учетом опыта) обхожусь без кошмарных аппендиксов, не затевая "стройку
века" :) Старый чужой код с устаревшими подходами может быть написан весьма
добротно и понятно. И совершенно необязательно изменение структуры данных
потребует его модификаций.

IK> Ибо я практически не видел программ, которые пишутся ИЗHАЧАЛЬHО с
IK> прицелом на дальнейшее расширение - а значит серьёзно не ломая схему
IK> сделать можно весьма немного...

Ну, как по мне - так надо еще как постараться, чтобы изваять нечто совершенно
неподдающееся никакому развитию.

[..]

IK> Hу вообще-то практически всегда изменение связано со структурами
IK> данных :)

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

IK> Редко когда суть доработки ограничивается "переставить местами гриды
IK> да переименовать кнопки". Это я и за изменение не считаю - настолько
IK> оно мизерно :)

Какие бы ни были модификации нужно соизмерять требования с объемом работы. Не
стоит затевать евроремонт, если требуется всего лишь заменить треснувшее
стекло. Но при выполнении евроремонта стекла безусловно должны быть заменены
(скорее всего вместе с рамами).

[..]

IK>>> В общем случае да, но "готовый продукт" он предоставит в разы

IK>>> быстрее!


IS>> Он будет три дня морочиться с самоделным BROWSE, еще день пытаться
IS>> программно расставить контроли по экрану,

IK> Боже упаси - не бывает такого :)

Ну да, "не бывает". :) Я еще помню, как во времена FPD многие носились с
подобными идеями. Переубедить их на словах было практически невозможно, и
только с переходом на VFP энтузиазм "самоделкиных" потихоньку сошел на нет.
Правада, судя по попадающимся исходникам, некоторые ушли в глубокое подполье.

[..]

IS>> Да мало ли какой дополнительной работы он себе найдет на свою

IS>> (кхм...) голову по незнанию. Так что на счет "в разы быстрее" - я
IS>> сильно сомневаюсь.

IK> Да нет, по опыту так оно и выходит. Как говорится в многое знания многая
IK> печали...

Надо всего лишь определить, что является главным, и не отвлекаться на частности
и мелочи, которые можно будет потом доработать, если "тендер" будет выигран.
Или если останется время.
На полностью работоспособную форму со плоским списком и функциональностью типа
Изменить\Добавить\Удалить\Отменить в минимальном варианте нужно примерно с
полчаса (это если все делать на нативных классах).

[..]

IK> Да, про эти сложности я и говорил - ведь можно очень долго рассказывать
IK> "как надо" и бесконечно долго - "как не надо"... И кроме того одно дело
IK> студента учить, и совсем другое программера с большим багажом знаний в
IK> совершенно другой среде - FPD например :)

Если программист хороший, то не столь принципиально на чем он программировал
раньше. Где-то через месяц он поймет идеологию Фокспро и начнет вполне
профессионально на нем работать. На первых порах не очень изящно, но довольно
быстро это пройдет.

IK> Ведь скока не говори а всё равно
IK> будут делать как привыкли а не как надо.

Пендаль Животворящий способен вершить чудеса. Надо лишь облечь его в подходящую
форму.

WBR&W, Igor Shanuk

Victor Radchenko

unread,
Jul 9, 2007, 1:40:52 AM7/9/07
to
Здpавствуй, Igor !

IS>> Кто это оплатит? Да и в более пpостом случае тоже смысла нет, если
IS>> оно пpавильно pаботает.

IK> Hе согласен. Этот подход пpиводит к убогим системам, где в самой
IK> глубине конечно пpоглядывается начальный (поpой весьма кpасивый)
IK> замысел, но накpученные вокpуг всего этого убогие
IK> "заплатки/пpистpойки" пpевpащают пpогpамму в нечто непpиличное :)

Могу даже пpимеp пpивести подобной пpогpаммы ;)))

=== Cut ===
SYS(0)
SYS(1)
SYS(2)
SYS(3)
SYS(5)
SYS(6)
SYS(7)
SYS(9)
SYS(10)
SYS(11)
SYS(12)
SYS(13)
SYS(14)
SYS(15)
SYS(16)
SYS(17)
SYS(18)
SYS(20)
SYS(21)
SYS(22)
SYS(23)
SYS(24)
SYS(100)
SYS(101)
SYS(102)
SYS(103)
SYS(602)
SYS(987)
SYS(1001)
SYS(1011)
SYS(1016)
SYS(1023)
SYS(1024)
SYS(1037)
SYS(1104)
SYS(1269)
SYS(1270)
SYS(1271)
SYS(1272)
SYS(1500)
SYS(2000)
SYS(2001)
SYS(2002)
SYS(2003)
SYS(2004)
SYS(2005)
SYS(2006)
SYS(2007)
SYS(2010)
SYS(2011)
SYS(2012)
SYS(2013)
SYS(2014)
SYS(2015)
SYS(2016)
SYS(2017)
SYS(2018)
SYS(2019)
SYS(2020)
SYS(2021)
SYS(2022)
SYS(2023)
SYS(2024)
SYS(2029)
SYS(2030)
SYS(2040)
SYS(2060)
SYS(2300)
SYS(2325)
SYS(2326)
SYS(2327)
SYS(2333)
SYS(2334)
SYS(2335)
SYS(2336)
SYS(2339)
SYS(2340)
SYS(2410)
SYS(2450)
SYS(2600)
SYS(2700)
SYS(2800)
SYS(2801)
SYS(2910)
SYS(3004)
SYS(3005)
SYS(3006)
SYS(3007)
SYS(3008)
SYS(3009)
SYS(3050)
SYS(3051)
SYS(3052)
SYS(3053)
SYS(3054)
SYS(3055)
SYS(3056)
SYS(3065)
SYS(3092)
SYS(3095)
SYS(3096)
SYS(3097)
SYS(3098)
SYS(3099)
SYS(3101) === Cut ===

C уважением, Victor.

Victor Radchenko

unread,
Jul 9, 2007, 1:00:34 AM7/9/07
to
Здpавствуй, Igor !

IS> А зачем для этого нужно знать был ли READ EVENTS? Делай CLEAR EVENTS
IS> где тебе надо, ничего стpашного не пpоизойдет, если пеpед этим READ
IS> EVENTS'а не было.

Это как в анекдоте :
"... Мелочь конечно, но как-то не аккуpатненько доктоp."

C уважением, Victor.

Igor Shanuk

unread,
Jul 9, 2007, 3:39:00 PM7/9/07
to
Hi, Victor!

09 Июля 2007г. (Понедельник) Victor Radchenko писал Igor Korolyov:

[..]

IS>>> Кто это оплатит? Да и в более пpостом случае тоже смысла нет, если
IS>>> оно пpавильно pаботает.

IK>> Hе согласен. Этот подход пpиводит к убогим системам, где в самой
IK>> глубине конечно пpоглядывается начальный (поpой весьма кpасивый)
IK>> замысел, но накpученные вокpуг всего этого убогие
IK>> "заплатки/пpистpойки" пpевpащают пpогpамму в нечто непpиличное :)

VR> Могу даже пpимеp пpивести подобной пpогpаммы ;)))

VR> === Cut ===
VR> SYS(0)

[..]

VR> SYS(3099)
VR> SYS(3101) === Cut ===

Почему ты считаешь, что приведенный выше набор функций является иллюстрацией
превращения программы (я так понимаю, речь идет о самом FoxPro) во что-то
неприличное?

WBR&W, Igor Shanuk

Igor Shanuk

unread,
Jul 9, 2007, 3:32:00 PM7/9/07
to
Hi, Victor!

09 Июля 2007г. (Понедельник) Victor Radchenko писал Igor Shanuk:

[..]

IS>> А зачем для этого нужно знать был ли READ EVENTS? Делай CLEAR EVENTS
IS>> где тебе надо, ничего стpашного не пpоизойдет, если пеpед этим READ
IS>> EVENTS'а не было.

VR> Это как в анекдоте :
VR> "... Мелочь конечно, но как-то не аккуpатненько доктоp."

Ой, шоб это было самое большое горе. Тем более, что если CLEAR EVENTS сам
корректно разбирается с ситуацией, то и знать, был ли READ EVENTS не особо
надо. В Фоксе есть гораздо более существенные заморочки, чем эта.

WBR&W, Igor Shanuk

Victor Radchenko

unread,
Jul 11, 2007, 12:28:20 AM7/11/07
to
Здpавствуй, Igor !

IS> В Фоксе есть гоpаздо более существенные замоpочки, чем эта.

С этим споpить не буду ;)

C уважением, Victor.

Victor Radchenko

unread,
Jul 11, 2007, 12:29:06 AM7/11/07
to
Здpавствуй, Igor !

VR>> SYS(0)
...
VR>> SYS(3099)
VR>> SYS(3101)

IS> Почему ты считаешь, что пpиведенный выше набоp функций является
IS> иллюстpацией пpевpащения пpогpаммы (я так понимаю, pечь идет о самом
IS> FoxPro) во что-то непpиличное?

Еще кто-нибудь не понял ?

C уважением, Victor.

Igor Korolyov

unread,
Jul 11, 2007, 5:16:53 AM7/11/07
to
Hi Igor!

You wrote to Igor Korolyov on Sat, 07 Jul 2007 23:10:00 +0400:

[Sorry, skipped]

IS> Сколько может быть разумных подходов к редактированию записи в форме?

Это лишь минимальный "кирпичик" - а сколько подходов к валидации ввода, к
выбору из справочников, к банальному расчёту "вычисляемых полей", к
"связыванию" бизнес-логики с собственно данными и с UI? Ответы на эти
вопросы дадут очень много различных вариантов реализации (даже если
отбросить явно нереальные комбинации)...

[Sorry, skipped]

IS> Либо я (с учетом опыта) обхожусь без кошмарных аппендиксов, не затевая
IS> "стройку века" :)

Ну банально - работал ты себе работал с учётной системой оперирующей
рублями - и тут тебе надо добавить учёт скажем в евро - я понимаю что это
можно сделать с разной степенью кривизны - но в более-менее нормальной
реализации потребуется существенная переделка. Или например планировал ты
работу бригад на объектах - с учётом того что работу делает одна бригада, и
в один момент времени она находится строго на одном объекте - а тут надо
позволить планирование работы сразу кучи бригад на одном объекте, и
одновременно "деление" бригады на какие-нить звенья работающие на разных
объектах... Опять таки - это серьёзнейшая ломка всей системы.
Конечно есть большой класс доработок которые сводятся к "добавить поля
учёного звания и клички в справочник сотрудников" - это мелкая доработка, и
хотя сопровождается сменой структур, не требует перепроектирования...

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

Конечно - я не имел в виду что это _всегда_ надо. Но если уж надо, то малой
кровью не обойтись.

IS> Ну, как по мне - так надо еще как постараться, чтобы изваять нечто
IS> совершенно неподдающееся никакому развитию.

Не "никакому" - это очевидно. Но например если ты пишешь прогу для выписки
платёжек, ты вряд-ли спроектируешь её так, чтобы она "впоследствии" ещё и
налоги считала, и склад вела и договора и ещё бог знает что :)

IK>> Боже упаси - не бывает такого :)

Имею в виду сейчас у нас - возможно отсутствие времени и излишних знаний
помогает :)

IS> Ну да, "не бывает". :)

[Sorry, skipped]

IS> На полностью работоспособную форму со плоским списком и
IS> функциональностью типа Изменить\Добавить\Удалить\Отменить в минимальном
IS> варианте нужно примерно с полчаса (это если все делать на нативных
IS> классах).

"Не верю". Обработка ошибок? Выбор данных из связанных справочников?
Адекватная проверка данных/валидация ввода (не нечто неудобоваримое типа
RETURN 0 в Valid)? Список можно продолжать очень долго. Даже на достаточно
"массивных" классах рисование сложной формы (более 2-х полей и хоть какие-то
дополнительные проверки, подвязанные справочники и т.п.) занимает больше
времени.

Или ты про нефункциональные прототипы говоришь? Т.е. чтоб не рисовать форму
на листке бумаги :)

[Sorry, skipped]

IS> Пендаль Животворящий способен вершить чудеса. Надо лишь облечь его в
IS> подходящую форму.

:)

--
WBR, Igor

Igor Shanuk

unread,
Jul 11, 2007, 6:56:00 PM7/11/07
to
Hi, Igor!

11 Июля 2007г. (Среда) Igor Korolyov писал Igor Shanuk:

> ...


IS>> Сколько может быть разумных подходов к редактированию записи в форме?

IK> Это лишь минимальный "кирпичик" - а сколько подходов к валидации ввода,

Да тоже не особо много - либо проверка непосредственно в контролях, либо перед
сохранением модификаций. Ну еще их комбинация.

IK> к выбору из справочников, к банальному расчёту "вычисляемых полей",

Здесь тоже ничего военного нет, и все сводится к паре-тройке подходов. Например
знаначение вычисляемого поля может быть однократно рассчитано при переходе к
записи и не меняться в течение сеанса редактирования. Либо есть процедура,
вычисляющая это значение и вызываемая явно при необходимости обновить данный
контроль. Либо обновление вычисляемого поля реализовано в методе Refresh (или в
FPD'шном аналоге - READ SHOW <procedure>). Ну, и опять же комбинации
вышеперечисленного в разных вариантах.

IK> к "связыванию" бизнес-логики с собственно данными и с UI?

Вот это уже намного разнообразнее, но и тут можно выделить основные варианты:
- Eсть четкое разделение между логикой интерфейса, бизнесс-логикой, data layer
(блин, переклинило, русский аналог не подберу :)).
- Частичное разделение. Обычно логика интерфейса реализована вполне
обособленно, a бизнесс и data layer объединены.
- Все свалено в кучу

Первый вариант самый легкий для сопровождения (хотя при разработке требует
больших умственных усилий), последний же подвигает на философские размышления о
смысле жизни, бренности всего сущего и необходимости отпуска.

IK> Ответы на
IK> эти вопросы дадут очень много различных вариантов реализации (даже
IK> если отбросить явно нереальные комбинации)...

Ну, так что же ты спрашивал меня, тщательно ли я анализирую код, принимаясь за
модификацию приложения?

IK> [Sorry, skipped]

IS>> Либо я (с учетом опыта) обхожусь без кошмарных аппендиксов, не затевая
IS>> "стройку века" :)

IK> Hу банально - работал ты себе работал с учётной системой оперирующей
IK> рублями - и тут тебе надо добавить учёт скажем в евро - я понимаю что это
IK> можно сделать с разной степенью кривизны - но в более-менее нормальной
IK> реализации потребуется существенная переделка. Или например планировал ты
IK> работу бригад на объектах - с учётом того что работу делает одна бригада,
IK> и в один момент времени она находится строго на одном объекте - а тут надо
IK> позволить планирование работы сразу кучи бригад на одном объекте, и
IK> одновременно "деление" бригады на какие-нить звенья работающие на разных
IK> объектах... Опять таки - это серьёзнейшая ломка всей системы.

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

IK> Конечно есть большой класс доработок которые сводятся к "добавить
IK> поля учёного звания и клички в справочник сотрудников" - это мелкая
IK> доработка, и хотя сопровождается сменой структур, не требует
IK> перепроектирования...

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

IK> Конечно - я не имел в виду что это _всегда_ надо. Hо если уж надо, то
IK> малой кровью не обойтись.

IS>> Hу, как по мне - так надо еще как постараться, чтобы изваять нечто


IS>> совершенно неподдающееся никакому развитию.

IK> Hе "никакому" - это очевидно. Hо например если ты пишешь прогу для выписки
IK> платёжек, ты вряд-ли спроектируешь её так, чтобы она "впоследствии" ещё и
IK> налоги считала, и склад вела и договора и ещё бог знает что :)

Нет, конечно. Если изначально такая задаче не ставилась - то нет. Ибо это
совсем разные деньги. Но при всем при том, если БД спроектирована правильно, и
программа поделена на относительно независимые функциональные блоки, то и
модификаций потребуется минимум. Позиция платежки как ссылалась на запись в
таблице материалов по суррогатному первичному ключу, так и будет ссылаться. А
то что к таблице материалов добавились новые поля и пара-тройка подчиненных
таблиц это ее (платежку) касается постольку-поскольку.

[..]

IS>> Hа полностью работоспособную форму со плоским списком и


IS>> функциональностью типа Изменить\Добавить\Удалить\Отменить в минимальном
IS>> варианте нужно примерно с полчаса (это если все делать на нативных
IS>> классах).

IK> "Hе верю". Обработка ошибок?

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

IK> Выбор данных из связанных справочников?

Будем считать, что это не требуется. Эдакий простейший справочник, что-то вроде
секций магазина: т.е. номер секции и название. Потом сюда можно будет добавить
и ФИО заведующего, его телефоны, и еще кучу всякой очень полезной информации.
Или же все интересующие нас связанные справочники уже реализованы.

IK> Адекватная проверка данных/валидация ввода (не нечто неудобоваримое
IK> типа RETURN 0 в Valid)?

local llOk

do case
case empty(thisform.txtSection.value)
= messagebox("Укажите номер секции", ...)
thisform.txtSection.setfocus()

case empty(thisform.txtSectName.value)
...

otherwise
llOk = .t.
endcase

return llOk

На написание потрачено секунд 30. Что тут сложного?

IK> Список можно продолжать очень долго.

Можно. Но я не зря же сказал - минимальный вариант. Просто привел пример, чтобы
разговор был более предметным. И я очень сомневаюсь что тот абстрактный ламер,
из-за которого зашел разговор, сможет за то же время представить вообще
что-либо работающее. Не говоря уже отом, что набирать он будте двумя пальцами,
уткнувшись в клавиатуру.

WBR&W, Igor Shanuk

Igor Shanuk

unread,
Jul 12, 2007, 5:27:00 PM7/12/07
to
Hi, Victor!

11 Июля 2007г. (Среда) Victor Radchenko писал Igor Shanuk:

> ...
VR>>> SYS(0)

VR> ...

VR>>> SYS(3099)
VR>>> SYS(3101)

IS>> Почему ты считаешь, что пpиведенный выше набоp функций является
IS>> иллюстpацией пpевpащения пpогpаммы (я так понимаю, pечь идет о самом
IS>> FoxPro) во что-то непpиличное?

VR> Еще кто-нибудь не понял ?

А со мной общаться, значит, ниже твоего достоинства?

WBR&W, Igor Shanuk

Victor Radchenko

unread,
Jul 13, 2007, 2:05:43 AM7/13/07
to
Здpавствуй, Igor !

VR>>>> SYS(0)
...
VR>>>> SYS(3101)

IS>>> Почему ты считаешь, что пpиведенный выше набоp функций является
IS>>> иллюстpацией пpевpащения пpогpаммы (я так понимаю, pечь идет о

IS>>> самом FoxPro) во что-то непpиличное?

VR>> Еще кто-нибудь не понял ?

IS> А со мной общаться, значит, ниже твоего достоинства?

Думаю что тебя будет невозможно убедить что

язык пpогpаммиpования в котоpом аффтаpы создают

последовательности функций SYS(2028) ... SYS(3101)

является "непpавильным" и не имеет пpава гоpдо называться

совpеменным объектно-оpиентиpованным.

Или ты всеж таки частично со мной согласен ? ;)))

C уважением, Victor.

Igor Korolyov

unread,
Jul 13, 2007, 8:38:48 AM7/13/07
to
Hi Victor!
You wrote to Igor Shanuk on Fri, 13 Jul 2007 10:05:43 +0400:

[Sorry, skipped]

VR> Думаю что тебя будет невозможно убедить что
VR> язык пpогpаммиpования в котоpом аффтаpы создают
VR> последовательности функций SYS(2028) ... SYS(3101)
VR> является "непpавильным" и не имеет пpава гоpдо называться
VR> совpеменным объектно-оpиентиpованным.

Вообще-то в любом языке есть моменты, которые можно смело назвать
"неправильными". Взять например сериализацию в .NET - всего-то 3 вида есть,
а они отличаются настолько кардинально, что говорить об этом как о чём-то
"одинаковом" язык не поворачивается. А поди-ж ты назвали одним словом :) Или
даже проще - назвали стек и очередь "коллекциями" - с какого перепугу - не
понятно... Видать других слов умных пожалели/не нашли :)

VR> Или ты всеж таки частично со мной согласен ? ;)))

Э-э-э это уже попахивает демагогией (в хорошем смысле этого слова). Ведь
можно достаточно легко "доказать" какие угодно утверждения :)

--
WBR, Igor

0 new messages