Обработка на грешки – кратка история
Обработката на грешки (error handling) става особено популярна с появата на първите програмни езици от високо ниво. Началото е поставено през 60-те години на ХХ век с езика BASIC. Преди появата на езиците от високо ниво за разработка са се използвали директно машинни кодове или асемблерни езици. И в двата случая обработка на грешки по време на изпълнение въобще не се е извършвала. Операторът е разбирал, че програмата му не работи вярно едва след като тя е приключила и той прегледа изходния листинг.
С развитието на изчислителната техника нуждата от по-стриктен контрол при управлението на хардуера е предизвикала създаването на по-съвършени средства за програмиране. Езиците от високо ниво добавят още едно ниво на абстракция в комуникацията между машините и хората. Все по-актуален става въпросът “Какво правим, когато се случи нещо непредвидено, докато програмата ни все още се изпълнява?”. А животът ни предлага непредвидени неща във всеки един момент, точно както се е появила онази буболечка, довела до появата на понятието “bug” в професионалния жаргон на програмистите. Разбира се, насекомите отдавна са само в историята на изчислителната техника, като са отстъпили място на събития от следния вид: недостатъчно памет, неправомерен достъп до входно/изходни устройства, погрешно приета информация по зашумен канал и т.н.
Относително голямата несигурност, при която се изпълняват програмите, логично довежда до развиване на средствата за борба с непредвидени ситуации. Първите средства за тази цел се появяват в ранните версии на езика BASIC, където програмите са писани, като всеки ред е имал уникален номер, а пътят за изпълнение на програмата се е контролирал от GOTO оператор, който е бил единственото средство за предаване на управлението на ред с посочен номер. При работата в тази среда единствената възможност за обработка на грешки, възникнали в процеса на изпълнение, е било декларирането на целочислена променлива errorcode, чието съдържание е отразявало актуалното състояние на програмата. Този подход води до създаването на програми, изглеждащи по следния начин:
1010 LET DATA = INPUTFILE
1020 CALL DATA_PROCESSING_FUNCTION
1030 IF NOT ERRORCODE = 0 GOTO 5000
1040 CALL ANOTHER_FUNCTION
1050 IF NOT ERRORCODE = 0 GOTO 5000
1060 REM CONTINUE PROCESSING LIKE THIS
...
5000 IF ERRORCODE = 1 GOTO 5100
5010 IF ERRORCODE = 2 GOTO 5200
5020 REM MORE IF STATEMENTS
...
5100 REM HANDLE ERROR CODE 1 HERE
...
5200 REM HANDLE ERROR CODE 2 HERE
Както можем да забележим, повече от половината код е предназначен за обработката на грешки. С времето езикът е претърпял развитие и част от кода за обработка на грешки е прехвърлена като отговорност на интерпретатора, както следва:
1010 LET DATA = INPUTFILE
1020 ON ERROR GOTO 5000
1030 CALL DATA_PROCESSING_FUNCTION
1040 CALL ANOTHER_FUNCTION
...
5000 IF ERRORCODE = 1 GOTO 5100
5010 IF ERRORCODE = 2 GOTO 5200
Това е позволило на една-единствена линия да се маркира мястото, на което може да възникне грешка, присвоявайки стойност на променливата errorcode. Въпреки че след това грешката отново трябва да бъде анализирана с цел определянето на точния й вид, това води до значително улесняване при писането и четенето на програмни текстове.
Както логично можем да предположим, Visual Basic, дори в последните си версии, предлага аналогичен начин за обработка на изключителните ситуации, въпреки че номерирането на редовете е отпаднало и е било заменено с по-лесните за разчитане етикети. Примерно във VBScript имаме възможност да обработим грешките локално или да ги игнорираме изцяло:
On Error GoTo 0 ' 0 implies go nowhere
SomeFunction()
SomeOtherFunction()
....
Или:
On Error Resume Next
SomeFunction()
If Err.Number = 42 Then
' handle the error here
SomeOtherFunction()
...
Употребата на променливи, като индикатор за типа на грешката и прекъсване на нормалното изпълнение на програмата, води до някои много сериозни проблеми, като освобождаване на заделени ресурси, невъзможност за връщане към нормалния път за изпълнение на програмата и т.н. Всички тези усложнения налагат въвеждането на механизъм за обработка на изключителни ситуации (exception handling) като стандартна част от съвременните езици за програмиране. В повечето езици синтактично конструкцията е представена от try-catch блокове. Примерно в Java:
try
{
out = new FileOutputStream( "myfile.txt" );
p = new PrintStream( out );
p.println("This is written to a file");
p.close();
}
catch (Exception e)
{
System.err.println( "Error writing to file" );
}
Основните предимства на този метод са, както следва: 1) отделяне на работната логика от кода за обработка на изключителни ситуации, което позволява писането на много по-добре структуриран код; 2) предаване на грешката на по-горни нива в йерархията за извикване на функции; 3) групиране на различните видове грешки, включително под формата на йерархия от класове; 4) изпълнението на програмата продължава непосредствено след защитения блок.
Любопитно е в каква посока ще се развият средствата за предпазване от грешки както по време на изпълнение, така и по време на компилация. В практиката все по-често се налага високо качество на програмния текст и по-адекватно поведение на програмните продукти, дори в ситуации, които е трудно да се предвидят през етапите на разработка. За постигането на тези цели са необходими добро познаване на средствата за предпазване от програмни грешки и правилното им съчетаване със система за логове (logging). Винаги трябва да се има предвид, че високото качество води до по-високи печалби.
Тодор Балабанов
teodorgig@mail.ru
Информационни източници:
1. Alan Gauld. Handling Errors, http://www.freenetpages.co.uk/hp/alan.gauld/tutor2/tuterrors.htm
2. Advantages of Exceptions, http://java.sun.com/docs/books/tutorial/essential/exceptions/advantages.html
Последни коментари
GbCAFadEPbdZPkX
ubbkynECWuFeOvIj
hEzLOAktNJWa
ttoLurraNC
IHEEcZdznG
vFaxEaDKAlMf
ksEyLfQSPG
iKEzeuFkLdwHFMwudyV
XLpwzWgYzdQK
Добави коментар
Ако желаете да добавите коментар моля влезте, използвайки формата вляво.Ако не сте регистрирани това може да направите тук!
GchrxVjTaQBRSCTbrA