Общие принципы построения приложения в FoxPro

sg12
Дата: 25.01.2013 19:50:04
Чтож, по просьбам откроем новую тему.
sg12
Дата: 25.01.2013 19:54:40
ВладимирМ
Объясните, пожалуйста, что вы имели ввиду под термином, вынесеным по вашей просьбе в заголовок темы?
PaulWist
Дата: 25.01.2013 20:18:02
sg12
Чтож, по просьбам откроем новую тему.
Sergey Ch, пожалуйста, снесите в старой теме все, начиная с моего провокационного поста.


Эту статью читали?
ВладимирМ
Дата: 25.01.2013 20:18:33
Я имел в виду хотя бы общее представление о том, как приложение должно отображать/изменять данные. Интерфейс с пользователем, программная реализация этого интерфейса, хранение данных, способы обработки.

Обсуждение началось вот с этого

sg12
А здесь всего три процедуры "Добавить, Удалить, Изменить" в двух вариациях.

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

И ошибка была бы только в строке вызова, и то при неправильном синтаксисе.

Для начала примерно так:
LPARAMETERS tcCase
DOCASE
CASE tcCase == 'Add'
***
CASE tcCase == 'Delete'
***
CASE tcCase == 'Edit"
***
ENDCASE


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

Вот пользователь открыл приложение. Очевидно, вызвал некую форму. Далее ему надо изменить существующую запись. Что надо сделать пользователю, чтобы это произошло? Каким образом действия пользователя приведут к использованию Вашего Do Case? Где в приложении место для подобного кода?
sg12
Дата: 25.01.2013 20:41:41
PaulWist
Эту статью читали?


Читал.
Статья хорошая, но в ней допущены серьезные недоработки, к которым мы еще будем возвращаться. Поэтому я прошу ВладимираМ предъявить реальный пример.

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

Процедура DoEdit
LPARAMETERS tcCase
DOCASE
CASE tcCase == 'Add'
***
CASE tcCase == 'Delete'
***
CASE tcCase == 'Edit"
***
ENDCASE

Процедура DoSave
LPARAMETERS tcCase
DOCASE
CASE tcCase == 'Update'
***
CASE tcCase == 'Revert'
***
ENDCASE
Dima T
Дата: 25.01.2013 21:03:52
sg12
Как вы думаете, что изменится, если из его главного модуля перенести процедуры добавления, удаления, редактирования, а также сохранения и восстановления в следующие процедуры объекта oTable

Сместится точка возникновения ошибок. Ошибки будут происходить в этом коде. Сообщения об ошибках будут указывать на этот код и будет непонятно где реально ошибка.

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

В остальном ничего не изменится.
Dima T
Дата: 25.01.2013 21:22:30
И потом сам предлагаемый шаблон изначально ущербный.
Например oTable.DoEdit('add') не сработает и ошибки не будет.
Если уж городить огород то делать oTable.Add()
sg12
Дата: 25.01.2013 21:47:23
Dima T,

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

Что изменится? Главный модуль "похудеет" и станет менее "страшнее" на пять процедур, и это только начало.
А для работы с этими процедурами напишем объект класса CommandGroup с тремя кнопками, который будем навешивать на формы.
Или два класса - по 3 и 2, кому что по вкусу.
Т.е. избавим наши формы от необходимости чуть не в каждой писать индивидуально эти же процедуры, от которых рябит в глазах.
sg12
Дата: 25.01.2013 22:04:20
Напишем еще одну процедуру DoNavigate:
LPARAMETERS tcCase
DOCASE
CASE tcCase == 'Top'
***
CASE tcCase == 'Bottom'
***
CASE tcCase == 'Prior'
***
CASE tcCase == 'Next'
***
ENDCASE

Перенесем туда существующие процедуры. Главный модуль похудеет аж на целый класс.
Создадим аналогичный объект класса CommandGroup с четырьмя кнопками, разрисуем их и еще один вопрос снят.
Станислав С...кий
Дата: 25.01.2013 23:06:10
sg12,
Почитал Ваши рассуждения и не соглашусь с некоторыми из них.
1. Прежде всего, если исходить из понятия "таблица", как множества строк, то к таблице должны относиться только процедуры:

Update/Commit - фиксирование изменений
Revert/Rollback - откат изменений.

Процедцры Add - добавление строки и Delete - удаление строки должны относиться к классу записи/строки таблицы (oRow или oRecord)

Процедура Edit не может относиться к таблице: значения меняются не в абстрактной таблице, а в конкретной ячейке (на пересечнии конкретных столбца и строки). Поэтому процедура Edit должна относиться либо к классу поля (oField), либо к классу ячейки (oCell)...

Хотя нет, обманываю... Edit может быть у таблицы. Но она, по логике ООП, должна относиться не к редактированию записей, а к редактированию структуры таблицы (что-то типа alter table...). По той же логике Add должно создавать таблицу / копию таблицы, а Delete - удалять таблицу.

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

Мне на практике приходилось сопровождать систему (биллинговая система оператора связи), написанную на Alaska xBase (потомок Clipper'а) с высоким уровнем абстракции - на макроподстановках.
Да, она была компактна и, в чем-то даже изящна. Все ее программы ("скрипты") содержались в текстовых файлах. При работе программы из этих файлов читались строки и выполнялись через макроподстановку.
Все, что когда-то было отлажено - работало четко.
Но когда нужно было отладить новый алгоритм, тогда и начинались "пляски с бубном"... Синтаксические ошибки еще худо-бедно можно было отлавливать. А вот логические ошибки в макроподстановках искать - то еще удовольствие...
Примерно такое же, как отлаживать сложный SQL запрос, динамически формируемый на клиенте, при помощи SQLEXEC()...