Як укараніць статычны аналізатар кода ў legacy праект і не дэматываваць каманду

Як укараніць статычны аналізатар кода ў legacy праект і не дэматываваць каманду
Паспрабаваць статычны аналізатар кода лёгка. А вось, каб укараніць яго, асабліва ў распрацоўку вялікага старога праекту, запатрабуецца ўменне. Пры няправільным падыходзе аналізатар можа дадаць працы, запаволіць распрацоўку і дэматываваць каманду. Давайце коратка пагаворым, як правільна падысці да інтэграцыі статычнага аналізу ў працэс распрацоўкі і пачаць яго выкарыстоўваць як частка CI/CD.

Увядзенне

Нядаўна маю ўвагу прыцягнула публікацыя "Getting Started With Static Analysis Without Overwhelming the Team". З аднаго боку, гэта добры артыкул, з якім варта пазнаёміцца. З іншага боку, як мне здаецца, у ім так і не прагучала поўнага адказу, як бязбольна ўкараніць статычны аналіз у праект з вялікай колькасцю legacy кода. У артыкуле гаворыцца, што можна змірыцца з тэхнічным доўгам і працаваць толькі з новым кодам, але няма адказу на тое, што рабіць з гэтым тэхнічным доўгам потым.

Наша каманда PVS-Studio прапануе свой погляд на гэтую тэму. Давайце разгледзім, як наогул узнікае праблема ўкаранення статычнага аналізатара кода, як пераадолець гэтую праблему і як бязбольна паступова ўхіліць тэхнічны абавязак.

Праблематыка

Запусціць і паглядзець, як працуе статычны аналізатар, як правіла, нескладана1]. Можна ўбачыць у кодзе цікавыя памылкі ці нават страшныя патэнцыйныя ўразлівасці. Можна нават нешта паправіць, але далей у многіх праграмістаў апускаюцца рукі.

Усе статычныя аналізатары выдаюць ілжывыя спрацоўванні. Такая асаблівасць метадалогіі статычнага аналізу кода, і з ёй нічога нельга зрабіць. У агульным выпадку гэта невырашальная задача, што пацвярджаецца тэарэмай Райса [2]. Не дапамогуць і алгарытмы машыннага навучання3]. Калі нават чалавек не заўсёды можа сказаць, памылковы той ці іншы код, то ня варта чакаць гэтага ад праграмы :).

Ілжывыя спрацоўванні не з'яўляюцца праблемай, калі статычны аналізатар ужо настроены:

  • Адключаны неактуальныя наборы правіл;
  • Адключаны асобныя неактуальныя дыягностыкі;
  • Калі мы гаворым пра C ці C++, то размечаны макрасы, якія змяшчаюць спецыфічныя канструкцыі, з-за якіх з'яўляюцца бескарысныя папярэджанні ў кожным месцы, дзе такія макрасы выкарыстоўваюцца;
  • Размечаны ўласныя функцыі, якія выконваюць дзеянні аналагічныя сістэмным функцый (свой аналаг memcpy або printf) [4];
  • Кропкава з дапамогай каментароў адключаныя ілжывыя спрацоўванні;
  • І гэтак далей.

У такім выпадку, можна чакаць нізкі ўзровень ілжывых спрацоўванняў на ўзроўні каля 10-15% [5]. Іншымі словамі, 9 з 10 папярэджанняў аналізатара будуць паказваць на рэальную праблему ў кодзе або, прынамсі, на "код з моцным пахам". Пагадзіцеся, такі сцэнар вельмі прыемны, і аналізатар з'яўляецца сапраўдным сябрам праграміста.

Як укараніць статычны аналізатар кода ў legacy праект і не дэматываваць каманду
У рэальнасці ў вялікім праекце першапачатковая карціна будзе зусім іншая. Аналізатар выдае сотні ці тысячы папярэджанняў на legacy код. Што з гэтых папярэджанняў па справе, а што не, хутка зразумець немагчыма. Сесці і пачаць разбірацца з усімі гэтымі папярэджаннямі нерацыянальна, бо асноўная праца ў гэтым выпадку спыніцца на дні ці тыдні. Як правіла, каманда не можа дазволіць сабе такі сцэнар. Таксама ўзнікне вялікая колькасць diff-аў, якія псуюць гісторыю змен. А хуткая масавая праўка такой колькасці фрагментаў у кодзе непазбежна выльецца ў новыя памылкі друку і памылкі.

І самае галоўнае, падобны подзвіг у барацьбе з папярэджаннямі мае мала сэнсу. Пагадзіцеся, што калі праект шмат гадоў паспяхова працуе, то і большасць крытычных памылак у ім ужо выпраўлена. Так, гэтыя выпраўленні былі вельмі дарагімі, прыходзілася адладжвацца, атрымліваць негатыўныя водгукі карыстачоў аб багах і гэтак далей. Статычны аналізатар дапамог бы выправіць многія з гэтых памылак яшчэ на этапе напісання кода, хутка і танна. Але ў дадзены момант, так ці інакш гэтыя памылкі выпраўлены, і аналізатар у асноўным выяўляе некрытычныя памылкі ў старым кодзе. Гэты код можа не выкарыстоўвацца, выкарыстоўвацца вельмі рэдка, і памылка ў ім можа не прыводзіць да заўважных наступстваў. Магчыма, недзе цень ад кнопкі не таго колеру, але карыстацца прадуктам гэта нікому не перашкаджае.

Вядома, нават несур'ёзныя памылкі ўсё роўна застаюцца памылкамі. А часам за памылкай можа хавацца сапраўдная ўразлівасць. Аднак, кінуць усё і днямі/тыднямі займацца дэфектамі, якія слаба выяўляюць сябе, выглядае сумнеўнай ідэяй.

Праграмісты глядзяць, глядзяць, глядзяць на ўсе гэтыя папярэджанні на стары які працуе код… І думаюць: абыйдземся без статычнага аналізу. Пойдзем лепш новы карысны функцыянал пісаць.

Па-свойму, яны маюць рацыю. Яны лічаць, што спачатку яны павінны неяк пазбавіцца ад усіх гэтых папярэджанняў. І толькі тады яны змогуць атрымліваць карысць ад рэгулярнага выкарыстання аналізатара кода. У адваротным выпадку, новыя папярэджанні будуць проста тануць у старых, і на іх ніхто не будзе зважаць.

Тут тая ж аналогія, што і з папярэджаннямі кампілятара. Нездарма рэкамендуюць трымаць колькасць папярэджанняў кампілятара на ўзроўні 0. Калі папярэджанняў 1000, то, калі іх стане 1001, на гэта ніхто не зверне ўвагу, ды і не зразумела, дзе шукаць гэтае самае новае папярэджанне.

Як укараніць статычны аналізатар кода ў legacy праект і не дэматываваць каманду
Самае горшае ў гэтай гісторыі, калі нехта зверху ў гэты момант прымусіць выкарыстоўваць статычны аналіз кода. Гэта толькі дэматывуе каманду, бо з іх пункту гледжання з'явіцца дадатковая бюракратычная складанасць, якая толькі замінае. Справаздачы аналізатара ніхто не будзе глядзець, і ўсё выкарыстанне будзе толькі "на паперы". Г.зн. фармальна аналіз убудаваны ў DevOps працэс, але на практыцы ад гэтага нікому ніякай карысці няма. Мы чулі падрабязныя гісторыі пры зносінах на стэндах ад наведвальнікаў канферэнцый. Падобны досвед можа надоўга, калі не на заўсёды, адбіць жаданне ў праграмістаў звязвацца з прыладамі статычнага аналізу.

Укараненне і ўстараненне тэхнічнага абавязку

Насамрэч, няма нічога складанага і страшнага ва ўкараненні статычнага аналізу нават у вялікі стары праект.

CI / CD

Прычым аналізатар можна адразу зрабіць часткай працэсу бесперапыннай распрацоўкі. Напрыклад, у дыстрыбутыве PVS-Studio ёсць утыліты для зручнага прагляду справаздачы ў патрэбным вам фармаце, і апавяшчэння распрацоўнікаў, якія напісалі праблемныя ўчасткі кода. Тым, хто больш падрабязна цікавіцца запускам PVS-Studio з-пад CI/CD сістэм, рэкамендую азнаёміцца ​​з адпаведным раздзелам дакументацыі і цыклам артыкулаў:

Але вернемся да пытання вялікай колькасці ілжывых спрацоўванняў на першых этапах укаранення прылад аналізу кода.

Фіксацыя існуючага тэхнічнага абавязку і праца з новымі папярэджаннямі

Сучасныя камерцыйныя статычныя аналізатары дазваляюць вывучаць толькі новыя папярэджанні, якія з'яўляюцца ў новым ці змененым кодзе. Рэалізацыі гэтага механізму адрозніваецца, але сутнасць адна. У статычным аналізатары PVS-Studio гэтая функцыянальнасць рэалізавана наступным чынам.

Каб хутка пачаць выкарыстоўваць статычны аналіз, мы прапануем карыстальнікам PVS-Studio скарыстацца механізмам масавага падаўлення папярэджанняў [6]. Агульная ідэя ў наступным. Карыстальнік запусціў аналізатар і атрымаў мноства папярэджанняў. Калі праект, які распрацоўваецца шмат гадоў, жывы, развіваецца і прыносіць грошы, то, хутчэй за ўсё, у справаздачы не будзе шмат папярэджанняў, якія паказваюць на крытычныя дэфекты. Іншымі словамі, крытычныя багі так ці інакш ужо папраўленыя даражэйшымі спосабамі або дзякуючы фідбэку ад кліентаў. Адпаведна, усё, што зараз знаходзіць аналізатар, можна лічыць тэхнічным абавязкам, які непрактычна імкнуцца ўхіліць адразу.

Можна паказаць PVS-Studio лічыць гэтыя папярэджанні пакуль неактуальнымі (адкласці тэхнічны абавязак на потым), і ён больш не будзе іх паказваць. Аналізатар стварае спецыяльны файл, дзе захоўвае інфармацыю аб пакуль нецікавых памылках. І зараз PVS-Studio будзе выдаваць папярэджанні толькі на новы ці зменены код. Прычым, усё гэта рэалізавана разумна. Калі, напрыклад, у пачатак файла з зыходным кодам будзе дададзены пусты радок, то аналізатар разумее, што, у сутнасці, нічога не змянілася, і па-ранейшаму будзе маўчаць. Гэты файл разметкі можна закласці ў сістэму кантролю версій. Файл вялікі, але гэта не страшна, бо часта яго закладваць няма сэнсу.

Цяпер усе праграмісты будуць бачыць папярэджанні, якія адносяцца толькі да новага або змененага кода. Такім чынам, аналізатар можна пачаць выкарыстоўваць, што завецца, са наступнага дня. А да тэхнічнага абавязку можна будзе вярнуцца пазней, і паступова выпраўляць памылкі і настройваць аналізатар.

Такім чынам, першая праблема, з укараненнем аналізатара ў вялікі стары праект вырашана. Цяпер давайце разбярэмся, што рабіць з тэхнічным доўгам.

Выпраўленне памылак і рэфакторынг

Самае простае і натуральнае - гэта вылучыць некаторы час на разбор масава прыгнечаных папярэджанняў аналізатара і паступова разбірацца з імі. Дзесьці варта выправіць памылкі ў кодзе, дзесьці правесці рэфактарынг, каб падказаць аналізатару, што код не з'яўляецца праблемным. Просты прыклад:

if (a = b)

На падобны код лаецца большасць З++ кампілятараў і аналізатараў, бо высокая верагоднасць, што насамрэч жадалі напісаць (a == b). Але існуе сакрэтная дамова, і гэта звычайна адзначана ў дакументацыі, што калі стаяць дадатковыя дужкі, то лічыцца, што праграміст свядома напісаў такі код, і лаяцца не трэба. Напрыклад, у дакументацыі PVS-Studio да дыягностыкі V559 (CWE-481) відавочна напісана, што наступны радок будзе лічыцца карэктным і бяспечным:

if ((a = b))

Іншы прыклад. Ці забыты ў гэтым C++ кодзе перапынак ці не?

case A:
  foo();
case B:
  bar();
  break;

Аналізатар PVS-Studio выдасць тут папярэджанне V796 (CWE-484). Магчыма, гэта не памылка, і тады трэба даць аналізатару падказку, дадаўшы атрыбут. [[fallthrough]] ці, напрыклад, __attribute__((fallthrough)):

case A:
  foo();
  [[fallthrough]];
case B:
  bar();
  break;

Можна сказаць, што падобныя змены кода не выпраўляюць памылкі. Так, гэта так, але выконваецца два карысныя дзеянні. Па-першае, справаздача аналізатара пазбаўляецца ад ілжывых спрацоўванняў. Па-другое, код становіцца больш зразумелым для людзей, якія займаюцца яго суправаджэннем. І гэта вельмі важна! Дзеля аднаго гэтага ўжо варта праводзіць дробны рэфактарынг, каб код стаў больш зразумелым і лягчэй у суправаджэнні. Раз аналізатару незразумела, патрэбен "break" ці не, гэта будзе незразумела і калегам-праграмістам.

Апроч выпраўлення памылак і рэфактарынгу, можна кропкава душыць відавочна ілжывыя папярэджанні аналізатара. Нейкія неактуальныя дыягностыкі можна адключыць. Напрыклад, нехта лічыць бессэнсоўнымі папярэджанні V550 аб параўнанні значэнняў тыпу float/double. А нехта адносіць іх да важных і годных вывучэння [7]. Якія папярэджанні лічыць актуальнымі, а якім не, вырашаць толькі камандзе распрацоўшчыкаў.

Існуюць і іншыя спосабы прыгнечання ілжывых папярэджанняў. Напрыклад, раней ужо згадвалася разметка макрасаў. Усё гэта падрабязней апісана ў дакументацыі. Самае галоўнае - разумець, што калі паступова і сістэматычна падысці да працы з ілжывымі спрацоўваннямі, нічога страшнага ў іх няма. Пераважная большасць нецікавых папярэджанняў знікае пасля наладкі, і застаюцца толькі месцы, якія сапраўды патрабуюць уважлівага вывучэння і нейкіх змен у кодзе.

Таксама, мы заўсёды дапамагаем нашым кліентам наладзіць PVS-Studio, калі ўзнікаюць нейкія складанасці. Больш таго, былі выпадкі, калі мы самі ўхілялі ілжывыя папярэджанні і выпраўлялі памылкі [8]. На ўсялякі выпадак вырашыў прыгадаць, што магчымы і такі варыянт пашыранага супрацоўніцтва :).

Метад храпавік

Ёсць і іншы цікавы падыход да таго, каб паступова паляпшаць якасць кода, ухіляючы папярэджанне статычнага аналізатара. Сутнасць у тым, што колькасць папярэджанняў можа толькі змяншацца.

Як укараніць статычны аналізатар кода ў legacy праект і не дэматываваць каманду

Фіксуецца колькасць папярэджанняў, якія выдае статычны аналізатар. Quality gate наладжваецца такім чынам, што зараз можна закласці толькі такі код, які не павялічвае колькасць спрацоўванняў. У выніку запускаецца працэс паступовага памяншэння колькасці спрацоўванняў за кошт наладкі аналізатара і праўкі памылак.

Нават калі чалавек захоча крыху схітрыць і вырашыць прайсці quality gate не дзякуючы ўхіленню папярэджанняў у яго новым кодзе, а за кошт паляпшэння старога старонняга кода, гэта нястрашна. Усё роўна храпавік пракручваецца ў адзін бок, і паступова колькасць дэфектаў будзе памяншацца. Нават калі чалавек не хочацца кіраваць свае ўласныя новыя дэфекты, яму ўсё роўна давядзецца нешта палепшыць у суседнім кодзе. У нейкі момант лёгкія спосабы памяншэння колькасці папярэджанняў заканчваюцца, і надыходзіць момант, калі будуць выпраўляцца сапраўдныя памылкі.

Больш падрабязна гэта метадалогія апісана ў вельмі цікавым артыкуле Івана Панамарова.Укараняйце статычны аналіз у працэс, а не шукайце з яго дапамогай багі", З якой я рэкамендую азнаёміцца ​​кожнаму, хто цікавіцца пытаннямі павышэння якасці кода."

У аўтара артыкула ёсць і даклад на гэтую тэму: "Бесперапынны статычны аналіз".

Заключэнне

Спадзяюся, пасля гэтага артыкула чытачы будуць прыязней успрымаць інструменты статычнага аналізу і захочуць укараніць іх у працэс распрацоўкі. Калі ў вас засталіся пытанні, мы заўсёды гатовы пракансультаваць карыстальнікаў нашага статычнага аналізатара PVS-Studio і дапамагчы з яго укараненнем.

Існуюць і іншыя тыпавыя сумневы, ці зможа статычны аналіз сапраўды быць зручны і карысны. Я пастараўся развеяць большасць такіх сумневаў у публікацыі "Прычыны ўкараніць у працэс распрацоўкі статычны аналізатар кода PVS-Studio".9].

Дзякуй за ўвагу, і прыходзьце спампаваць і паспрабаваць аналізатар PVS-Studio.

Дадатковыя спасылкі

  1. Андрэй Карпаў. Як хутка паглядзець цікавыя папярэджанні, якія выдае аналізатар PVS-Studio для C і C++ кода?
  2. Wikipedia. Тэарэма Райса.
  3. Андрэй Карпаў, Вікторыя Ханіева. Выкарыстанне машыннага навучання ў статычным аналізе зыходнага кода праграм.
  4. PVS-Studio. Дакументацыя. Дадатковая настройка дыягностык.
  5. Андрэй Карпаў. Характарыстыкі аналізатара PVS-Studio на прыкладзе EFL Core Libraries, 10-15% ілжывых спрацоўванняў.
  6. PVS-Studio. Дакументацыя. Масавае прыгнечанне паведамленняў аналізатара.
  7. Іван Андрэшын. Пра тое, як мы апрабавалі статычны аналіз на сваім праекце навучальнага сімулятара рэнтгенэндаваскулярнай хірургіі.
  8. Павел Ерамееў, Святаслаў Размыслаў. Як каманда PVS-Studio палепшыла код Unreal Engine.
  9. Андрэй Карпаў. Прычыны ўкараніць у працэс распрацоўкі статычны аналізатар кода PVS-Studio.

Як укараніць статычны аналізатар кода ў legacy праект і не дэматываваць каманду

Калі хочаце падзяліцца гэтым артыкулам з англамоўнай аўдыторыяй, то прашу выкарыстаць спасылку на пераклад: Andrey Karpov. How to introduce static code analyzer ў legacy project and no to discourage the team.

Крыніца: habr.com

Дадаць каментар