Какой не должна быть программа

Какой не должна быть программа: советы и рекомендации для начинающих

Какой не должна быть программа

Какой не должна быть программа

Когда-то я был маленький
Еще не знал кем быть
Но очень уж не нравилось
Фекалии возить

Много книг и статей касаются темы «Какой должна быть программа». Если программы еще нет, то сам такой подход можно считать оптимистическим (может ее никогда и не будет). Рассмотрим похожую тему «Какой не должна быть программа». Если программы еще нет и, следовательно не известно будет ли она, то подход можно назвать пессимистическим (если она будет такой, какой не должна быть, лучше б ее и не было вообще).
Итак, еще не знаем как писать, но на ровном месте нагнетаем обстановку и говорим, допустим, не хочу потратить много времени на отладку, иметь проблемы с модернизацией и сопровождением. Список можно продолжить, но не включая пунктов таких, например, как « не хочу, чтобы мою программу похитили». Это уже оптимизм – надо еще ее сделать такой, чтобы ее кому то хотелось украсть.
Оптимизм и пессимизм по Гегелю – две стороны одного или единство и борьба противоположностей. Поработаешь хорошо на свой пессимизм и станешь оптимистом. Поработай с оптимизмом, но без опыта и почувствуешь законы Мерфи на свой шкуре и можешь впасть в пессимизм и это уже прямой путь к депрессии. Выработать иммунитет легче пессимисту – из депрессии в депрессию хода нет.
Программа начинает свою жизнь при первом запуске кода. Но это стадия эмбриона. На этой стадии пишем и отлаживаем. Если Вы молодой оптимист и пишите сразу длинный код со всеми бантиками – отладка не оставит времени на досуг. Долгая отладка раздражает и утомляет, а дистанция длинная и нужно экономить силы.
Напишите самую суть, отладьте и порадуйтесь жизни – что-то уже есть. Можно улучшать код – скорость, интерфейсные штучки, фишки красивые и т.д.
Программа начинает жизнь после первого показа тому, кто ее не писал.
Хорошо, когда ее ругают – еще есть время исправить ее, а со стороны лучше видно, что в ней плохо.
Программа начинает взрослую жизнь после установки у заказчика (даже если это ознакомительная версия). Теперь могут всплыть самые серьезные ошибки, а увидите их первыми не Вы. Скорее всего вы узнаете об этом по телефону и на ломаном русском вам продиктуют английские буквы сообщения об ошибке. Что делать?
Стоит написать обработчик ошибок.
Где-то в стартовом коде поставим
ON ERROR DO ERRTRAP WITH ERROR(), MESSAGE(), MESSAGE(1), SYS(2018), LINENO()
Можно и не передавать параметры, но бывает это полезно. Например, я вызываю ту же ERRTRAP в Catch’е структуры Try … endtry и передаю через параметры свойства объекта.
Что должно быть в ERRTRAP?
- возможность протолкнуть ошибку или снять задание
- сохранение информации об ошибке (например, в Errors.dbf)
- вызов формы с сообщением об ошибке в таком виде, который по возможности не сильно шокирует юзера и дает ему шанс сообщить Вам что-то полезное по телефону. Если есть модемная связю с юзером, то можно получить файл Errors.dbf и разобраться в ситуации.

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

2. Использование правил при названии переменных и полей.
Пользуюсь рекомендациями MicroSoft. 2 первых символа имени переменной памяти означают область действия (l,g – local,public) и тип переменной (c,n,d,t,l,u,o,a – соответственно текст, число, дата, время, логическое, неопределенное, объект и массив). Поля называю без префикса.
Например, если поле UserName, тогда

lcUserName = UserName

и можно не писать m.lcUserName.
Если надо, чтобы lcUserName была Private, то пишу явно. Public тоже пишу явно, но тогда переменная должна быть gcUserName.
Выделяю и беру в карман текст программы или метода. К функциональной клавише F9 у меня привязан код, по которому в кармане добавляется оператор Local для переменных с префиксом ‘l’:
ON KEY LABEL F9 DO locals
Заменяю выделенное на карман и не боюсь неприятной ошибки, когда в вызываемой программе или методе найдется переменная – двойник.
Текст программы locals:

#DEFINE TAB CHR(9)
#DEFINE CRLF CHR(13)+CHR(10)
SET EXACT ON
LOCAL i, lc1, lc2, lcLeft, lcLine, lcOther, lcPrefix, ;
ll, ln, lnEq, lnLine, lnLines, lnLocal

lc=_CLIPTEXT
lnLines=ALINES(la,lc)
STORE " " TO gcExclude
DIME laLocals(1), gaOther(1), laDeclare(3)
laDeclare(1)="LOCAL "
laDeclare(2)="PRIVATE "
laDeclare(3)="PUBLIC "
laLocals(1)="@"
STORE 0 TO gnLocals, gnOther

FOR lnLine=1 TO lnLines
IF LEFT(la(lnLine),1)="*"
LOOP
ENDIF
lcLine=ALLT( CHRT(la(lnLine),TAB," "))
FOR ln=1 TO ALEN(laDeclare,1)
lnLocal=AT(laDeclare(ln) , UPPER(lcLine))
IF lnLocal=1
i=1
DO WHILE RIGHT(lcLine,1) = ";"
lcLine=RTRIM(LEFT(lcLine,LEN(lcLine)-1))+CHRT(ALLT(la(lnLine+i)),TAB," ")
i=i+1
ENDDO
gcExclude=gcExclude+ UPPER(ALLT( SUBS( lcLine,AT( laDeclare(ln), UPPER(lcLine))+6)))+" "
LOOP
ENDIF
NEXT
lnLocal=AT("LPARA" , UPPER(ALLT(lcLine)))
IF lnLocal=1
gcExclude=gcExclude+ UPPER(ALLT( SUBS( lcLine,AT(" " , UPPER(lcLine)))))+" "
LOOP
ENDIF
NEXT
gcExclude=CHRT(gcExclude,","," ")

FOR lnLine=1 TO lnLines
IF LEFT(la(lnLine),1)="*"
LOOP
ENDIF
lcLine=ALLT(CHRT(la(lnLine),TAB," "))
IF UPPER(LEFT(lcLine,6))="STORE " AND " TO " $ UPPER(lcLine)
lc1=SUBS(lcLine,AT(" TO ",UPPER(lcLine))+4)+","
ln=OCCURS(",",lc1)
FOR i=1 TO ln
lc2=ALLT(LEFT(lc1,AT(",",lc1)-1))
IF "(" $ lc2
LOOP
ENDIF
=putIt(lc2)
lc1=SUBS(lc1,AT(",",lc1)+1)
NEXT
LOOP
ENDIF
lnEq=AT("=",lcLine)
IF lnEq=0
LOOP
ENDIF
lcLeft=ALLT(LEFT(lcLine,lnEq-1))
IF LEFT(lcLeft,4)="FOR "
=putIt(SUBS(lcLeft,5))
LOOP
ENDIF
IF LEFT(lcLeft,2)="M."
lcLeft=SUBS(lcLeft,3)
ENDIF
IF "&" $ lcLeft
LOOP
ENDIF
IF " " $ lcLeft OR "." $ lcLeft
LOOP
ENDIF
=putIt(lcLeft)
NEXT

= ASORT(laLocals)

gclocals="LOCAL "
lcPrefix="@@"
FOR lnLine=1 TO gnLocals
lc=laLocals(lnLine)
IF LEN(lc)>1
lc=LOWER(LEFT(lc,2))+UPPER(SUBS(lc,3,1))+IIF(LEN(lc)>3,SUBS(lc,4),"")
ll = lcPrefix # LEFT(lc,2) AND lnLine>1
lcPrefix=LEFT(lc,2)
ELSE
lc=LOWER(lc)
ll=.F.
ENDIF
gclocals=gclocals+IIF(ll,TAB+";"+CRLF+TAB,"")+ lc+IIF(lnLine=gnLocals,"",", ")
NEXT
i=0
lcOther=""
FOR lnLine=1 TO gnOther
lc=gaOther(lnLine)
lcOther=lcOther+IIF(i>6,CRLF,"")+ lc+IIF(lnLine=gnOther,"",", ")
i=IIF(i>6,0,i+1)
NEXT

lc=IIF(LEN(gclocals)<7,"","Карман @"+gclocals) ;
+IIF(EMPTY(lcOther),"","@@Другие : "+lcOther)
IF !EMPTY(lc)
IF messagebox(lc,292,"Делать вставку?")=7
_CLIPTEXT=gclocals+CRLF
RETU
ENDIF
ELSE
= messagebox ("OK",0,'')
RELEASE la
RETURN
ENDIF

lnInsert=0
lnTabs=0
FOR lnLine=1 TO lnLines
lcLeft4=UPPER(LEFT(ALLT(CHRT(la(lnLine),TAB," ")),4))
IF INLIST(lcLeft4,"FUNC","PROC","PARA","LPAR") ;
OR "#" $ lcLeft4 OR LEFT(lcLeft4,1)="*"
LOOP
ENDIF
lnInsert=lnLine
lnTabs=OCCURS(TAB,la(lnLine))
EXIT
NEXT
IF BETW(lnInsert,1,lnLines) AND LEN(gclocals)>6
lc=""
FOR lnLine=1 TO lnInsert-1
lc=lc+la(lnLine)+CRLF
NEXT
lc=lc+IIF(lnTabs>0,REPL(TAB,lnTabs),"")+gclocals+CRLF
FOR lnLine=lnInsert TO lnLines
lc=lc+la(lnLine)+CRLF
NEXT
_CLIPTEXT=lc
KEYBOARD '{CTRL+V}'
RETURN
ENDIF
_CLIPTEXT=gclocals+CRLF

FUNC putIt
LPARA lc
lcUp=UPPER(lc)
IF EMPTY(lc)
RETURN
ENDIF
IF " "+lcUp+" " $ gcExclude
RETU
ENDIF
IF "(" $ lc
RETU
ENDIF
IF ! INLIST(LEFT(lcUp,2) , "LC", "LD", "LT", "LU", "LN", "LL", "LO") ;
AND !LEFT(lcUp,1) $ "IJ"
IF ASCAN(gaOther,lcUp)>0
RETU
ENDIF
gnOther=gnOther+1
DIME gaOther(gnOther)
gaOther(gnOther)=lcUp
ELSE
FOR lnLine=1 TO ALEN(laLocals)
IF UPPER(laLocals(lnLine))=lcUp
RETU
ENDIF
NEXT
gnLocals=gnLocals+1
DIME laLocals(gnLocals)
laLocals(gnLocals)=lc
ENDIF
RETU

Стараюсь избегать коротких имен. Раньше писал, например,
FOR i=1 to N

Next
Когда требовалось найти или переименовать переменую i, то натыкался на массу слов, в которых есть эта буква. Сейчас пишу
FOR lnLine=1 TO lnLines

NEXT

Во-первых, знаю, что речь идет о строке (Line) и, что их количество lnLines, а не безликое N.

1. Проблема открытия и закрытия файла
Не люблю сообщений “file is in use” и ему подобных.
Две подпрограммы AutoLoad(‘список файлов’) и Unload() помогают жить.
lcListOfFiles = AutoLoad(‘partners;people’)
В переменную lcListOfFiles попадает информация для каждого файла из списка о том, был ли он до того открыт. После вызова AutoLoad все файлы будут открыты, если они вообще видны.
Далее с помощью
=Unload(lcListOfFiles)
закрываются файлы, которые ранее не были открыты.
Написать подобные подпрограммы может каждый. В моих присутствует дополнительный код, нужный не каждому.
С помощью подпрограммы Close(‘список файлов’) закрываю файл, если от открыт

FUNC Close
LPARA lc1,lc2,lc3,lc4,lc5,lc6,lc7,lc8,lc9,lc10, ; lc11,lc12,lc13,lc14,lc15,lc16,lc17,lc18,lc19,lc20
LOCAL lc, lcFile, lnCol, lnCols, lnLine
LOCAL la(1)
FOR lnLine=1 TO PARA()
lc=EVAL('lc'+ALLT(STR(lnLine)))
IF TYPE('lc')='C'
lc=ALLT(lc)
lnCols=ALINE(la,lc,',')
FOR lnCol=1 TO lnCols
lcFile = ALLTRIM(la(lnCol))
IF USED(lcFile)
SELECT (lcFile)
USE
ENDIF
NEXT
ENDIF
NEXT

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

3. Оператор Try … EndTry
Программа или ее часть, которая не прошла тяжелую обкатку можно поместить в Try … EndTry. На Catch’е включаю ERRTRAP. При ошибке юзер за один раз проталкивает программу и не попадает в ошибки – следствия первоначальной, а они могут оказаться в цикле и проталкивать больше 1000 раз многие из моих юзеров не любят.
Со временем Try … EndTry можно и убрать.

4. Файл Errors можно смотреть через Browse, но можно написать свою форму для его просмотра, а вызов ее где-то завуалировать или явно поставить где-нибудь в Top Menu.

5. Ошибки – это хорошо. Только их надо исправлять и думать как в следующий раз таких не допустить. Благодаря ошибкам идет развитие программиста как личности. Начинаешь другим прощать ошибки, становишься лучше. Многие из нас хвастаются ленью. Я, мол, ленивый и, поэтому сразу пишу гениально. Потом оказывается, нашлись еще более гениальные ошибки. Хорошо, если это ошибки MicroSoft и своя гениальность (не путать с генитальностью) вне сомнений. Иначе лучше лениво молчать об этом.
Даже если Вы ленивый гений, подумайте как быстро и проще исправлять ошибки. Ошибку в .prg легко исправить, если его нет в проекте. Все включать в проект, т.е. в ехе не обязательно. Frx вообще в проект лучше не включать. Делайте вызов в виде:
lcPrg=’alfa’
do &lcPrg with …

Alfa.prg не будет автоматически включена в проект и Вы сможете отредактировать ее на месте (у юзера).
На этом подходе мной с коллегами создан Framework, который одновременно является выполняемой программой и средством разработки и отладки. Он позволяет без инсталляции Fox’а у юзера исправлять ошибки и модифицировать и отлаживать программу на месте. Это еще называют «на лету». Конечно, создать свой Framework не так быстро. На первых порах можно просто не включать в проект все подряд.
Имея модемную связь с юзером, можно отсылать ему отдельно изменения в формах, репортах, подпрограммах. Лишь бы их не было в проекте.

5. Вынесите Public – переменные, которые могут со временем меняться в отдельную форму, где юзер при необходимости может их сам исправить.
Некоторые прогмены этого не любят. Мол, пусть юзер знает за что платит. Попросит, тогда и сделаю.
Если программа тиражируется, накладно объезжать всех юзеров, да и надо же любить юзера, а не держать его в напряжении даже если он Вас в напряжении держит.

Заключение.

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

Автор: Юдин А.Ю.

Автор публикации

не в сети 19 лет

Ydin

Комментарии: 0Публикации: 3Регистрация: 16-12-2005
Материалы по теме
Оставить комментарий
//////////////// ///////////////
Авторизация
*
*
Генерация пароля