Defensive programming

Programming is one of the most difficult branches of applied mathematics.
—Edsger W. Dijkstra
Sometimes the problem is to discover what the problem is.
—Gordon Glegg
Төгс програм гэж байхгүй.
—A programmer

Жишээ: Та зам гарах гэж байна гэж бод. Өмнө тань явган хүний гарц байна, ногоон гэрэл асаж байна, гэвч нэг машин дөхөн ирж явна, ер зогсох шинжгүй, хурдаа саалгүй ойртсоор. Энэ тохиолдолд та машин гарцан дээр ирээд зогсоно гэж итгээд зам хөндлөн гарах уу? эсвэл машин үнэхээр гарцанд тулаад зогсохыг хүлээх үү?

Жишээ: Цайны газар ороод хоол идэхийнхээ өмнө халбага сэрээгээ арчдаг уу? эсвэл үйлчлэгчийн авчирч өгсөн чигээр нь хоолондоо дүрдэг үү? Дэлгүүрээс хүнсний зүйл авахдаа хугацааг нь хардаг уу? шууд сагсандаа хийдэг үү?

Дээрх жишээнүүдээр сэрэмжтэй, хянуур чанарын тухай авч үзэх гэсэн юм. Програм бичихэд ч мөн хянуур сэрэмжтэй байхыг Defensive programming гэдэг нэр томъёогоор илэрхийлдэг. Ингээд Defensive programming -ийг хэрэгжүүлэх тухай авч үзье.

Design by Contract буюу Programming by Contract. Хүмүүсийн харилцааг зохицуулах амаргүй ажиллагааг шийдэхийн тулд гэрээ контракт гэдэг зүйл бий болжээ. Гэрээнд аль аль талын хүлээх үүрэг, эдлэх эрх болоод гэрээгээ зөрчвөл юу болох талаар заавал оруулсан байх учиртай. Гэрээнд гарын үсгээ зурсан л бол болоо-гэрээнд заасан эрхээ эдлээд, хүлээх үүргээ биелүүлээд явахад асуудал үгүй. Аль нэг тал гэрээгээ зөрвчвөл юу болох нь ч тодорхой.

Амласнаасаа илүү ч үгүй, дутуу ч үгүйг хийдэг програмыг сайн програм гэвэл, амласан зүйлыг тусгах гэрээ байх ёстой болно, тодорхой зүйл амлаж байгаа бол тодорхой эдлэх эрхтэй байх нь ч зүй. Аливаа програм гүйцэтгэх ажлаа ямар нэг функц процедураар хэрэгжүүлэх тул гэрээ нь функц дээр хэрэгжих болно. (DBC-гэдэг ойлголтыг анх Bertrand Meyer гэдэг хүн Eiffel хэл дээр хэрэгжүүлжээ. Түүний бичсэн “Object-Oriented Software Construction” гэдэг номыг уншаарай.) DBC-нь дараах 3-н зүйл дээр тулгуурлана:

  • Preconditions. Функц ажиллахаас өмнөх нөхцөл. Шаардлага нь биелээгүй тохиолдолд функц ажиллахгүй. Тухайн функцыг дуудаж байгаа тал өмнөх нөхцөлийг биелүүлсэн байх үүрэгтэй. Тухайлбал параметрүүд зөв байх.
  • Postconditions. Функц юу биелүүлсэн байх ёстойг шалгана. Хэрэв эдгээр нөхцөлүүд биелэхгүй бол гэрээгээ биелүүлээгүйд тооцогдоно.
  • Class invariants. Функц ажиллаж дуусахад хөндөгдөхгүй үлдэх ёстой шинж чанарууд. Тухайлбал классын зарим гишүүн хувьсагчдыг өөрчлөхгүй байх нөхцөл байж болно.

Assertions. Хэрэглэгчийг(функцийг дуудаж байгаа бусад функц, бусад програмчид, эцсийн хэрэглэгчид) ямар нэг зүйлийг хийхгүй гэж тооцоод хэрэглэж болох нүх сүв орхиж ерөөс болохгүй. Хэрэв ямар нэг зүйл хэзээ ч тохиолдох ёсгүй бол түүнийг тохиолдохгүй гэж үзвэл туршлагатай програмчид заавал үнэмшиж батлахыг эрмэлздэг ба үүнд Assertion-ийг хэрэглэдэг. Тухайн нөхцлийг биелэх, эсвэл биелэхгүйг дотроо тооцоод програмаа бичнэ гэдэг нь алдаа гаргахын эхлэл болдог. Дотроо тэгж бодож байгаа бол код дотроо ч оруулж өгөх хэрэгтэй. Гэрээ биелэж байгаа эсэхийг шалгахын тулд Preconditions болон Postconditions дээр Assertion-ийг ашигладаг. Assertion нь хөгжүүлэлтийн үед алдаа хайж дэбагдах цагийг урьчилан сэргийлэх боловч жинхэнэ орчинд Assertion-ийг тэр хэвээр үлдээвэл ажиллагааны хурдад нөлөөлөлх талтай. Иймд бодит орчинд Assertion-ийг тайлбар болгосноор тэр нь кодын баримтжуулалт болох ёстой юм.

Програмчлалын хэл болон Компайлерийн боломжууд. Эдгээрийг бололцооны хирээр ашиглах хэрэгтэй. Тухайлбал Eiffel хэл төрөлх байдлаараа contract гэсэн ухагдахуунтай. Мөн компайлерийнхээ анхааруулгын түвшинг хамгийн хатуу дээр тавьж хөгжүүлэлтийн үед ашиглах нь түгээмэл.

Алдааны код болон Онцгой тохиолдлуудын боловсруулалт. Хөгжүүлэлт хийж байгаа хэлэнд тань Онцгой тохиолдол(Exception) гэсэн ойлголт байдаг бол аль болох боломжит бүх тохиолдлуудыг тооц. Онцгой тохиолдолыг барьж авсан мөртлөө юу ч хийхгүй чимээгүй өнгөрөөх нь амиа хорлож байгаатай ижил гэдгийг ямагт анхаар.(Never do empty catch!) C дээр бол функцыг биелсний дараа алдааны кодыг шалгаж бүх юм хэвийн болохыг үнэмших нь өлзийтэй.

Юу хийж байгаагаа Яагаад хийж байгаатай нь бичих. Кодынхоо тайлбарт юу хийж байгаагаа бичихын сацуу, яагаад гэдгийг оруулж бай. Эхэнд дурдсан гэрээ гэдэг зүйлээ улам батжуулж буй хэрэг. Бусад програмчид кодыг хараад яагаад ингэж байгааг ойлгох юм бол функцыг буруу хэрэглэх нь багасах болно.

::Дүгнэлт::

Defensive programming гэдэг нь нарийн төвөгтэй олон хэсгүүдээс бүтсэн, олон хөгжүүлэгчид оролцсон, зохицуулахад амаргүй нөхцөл байдалд програмыг хийхэд бусад хэсгээс өөрийн кодыг хамгаалах нэг тактик юм. Ингэж чадсанаар хаана ямар хэсэгт буруу байгааг төвөггүйгээр, маргаангүйгээр шууд хэлж чадах болно-мэдээж цаг, хүч хэмнэнэ. Дээр нь хариуцлага тогтоно. Гэвч хэтэрхий Defensive байж бас болохгүй. Хэзээ ч төгс код гэж байдаггүй учраас defensive programming хэрэглэж байгаа ч, нөгөө талаас мөн л төгс код байдаггүй тул хэтэрхий Defensive байж болохгүй-Defensive хэсэг маань өөрөө хэт томорвол алдаатай болох магадлал ихэснэ. Эцэст нь өөрийнхөө кодод ч Defensive хандлагаар хандах хэрэгтэй. Зөв юм хийж байгаадаа итгэлтэй байх сайхан шүү дээ.

Холбоосууд