Кодын чанар

Хөгжүүлэгчдийг өндөр чанартай код бичихэд тусалдаг олон төрлийн хэрэгсэл, арга техникүүд байдаг. Энэхүү лекцээр бид дараах сэдвүүдийг авч үзэх болно:

Нэмэлт сэдэв болгон бид regular expressions буюу regex-ийг авч үзэх бөгөөд энэ нь кодын чанарыг сайжруулах, тухайлбал загварт тохирсон тестүүдийн хэсгийг ажиллуулахад ашиглагдахаас гадна IDE зэрэг бусад хэрэгслүүдэд (жишээлбэл, хайх, солих үед) өргөн хэрэглэгддэг чухал сэдэв юм.

Эдгээр хэрэгслийн ихэнх нь тухайн програмчлалын хэлнээсээ хамаардаг. Жишээлбэл, Python-д зориулсан Ruff линтер/форматжуулагч. Зарим тохиолдолд олон хэлийг дэмждэг хэрэгслүүд ч бий (тухайлбал, Prettier код форматжуулагч). Гэхдээ үндсэн ойлголтууд нь бараг бүх хэлэнд ижил байдаг — та ямар ч програмчлалын хэл дээр код форматжуулагч, линтер, тестийн сан зэргийг олж ашиглах боломжтой.

Форматжуулалт

Код авто-форматжуулагч нь кодын гаднах бүтцийг автоматаар цэгцэлж, үзэмжтэй болгодог. Ингэснээр та илүү гүнзгий бөгөөд хүндрэлтэй асуудлууддаа анхаарлаа хандуулах боломжтой болж, авто-форматжуулагч хэрэгсэл нь тэмдэгт мөрийн хашилтыг нэг стандартад оруулах — жишээ нь, хашилтын зөрүүг арилгах — хоёртын операторуудын эргэн тойронд зай авах (x+y-ийн оронд x + y), import түүхүүдийг эрэмбэлэх, хэт урт мөрүүдээс зайлсхийх зэрэг өдөр тутмын жижиг ажлуудыг хариуцдаг. Код форматжуулагчийн нэг гол давуу тал нь тухайн төсөл дээр ажиллаж буй бүх хөгжүүлэгчдийн кодын хэв маягийг нэг стандартад оруулдагт оршино.

Prettier зэрэг зарим хэрэгслүүд нь маш уян хатан тохируулгатай байдаг; та тохиргооны файлыг төслийнхөө хувилбарын хяналтын систем рүү оруулах хэрэгтэй. Харин Black болон gofmt зэрэг бусад хэрэгслүүд нь хэрэгцээгүй маргааныг (bikeshedding буюу жижиг сажиг зүйлд цаг үрэх) багасгахын тулд тохируулга хийх боломжийг хязгаарласан эсвэл огт байхгүй байдаг.

Код форматжуулагчаа IDE интеграцчилалтай холбож тохируулснаар код бичих явцад эсвэл файлыг хадгалах үед автоматаар форматлагдах боломжтой. Мөн та төсөлдөө EditorConfig файл нэмснээр файл төрөл бүрийн догол мөрийн хэмжээ гэх мэт төслийн түвшний тохиргоог өөрийн IDE-дээ зааж өгөх боломжтой.

Линтинг (Linting)

Линтер нь кодыг ажиллуулахгүйгээр статик шинжилгээ (static analysis) хийж, кодонд байгаа antipattern болон гарч болзошгүй алдааг олж илрүүлдэг. Эдгээр хэрэгсэл нь код форматжуулагчаас илүү гүнзгий ажиллаж, зөвхөн гаднах бүтцээс цааших зүйлийг шалгадаг. Шинжилгээний гүн нь тухайн хэрэгслээс хамаарч өөр өөр байна.

Линтерүүд нь төслийн түвшинд тохируулах боломжтой rules (дүрэм) болон тэдгээрийн бэлэн багцуудтай ирдэг. Зарим линтерийн дүрэм нь алдаагүй кодыг алдаатай гэж андуурах false positive тохиодол байдаг тул та тэдгээрийг файл эсвэл мөр бүрээр нь идэвхгүй болгож болно.

Сайн линтерүүд нь дүрэм бүрийг тайлбарласан тусламж эсвэл баримт бичигтэй байдаг — дүрэм яг юуг шалгаж байгаа, яагаад буруу болох, мөн илүү сайн хувилбар нь юу болохыг заадаг. Жишээлбэл, Python кодон дахь шаардлагагүй давхарласан if нөхцөлүүдийг илрүүлдэг Ruff-ийн SIM102 дүрмийн баримт бичгийг үзэж болно.

Зарим линтерүүд нь зөвхөн асуудлыг анхааруулаад зогсохгүй зарим тодорхой асуудлуудыг автоматаар засаж өгөх боломжтой байдаг.

Тухайн хэлэнд зориулсан линтерээс гадна semgrep хэмээх “семантик grep” хэрэгсэл хэрэг болж магадгүй юм. Энэ нь тэмдэгтийн түвшинд бус (grep шиг), харин AST (Abstract Syntax Tree) түвшинд ажилладаг бөгөөд олон хэлийг дэмждэг. Та semgrep-ийг ашиглан өөрийн төсөлд зориулсан тусгай линтерийн дүрмийг хялбархан бичиж болно. Жишээлбэл, Python дахь аюултай subprocess.Popen(..., shell=True) дуудлагыг хэрэглэхийг хязгаарлахыг хүсвэл дараах тушаалаар уг кодын бүтцийг олж болно:

semgrep -l python -e "subprocess.Popen(..., shell=True, ...)"

Тест хийх (Testing)

Програм хангамжийн тест хийх нь таны бичсэн код зөв ажиллаж байгаа эсэхэд итгэлтэй байдлыг нэмэгдүүлдэг стандарт арга техник юм. Та код бичиж, дараа нь тухайн кодоо ажиллуулан шалгадаг код бичих бөгөөд хэрэв код хүлээгдэж байснаар ажиллахгүй бол алдаа заана.

Та кодыг янз бүрийн түвшинд хуваан тест бичиж болно. Үүнд тусдаа функцүүдийг шалгах нэгж тест (unit tests), модуль эсвэл үйлчилгээнүүдийн хоорондын харилцан үйлчлэлийг шалгах интеграци тест (integration tests), болон эцсийн хэрэглэгчийн цогц хувилбарыг шалгах функциональ тест (functional tests) багтана. Мөн хөгжүүлэлтийн код бичихээсээ өмнө тест бичдэг TDD буюу тестэд суурилсан хөгжүүлэлт хийж болно. Хэрэв та кодноосоо алдаа олвол ирээдүйд уг функц дахин эвдрэхээс сэргийлж регрессийн тест (regression test) бичиж болно. Мөн Haskell хэлний QuickCheck-ээс эхлэлтэй, Python-д зориулсан Hypothesis зэрэг олон санд хэрэгжсэн property-based test-ийг бичиж болно. Тестийн аль аргыг ашиглах нь таны төслөөс хамаарах бөгөөд магадгүй эдгээрийг хослуулан хэрэглэх байх.

Хэрэв таны програм өгөгдлийн сан эсвэл вэб API гэх мэт гадаад хамааралтай бол тест ажиллах үед гуравдагч талын үйлчилгээтэй шууд холбогдохын оронд тэдгээр хамаарлыг орлуулах буюу моклох (mock) нь илүү тохиромжтой байдаг.

Кодын бүрхэц

Code coverage нь таны бичсэн тестүүд хэр сайн болохыг хэмжих үзүүлэлт юм. Энэ нь тестүүд ажиллах үед таны кодын аль мөрүүд ажиллаж байгааг хянаж, кодын бүх хэсгийг шалгаж чадсан эсэхийг баталгаажуулдаг. Code coverage хэрэгслүүд нь тест бичихэд чиглүүлэх зорилгоор мөр мөрөөр шалгасан тайланг харуулж чадна. Codecov зэрэг үйлчилгээнүүд нь төслийн хөгжүүлэлтийн түүхэн дэх code coverage-ийг хянах, харах боломжтой вэб интерфэйсийг олгодог.

Бусад хэмжүүрүүдийн адил кодын бүрхэц нь төгс зүйл биш юм; зөвхөн бүрхэцийн хувьд хэт анхаарахын оронд чанартай тест бичихэд төвлөрөх хэрэгтэй.

Pre-commit Hooks

Git-ийн pre-commit hooks нь pre-commit фрэймворкоор ашиглахад хялбар болсон бөгөөд Git дээр коммит хийх бүрт хэрэглэгчийн заасан кодыг автоматаар ажиллуулдаг. Төслүүдэд коммит хийх бүрийн өмнө форматжуулагч болон линтерийг, заримдаа тестүүдийг автоматаар ажиллуулж, кодын хэв маягийг тохируулах болон тодорхой алдаа байхгүй эсэхийг баталгаажуулахад pre-commit hooks-ийг өргөн ашигладаг.

Тасралтгүй интеграци (CI)

GitHub Actions зэрэг тасралтгүй интеграцийн (CI) үйлчилгээнүүд нь таныг код оруулах болгонд (эсвэл татах хүсэлт үүсгэх бүрт, эсвэл тодорхой хуваарийн дагуу) таны өмнөөс скриптүүдийг ажиллуулж чаддаг. Хөгжүүлэгчид ихэвчлэн форматжуулагч, линтер болон тест гэх мэт кодын чанарын хэрэгслүүдийг ажиллуулахад CI үйлчилгээг ашигладаг. Компиляц хийгддэг хэлний хувьд код хөрвөж байгаа эсэхийг шалгана; статик төрөлт хэлний хувьд төрлүүд зөв байгааг шалгаж болно. Шинэ коммит оруулах бүрт CI-ийг ажиллуулснаар үндсэн код руу алдаа орохоос сэргийлдэг; татах хүсэлт дээр ажилласнаар оролцогчдын оруулсан хувь нэмэр дэх асуудлыг илрүүлдэг; харин тогтсон хуваарийн дагуу ажилласнаар гадаад хамаарал дахь асуудлуудыг илрүүлэх боломжтой. Жишээлбэл, хөгжүүлэгч санамсаргүй байдлаар хувилбарт нийцтэй гэж өөрчлөлт оруулсан ч тэр нь кодыг эвдэх тохиолдолд энэ нь тусална.

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

Ерөнхийдөө CI дээр ажиллаж байгаа скрипт нь таны кодонд шууд өөрчлөлт оруулахгүй: хэрэгслүүдийг “засах” горимоос илүү зөвхөн “шалгах” горимоор ажиллуулах бөгөөд жишээлбэл, код форматжуулсан хэлбэрт нийцэхгүй байвал алдаа зааж дуусдаг.

Репозиториуд нь README файлдаа CI-ийн төлөв болон кодын бүрхэц зэрэг бусад мэдээллийг харуулсан status badges буюу төлөвийн тэмдэг-ийг олонтоо оруулдаг. Жишээлбэл, доор Missing Semester төслийн одоогийн бүтээх төлөвийг харуулав.

Build Status Links Status

Манай холбоос шалгагч нь proof-html GitHub Action-ийг ашигладаг бөгөөд гуравдагч талын вэбсайтуудын асуудлаас болоод олонтоо алдаа заадаг. Гэсэн хэдий ч энэ нь олон эвдэрсэн холбоосыг олж засахад тусалсан (заримдаа бичгийн алдаанаас болж, ихэнхдээ вэбсайтууд агуулгаа шилжүүлэхдээ чиглүүлэлт хийгээгүй эсвэл вэбсайт нь устсанаас болсон байдаг).

CI үйлчилгээ, форматжуулагч, линтер болон тестийн сангуудын онцлогийг сурах хамгийн сайн арга бол жишээн дээр ажиллах юм. GitHub дээрх чанартай нээлттэй эхийн төслүүдийг олж (програмчлалын хэл, чиглэл, хэмжээ, хамрах хүрээгээрээ таны төсөлтэй аль болох ойр байх тусмаа сайн), тэдгээрийн pyproject.toml, .github/workflows/, DEVELOPMENT.md болон бусад холбогдох файлуудыг судлаарай.

Тасралтгүй байршуулалт (Continuous deployment)

Тасралтгүй байршуулалт нь өөрчлөлтүүдийг бодитоор байршуулахад (deploy) CI-ийн дэд бүтцийг ашигладаг. Жишээлбэл, Missing Semester-ийн репозитори нь GitHub Pages руу тасралтгүй байршуулалтыг ашигладаг тул бид лекцийн тэмдэглэлийг git push хийх болгонд вэбсайт автоматаар шинэчлэгдэн байршдаг. Мөн та CI дээр програмын хоёртын файлууд эсвэл үйлчилгээнд зориулсан Docker зургууд зэрэг бусад төрлийн артефактуудыг үүсгэж болно.

Команд ажиллуулагч

just зэрэг команд ажиллуулагчид нь төслийн хүрээнд тушаалуудыг ажиллуулах ажлыг хялбаршуулдаг. Төслийнхөө кодын чанарын дэд бүтцийг хөгжүүлэх явцад хөгжүүлэгчдээрээ uv run ruff check --fix гэх мэт урт тушаалуудыг цээжлүүлэхийг хүсэхгүй байх. Команд ажиллуулагчийг ашигласнаар үүнийг just lint болгон хувиргаж болох бөгөөд үүнтэй адилаар хөгжүүлэгчийн ажиллуулах шаардлагатай бусад хэрэгслүүдэд зориулан just format, just typecheck гэх мэт дуудлагуудыг бэлтгэж болно.

Зарим тухайн хэлэнд зориулсан төсөл эсвэл багц менежерүүд нь ийм боломжийг дотроо агуулдаг тул just шиг хэлнээс хамааралгүй хэрэгслийг ашиглах шаардлагагүй байдаг. Жишээлбэл, Node.js-ийн npm-д зориулсан package.json файлын scripts хэсэг болон Python-ийн Hatch-д зориулсан pyproject.toml файлын tool.hatch.envs.*.scripts хэсэг нь энэ боломжийг дэмждэг.

Тогтмол илэрхийлэл (Regular expressions)

Тогтмол илэрхийлэл буюу “regex” нь тэмдэгт мөрийн олонлогийг илэрхийлэхэд ашиглагддаг хэл юм. Regex загварууд нь командын мөрийн хэрэгслүүд болон IDE зэрэг янз бүрийн орчинд pattern matching хийхэд өргөн хэрэглэгддэг. Жишээлбэл, ag нь код дотроос бүхэлд нь хайлт хийхэд regex-ийг дэмждэг (тухайлбал, ag "import .* as .*" нь Python дахь нэрийг нь өөрчилсөн бүх импортуудыг олно). Мөн go test нь тестүүдээс шүүж ажиллуулахын тулд -run [regexp] сонголтыг дэмждэг. Түүнчлэн, програмчлалын хэлүүд нь regular expression тааруулахад зориулсан суурилуулсан сан эсвэл гуравдагч талын сантай байдаг тул та pattern matching, шалгах, болон задлан шинжлэх зэрэгт regex-ийг ашиглаж болно.

Илүү сайн ойлголт өгөхийн тулд доор зарим regex загваруудын жишээг харуулав. Энэхүү лекцэнд бид Python-ий regex синтаксийг ашиглана. Regex нь дотроо олон төрөлтэй бөгөөд тэдгээрийн хооронд ялангуяа нарийн төвөгтэй функцууд дээр үл ялиг зөрүү байдаг. Тогтмол илэрхийллийг туршиж, алдааг засахын тулд regex101 зэрэг онлайн туршилтын хэрэгслийг ашиглаж болно.

Regex синтакс

Та regex синтаксийн бүрэн хэмжээний гарын авлагыг энэхүү баримт бичгээс (эсвэл онлайнаар авах боломжтой бусад эх сурвалжаас) үзэх боломжтой. Үндсэн барилгын блокуудаас дурдвал:

Бүлэг барих ба холбоос

Хэрэв та regex бүлэг (...)-ийг ашиглавал таарах хэсгийн дэд хэсгийг ялган авах эсвэл хайж солих зорилгоор ашиглаж болно. Жишээлбэл, YYYY-MM-DD форматтай огнооноос зөвхөн сарыг ялгаж авахын тулд дараах Python кодыг ашиглаж болно:

>>> import re
>>> re.match(r"\d{4}-(\d{2})-\d{2}", "2026-01-14").group(1)
'01'

Та өөрийн бичвэр засварлагч дээр хайж солих загварт барьсан бүлгээ холбож ашиглаж болно. Синтакс нь IDE бүрт өөр өөр байж болно. Жишээлбэл, VS Code-д бүлгүүдийг заахдаа $1, $2 гэх мэт хувьсагчдыг ашигладаг бол Vim-д \1, \2 гэх мэтийг ашигладаг.

Хязгаарлалтууд

Тогтмол хэлнүүд нь хүчирхэг боловч хязгаарлагдмал байдаг; стандарт regex-ээр илэрхийлэх боломжгүй тэмдэгт мөрийн ангиллууд байдаг (жишээ нь, {a^n b^n | n ≥ 0} буюу ижил тооны “a” болон “b” үсгээс бүрдэх олонлогийг илэрхийлэх regex бичих боломжгүй байдаг; амьдрал дээр HTML зэрэг хэлнүүд нь тогтмол хэл биш юм). Практикт орчин үеийн regex системүүд нь lookahead болон backreferences зэрэг тогтмол хэлнээс давсан боломжуудыг дэмждэг бөгөөд маш их хэрэг болдог хэдий ч тэдгээрийн илэрхийлэх хүчин чадал нь хязгаартай гэдгийг мэдэх нь чухал юм. Илүү нарийн төвөгтэй хэлнүүдийг задлан шинжлэхийн тулд илүү хүчирхэг задлан шинжлэгч ашиглах шаардлагатай болдог (нэг жишээ нь PEG задлан шинжлэгч болох pyparsing юм).

Regex сурах нь

Бид танд энэ хэлний бүх зүйлийг цээжлэх гэж оролдохын оронд үндсэн ойлголтуудыг (энэ лекцээр үзсэн зүйлс) сураад, хэрэгцээ гарах бүртээ лавлах баримт бичгүүдийг харж ашиглахыг зөвлөж байна.

Харилцан ярианы хиймэл оюун ухааны хэрэгслүүд нь regex загвар үүсгэхэд маш үр дүнтэй тусалж чаддаг. Жишээлбэл, өөрийн дуртай LLM-дээ дараах хүсэлтийг өгөөд үзээрэй:

Write a Python-style regex pattern that matches the requested path from log lines from Nginx. Here is an example log line:

169.254.1.1 - - [09/Jan/2026:21:28:51 +0000] "GET /feed.xml HTTP/2.0" 200 2995 "-" "python-requests/2.32.3"

Дасгалууд

  1. Өөрийн ажиллаж буй төсөлд форматжуулагч, линтер болон pre-commit дэгээнүүдийг тохируулаарай. Хэрэв маш олон алдаа гарвал: форматжуулалттай холбоотой алдаануудыг авто-форматжуулагч засах болно. Линтерийн алдааны хувьд тэдгээрийг засахын тулд хиймэл оюуны агентыг ашиглаж үзээрэй. Хиймэл оюуны агент нь линтерийг ажиллуулж, үр дүнг хянаж чаддаг эсэхийг баталгаажуулж, алдааг бүрэн засах хүртэл давталттай ажиллах боломжтойг бүрдүүлээрэй. Хиймэл оюун таны кодыг эвдээгүй эсэхийг маш сайн шалгах хэрэгтэй!

  2. Өөрийн мэддэг програмчлалын хэл дээр тестийн сан судалж, ажиллаж буй төсөлдөө нэгж тест бичээрэй. Кодын бүрхэц тодорхойлох хэрэгслийг ажиллуулан HTML форматаар тайлан гаргаж, үр дүнтэй танилцаарай. Кодын аль мөрүүд шалгагдсаныг харж чадаж байна уу? Таны кодын бүрхэц магадгүй маш бага байх болно. Түүнийг сайжруулахын тулд зарим тестүүдийг гараар бичиж үзээрэй. Мөн тестийн бүрхэцийг сайжруулахын тулд хиймэл оюуны агентыг ашиглаарай; кодлогч агент нь тестүүдийг бүрхэцийн хамт ажиллуулж, мөр бүрийн бүрхэцийн тайлан гаргаж чаддаг эсэхийг шалгаарай, ингэснээр хаана анхаарлаа хандуулахаа мэдэх болно. Хиймэл оюуны үүсгэсэн тестүүд үнэхээр сайн болж чадсан уу?

  3. Өөрийн ажиллаж буй төсөл дээр push хийх бүрт ажилладаг тасралтгүй интеграцийг тохируулаарай. CI дээр форматжуулалт, линтинг, болон тестүүдийг ажиллуулаарай. Кодоо санаатайгаар эвдэж (жишээ нь, линтерийн дүрэм зөрчсөн код оруулах), CI үүнийг илрүүлж байгаа эсэхийг баталгаажуулаарай.

  4. Тогтмол илэрхийлэл бичиж үзээд, grep командын мөрийн хэрэгслийг ашиглан өөрийн кодонд байгаа subprocess.Popen(..., shell=True) дуудлагуудыг олоорой. Одоо уг regex загвараа “эвдэхийг” оролдоорой. Таны grep хайлтыг хуурч чадсан аюултай кодын бүтцийг semgrep зөв олж чадсаар байна уу?

  5. Эдгээр лекцийн тэмдэглэлд байгаа - Markdown жагсаалтын тэмдэглэгээг * тэмдэглэгээгээр сольж, өөрийн IDE эсвэл бичвэр засварлагч дээр regex хайж солих үйлдлийг дадлагажуулаарай. Файл доторх бүх “-“ тэмдэгтийг шууд сольж болохгүй бөгөөд учир нь тэр тэмдэгтийг жагсаалтын тэмдэглэгээнээс өөр маш олон зорилгоор ашигласан байгааг анхаарна уу.

  6. {"name": "Alyssa P. Hacker", "college": "MIT"} хэлбэрийн JSON бүтцээс нэрийг (энэ жишээнд Alyssa P. Hacker-ийг) барьж авах regex бичээрэй. Санамж: эхний оролдлогоор та Alyssa P. Hacker", "college": "MIT гэсэн утгыг ялгаж авсан regex бичиж магадгүй; үүнийг хэрхэн засахыг мэдэхийн тулд Python-ийн regex баримт бичиг дээрх шунах квантификаторын талаар уншаарай.

    1. Маягтыг/загварыг нэр нь өөрөө " тэмдэгттэй байсан ч (JSON-д давхар хашилтыг \" гэж зайлсхийлгэж escape хийдэг) ажилладаг болгож засаарай.
    2. Бид практикт нарийн төвөгтэй задлан шинжлэх асуудалд тогтмол илэрхийлэл ашиглахыг зөвлөхгүй. Энэ даалгавар өөрийн ашиглаж буй програмчлалын хэлний JSON задлан шинжлэгчийг хэрхэн ашиглахыг олж мэдээрэй. Стандарт оролтоор дээр дурдсан хэлбэрийн JSON бүтцийг аваад, стандарт гаралтанд нэрийг хэвлэдэг командын мөрийн програм бичээрэй. Үүнд танд ердөө хэдхэн мөр код хэрэгтэй болно. Python-д import json-оос гадна ганцхан мөр кодоор үүнийг хялбархан хийж болно.

Энэ хуудсыг засварлах.

Лиценз: CC BY-NC-SA.