{"id":32848,"date":"2019-10-31T21:49:16","date_gmt":"2019-10-31T18:49:16","guid":{"rendered":"https:\/\/prohoster.info\/blog\/vnedryajte-staticheskij-analiz-v-protsess-a-ne-ishhite-s-ego-pomoshhyu-bagi\/"},"modified":"2019-10-31T21:49:16","modified_gmt":"2019-10-31T18:49:16","slug":"vnedryajte-staticheskij-analiz-v-protsess-a-ne-ishhite-s-ego-pomoshhyu-bagi","status":"publish","type":"post","link":"https:\/\/prohoster.info\/sl\/blog\/administrirovanie\/vnedryajte-staticheskij-analiz-v-protsess-a-ne-ishhite-s-ego-pomoshhyu-bagi","title":{"rendered":"Vklju\u010dite stati\u010dno analizo v proces, namesto da s pomo\u010djo le-te i\u0161\u010dete napake","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Pisanje tega \u010dlanka me je spodbudilo veliko \u0161tevilo gradiv o stati\u010dni analizi, ki so vse pogosteje pri\u0161la v o\u010di. Najprej je to <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/en\/company\/pvs-studio\/blog\/\">blog PVS-studio<\/a><\/noindex>, ki se aktivno promovira na Habu z pregledi napak, ki jih je njihov instrument na\u0161el v projektih z odprto kodo. Nedavno je PVS-studio uvedel <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/en\/company\/pvs-studio\/blog\/436496\/\">podporo za Javo<\/a><\/noindex>, in seveda razvijalci IntelliJ IDEA, \u010digar vgrajeni analitik je danes verjetno najbolj napreden za Javo, <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/en\/company\/JetBrains\/blog\/436278\/\">ne bi mogli ostati ob strani<\/a><\/noindex>. <\/p>\n<p>Ob branju takih pregledov se zdi, da gre za \u010darobni napoj: pritisni gumb in tukaj je \u2014 seznam napak pred o\u010dmi. Zdi se, da se bo ob izbolj\u0161evanju analitikov te\u017eav odkrilo vedno ve\u010d, in izdelki, ki jih skenirajo ti roboti, se bodo izbolj\u0161ali, brez kakr\u0161nega koli truda z na\u0161e strani.<\/p>\n<p>Toda \u010darobnih napojov ni. Rad bi govoril o tem, o \u010demer obi\u010dajno ne govorijo v objavah vrste \u201ekaj vse lahko na\u0161 robot najde\u201c: \u010desa analitiki nikoli ne morejo, kak\u0161na je njihova resni\u010dna vloga in mesto v procesu dobave programske opreme, ter kako jih pravilno uvajati.<\/p>\n<p><img decoding=\"async\" alt=\"Vklju\u010dite stati\u010dno analizo v proces, namesto da s pomo\u010djo le-te i\u0161\u010dete napake\" src=\"\/wp-content\/uploads\/2019\/05\/2a0339f10edcaed3310676ab6e2f975a.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Zobnik (vir: <noindex><a rel=\"nofollow\" href=\"https:\/\/ru.wikipedia.org\/wiki\/%D0%A5%D1%80%D0%B0%D0%BF%D0%BE%D0%B2%D0%BE%D0%B9_%D0%BC%D0%B5%D1%85%D0%B0%D0%BD%D0%B8%D0%B7%D0%BC#\/media\/File:Sperrklinke_Schema.svg\">wikipedia<\/a><\/noindex>).<\/i><br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h2>\u010cesa stati\u010dni analitiki nikoli ne morejo storiti<\/h2>\n<p>\nKaj prakti\u010dno pomeni analiza izvorne kode? Vnosimo dolo\u010dene izvorne kode in na izhodu v kratkem \u010dasu (znatno kraj\u0161em od izvajanja testov) dobimo dolo\u010dene podatke o na\u0161em sistemu. Temeljna in matemati\u010dno nepreklicna ovira je, da lahko na ta na\u010din pridobimo le ozko skupino informacij.<\/p>\n<p>Najbolj znan primer problema, ki se ne more re\u0161iti z uporabo stati\u010dne analize \u2014 <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Halting_problem\">problem ustavitve<\/a><\/noindex>: to je teorema, ki dokazuje, da ni mo\u017eno razviti splo\u0161nega algoritma, ki bi na podlagi izvorne kode programa dolo\u010dil, ali bo ta zanikala ali se kon\u010dala v kon\u010dnem \u010dasu. Raz\u0161iritev te teoreme je <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Rice%27s_theorem\">Riceova teorema<\/a><\/noindex>, ki potrjuje, da je za kakr\u0161no koli netrivijalno lastnost izra\u010dunljivih funkcij dolo\u010ditev, ali poljubni program izra\u010duna funkcijo s to lastnostjo, algoritemsko nere\u0161ljiv problem. Na primer, nemogo\u010de je napisati analitik, ki bo po katerem koli izvorno kodo dolo\u010dil, ali analizirani program implementira algoritem, ki izra\u010duna, recimo, kvadrat celo \u0161tevilo.<\/p>\n<p>Tako ima funkcionalnost stati\u010dnih analizatorjev nepremagljive omejitve. Statisti\u010dni analizator nikoli ne bo mogel v vseh primerih dolo\u010diti takih stvari, kot so na primer pojav \u00abnull pointer exception\u00bb v jezikih, ki dopu\u0161\u010dajo vrednost null, ali v vseh primerih dolo\u010diti pojav \u00abattribute not found\u00bb v jezikih z dinami\u010dno tipizacijo. Vse, kar lahko najpopolnej\u0161i stati\u010dni analizator naredi, je izlo\u010danje posebnih primerov, katerih \u0161tevilo med vsemi mo\u017enimi te\u017eavami z va\u0161o izvorno kodo je, brez pretiravanja, kaplja v morju.<\/p>\n<h2>Stati\u010dna analiza ni iskanje napak.<\/h2>\n<p>\nIz zgoraj navedenega sledi sklep: stati\u010dna analiza ni sredstvo za zmanj\u0161anje \u0161tevila napak v programu. Tvegano trdim: ob prvem uvajanju v va\u0161 projekt bo na\u0161el v kodi 'zanimiva' mesta, vendar najverjetneje ne bo na\u0161el nobenih napak, ki vplivajo na kakovost delovanja va\u0161ega programa.<\/p>\n<p>Primeri napak, ki jih avtomatsko najdejo analizatorji, so impresivni, vendar ne smemo pozabiti, da so ti primeri najdeni s skeniranjem velikega nabora velikih kodnih baz. Na enak na\u010din hekerji, ki imajo mo\u017enost preizkusiti nekaj preprostih gesel na \u0161tevilnih ra\u010dunih, na koncu najdejo ra\u010dune, kjer je enostavno geslo.<\/p>\n<p>Ali to pomeni, da stati\u010dne analize ni treba izvajati? Seveda ne! In ravno iz istega razloga, zakaj je vredno preverjati vsako novo geslo, da ne pade na seznam 'preprostih' gesel.<\/p>\n<h2>Stati\u010dna analiza je ve\u010d kot iskanje napak.<\/h2>\n<p>\nV resnici so naloge, ki jih lahko analizira, bistveno \u0161ir\u0161e. Kajti na splo\u0161no, stati\u010dna analiza je vsakr\u0161na preveritev izvornih kod, opravljena pred njihovim zagonom. Tukaj je nekaj stvari, ki jih lahko po\u010dnete:<\/p>\n<ul>\n<li> Preverjanje sloga kodiranja v \u0161ir\u0161em pomenu te besede. To vklju\u010duje tako preverjanje oblikovanja kot iskanje uporabe praznih\/nepotrebnih oklepajev, nastavitev pragu meril, kot so \u0161tevilo vrstic \/ ciklomati\u010dna kompleksnost metode itd. \u2014 vse, kar lahko ote\u017ei berljivost in vzdr\u017eevanje kode. V Javi je tak instrument Checkstyle, v Pythu pa flake8. Programi te vrste se obi\u010dajno imenujejo \u201elinters\u201c.<\/li>\n<li>Analizi je lahko podvr\u017een ne samo izvr\u0161ni koda. Datoteke virov, kot so JSON, YAML, XML, .properties, lahko (in morajo!) biti samodejno preverjene na veljavnost. Saj je bolje izvedeti, da je z neparnimi narekovaji po\u0161kodovana struktura JSON v zgodnji fazi samodejnega preverjanja Pull Request, kot pa pri izvajanju testov ali v \u010dasu izvajanja? Ustrezna orodja so na voljo: na primer, <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/adrienverge\/yamllint\">YAMLlint<\/a><\/noindex>, <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/zaach\/jsonlint\">JSONLint<\/a><\/noindex>.<\/li>\n<li> Kompilacija (ali analiza za dinami\u010dne programske jezike) je tudi oblika stati\u010dne analize. Obi\u010dajno lahko prevajalniki dajejo opozorila, ki signalizirajo te\u017eave s kakovostjo izvorne kode, katerih ne smemo ignorirati.<\/li>\n<li>V\u010dasih kompilacija ni le kompilacija izvr\u0161nega kode. Na primer, \u010de imate dokumentacijo v formatu <noindex><a rel=\"nofollow\" href=\"https:\/\/asciidoctor.org\/\">AsciiDoctor<\/a><\/noindex>, se ob pretvorbi v HTML\/PDF lahko obdelovalec AsciiDoctor (<noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/asciidoctor\/asciidoctor-maven-plugin\">Maven plugin<\/a><\/noindex>) izdaja opozorila, na primer o po\u0161kodovanih notranjih povezavah. In to je pomemben razlog, da ne sprejmete Pull Request s spremembami dokumentacije.<\/li>\n<li>Preverjanje pravopisa je prav tako oblika stati\u010dne analize. Orodje <noindex><a rel=\"nofollow\" href=\"http:\/\/aspell.net\/\">aspell<\/a><\/noindex> lahko preverja pravopis ne le v dokumentaciji, temve\u010d tudi v izvornih kodah programov (v komentarjih in literatih) v razli\u010dnih programskih jezikih, vklju\u010dno s C\/C++, Javom in Pythonom. Napaka v pravopisu v uporabni\u0161kem vmesniku ali dokumentaciji je tudi napaka!<\/li>\n<li>Konfiguracijski testi (o tem, kaj to je \u2014 glej <noindex><a rel=\"nofollow\" href=\"https:\/\/www.youtube.com\/watch?v=KaeEjsAjV6A&amp;index=30&amp;list=PLsVTVVvrKX9tuYyCtL8mASB6IOaa-kRCA&amp;t=0s\">ta<\/a><\/noindex> in <noindex><a rel=\"nofollow\" href=\"https:\/\/www.youtube.com\/watch?v=Tk_nmV-mWOA\">ta<\/a><\/noindex> poro\u010dila), \u010deprav se izvajajo v okolju izvajanja enotnih testov, kot je pytest, so pravzaprav tudi vrsta stati\u010dne analize, saj ne izvajajo izvorne kode med svojim izvajanjem.<\/li>\n<\/ul>\n<p>\nKot vidimo, iskanje napak na tem seznamu zaseda manj pomembno vlogo, vse ostalo pa je dostopno z uporabo brezpla\u010dnih odprtokodnih orodij.<\/p>\n<p>Kateri od teh vrst stati\u010dne analize bi morali uporabljati v va\u0161em projektu? Seveda, vse, ve\u010d je bolje! Najpomembnej\u0161e je, da to pravilno implementirate, o \u010demer bomo govorili naprej.<\/p>\n<h2>Dobavna cev kot ve\u010dstopenjski filter in stati\u010dna analiza kot njen prvi kaskad.<\/h2>\n<p>\nKlasi\u010dna metafora neprekinjene integracije je cevovod (pipeline), po katerem potekajo spremembe \u2014 od spremembe izvorne kode do dobave v produkcijo. Standardni zaporedni koraki tega cevovoda izgledajo tako:<\/p>\n<ol>\n<li>stati\u010dna analiza<\/li>\n<li>kompilacija<\/li>\n<li>enotni testi<\/li>\n<li>integracijski testi<\/li>\n<li>UI testi<\/li>\n<li>ro\u010dna preverjanja<\/li>\n<\/ol>\n<p>\nSpremembe, ki so bile zavrnjene na N-tem koraku cevovoda, ne preidejo na korak N+1.<\/p>\n<p>Zakaj tako, in ne druga\u010de? V tistem delu cevovoda, ki se nana\u0161a na testiranje, testerji spoznajo \u0161iroko znano piramido testiranja.<\/p>\n<p><img decoding=\"async\" alt=\"Vklju\u010dite stati\u010dno analizo v proces, namesto da s pomo\u010djo le-te i\u0161\u010dete napake\" src=\"\/wp-content\/uploads\/2019\/05\/f155307fd4c1663800843c394098ea6f.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Testna piramida. Vir: <noindex><a rel=\"nofollow\" href=\"https:\/\/martinfowler.com\/bliki\/TestPyramid.html\">\u010dlanek<\/a><\/noindex> Martin Fowler.<\/i><\/p>\n<p>Na dnu te piramide so testi, ki jih je la\u017eje pisati, ki se hitro izvajajo in nimajo tendence k la\u017enim pozitivnim rezultatom. Zato bi jih moralo biti ve\u010d, pokrivati bi morali ve\u010d kode in se izvajati najprej. Na vrhu piramide pa je situacija nasprotna, zato se mora \u0161tevilo integracijskih in UI testov zmanj\u0161ati na nujno minimalno. \u010clovek v tej verigi je najdra\u017eji, najpo\u010dasnej\u0161i in najmanj zanesljiv vir, zato je na samem koncu in opravlja delo le, \u010de prej\u0161nji koraki niso odkrili nobenih napak. Vendar pa po istih principih deluje cevovod tudi v delih, ki niso neposredno povezani s testiranjem!<\/p>\n<p>Rad bi predlagal analogijo v obliki ve\u010dstopenjskega sistema filtracije vode. Na vhod prite\u010de umazana voda (spremembe z napakami), na izhodu pa moramo dobiti \u010disto vodo, v kateri so odstranjenje vse ne\u017eelene onesna\u017eevalce.<\/p>\n<p><img decoding=\"async\" alt=\"Vklju\u010dite stati\u010dno analizo v proces, namesto da s pomo\u010djo le-te i\u0161\u010dete napake\" src=\"\/wp-content\/uploads\/2019\/05\/76b5be8f13d55c16970d67e09767a045.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Ve\u010dstopenjski filter. Vir: <noindex><a rel=\"nofollow\" href=\"https:\/\/commons.wikimedia.org\/wiki\/File:Milli-Q_Water_filtration_station.JPG\">Wikimedia Commons.<\/a><\/noindex><\/i><\/p>\n<p>Kot je znano, se \u010distilni filtri zasnovajo tako, da lahko vsak naslednji kaskad filtrira vedno manj\u0161e delce onesna\u017eeval. Ob tem imajo kaskade bolj grobe filtracije ve\u010djo propustnost in ni\u017eje stro\u0161ke. V na\u0161i analogiji to pomeni, da vhodna kvalitetna vrata zagotavljajo ve\u010djo hitrost delovanja, zahtevajo manj napora za zagon in so same po sebi manj zahtevne za delovanje \u2014 in ravno v tej zaporedju so zasnovane. Vloga stati\u010dne analize, ki, kot zdaj razumemo, lahko zajame le najbolj grobe napake \u2014 je vloga mre\u017ee '\u010distilca' na samem za\u010detku kaskade filtrov.<\/p>\n<p>Sama stati\u010dna analiza ne izbolj\u0161uje kakovosti kon\u010dnega produkta, kot '\u010distilec' ne naredi vode pitne. Kljub temu pa je v kombinaciji z drugimi elementi procesne linije njen pomen o\u010diten. \u010ceprav v ve\u010dkaskadnem filtru lahko izhodni kaskadi potencialno zajamejo vsa ista onesna\u017eevala kot vhodni \u2014 je jasno, kak\u0161ne posledice bo imela poskus izpustiti se zgolj s kaskadami fine filtracije, brez vhodnih kaskad.<\/p>\n<p>Namen '\u010distilca' je razbremeniti naslednje kaskade zadol\u017eitve za zajemanje res grobih napak. Na primer, najmanj, oseba, ki izvaja pregled kode, ne sme biti motena zaradi nepravilno oblikovane kode in kr\u0161enja dolo\u010denih norm kodiranja (kot so odve\u010dne oklepaje ali pregloboko zaklepanje vej). Napake, kot je NPE, morajo biti ujete z enotskimi testi, vendar, \u010de nam analitik \u017ee pred testom nakazuje, da se napaka nujno zgodi \u2014 bo to znatno pospe\u0161ilo njeno odpravo.<\/p>\n<p>Menim, da je zdaj jasno, zakaj stati\u010dna analiza ne izbolj\u0161uje kakovosti izdelka, \u010de se uporablja epizodi\u010dno, in bi morala biti uporabljena stalno za filtriranje sprememb z grobimi napakami. Vpra\u0161anje, ali bo uporaba stati\u010dnega analitik izbolj\u0161ala kakovost va\u0161ega izdelka, je pribli\u017eno enako vpra\u0161anju 'ali se bodo pitne lastnosti vode, vzete iz umazanega vodnjaka, izbolj\u0161ale, \u010de jo bomo prefiltrirali skozi cedilo?'<\/p>\n<h2>Vklju\u010ditev v legacy-projekt<\/h2>\n<p>\nPomembno prakti\u010dno vpra\u0161anje: kako vklju\u010diti stati\u010dno analizo v proces neprestanega integriranja kot \"quality gate\"? V primeru avtomatskih testov je vse jasno: obstaja niz testov, kjer je vsak neuspeh dovolj, da menimo, da zbirka ni prestala quality gate. Poskusiti postaviti gate na podlagi rezultatov stati\u010dne analize pa propade: pri legacy kodi je preve\u010d opozoril, ki jih analiza prika\u017ee, popolnoma jih ignorirati no\u010demo, a hkrati ni mogo\u010de ustaviti dostave izdelka zgolj zato, ker so v njem opozorila analizatorja.<\/p>\n<p>Ko ga prvi\u010d uvedemo, analizador na katerem koli projektu izdaja ogromno \u0161tevilo opozoril, ki ve\u010dinoma nimajo zveze s pravilnim delovanjem izdelka. Takoj popraviti vseh teh pripomb ni mogo\u010de, \u0161tevilnih tudi ni treba. Na koncu koncev, vemo, da na\u0161 izdelek na splo\u0161no deluje, in to pred uvedbo stati\u010dne analize!<\/p>\n<p>Kot rezultat se mnogi omejijo na ob\u010dasno uporabo stati\u010dne analize ali jo uporabljajo le v informativnem na\u010dinu, ko se pri gradnji preprosto izda poro\u010dilo analizatorja. To je ekvivalentno odsotnosti kakr\u0161ne koli analize, saj \u010de imamo \u017ee veliko opozoril, bo pojavitev \u0161e enega (ne glede na to, kako resno) ob spremembi kode ostala neopa\u017eena.<\/p>\n<p>Poznani so naslednji na\u010dini uvedbe quality gates:<\/p>\n<ul>\n<li>Nastavitev omejitve skupnega \u0161tevila opozoril ali \u0161tevila opozoril, deljenega s \u0161tevilom vrstic kode. To slabo deluje, saj tak\u0161en gate prosto spusti spremembe z novimi napakami, dokler njihova omejitev ni prese\u017eena.<\/li>\n<li>Zagotavljanje, da so vsi stari opozorila v kodi na nekem mestu ozna\u010deni kot prezrta, in zavrnitev gradnje pri pojavu novih opozoril. To funkcionalnost omogo\u010data PVS-studio in nekateri spletni viri, kot je Codacy. Nisem delal s PVS-studio, kar se ti\u010de mojih izku\u0161enj s Codacy, pa je njihova glavna te\u017eava v tem, da je ugotavljanje, katera napaka je 'stara', in katera 'nova' - precej zapleteno in algoritem ne deluje vedno pravilno, posebej, \u010de se datoteke mo\u010dno spreminjajo ali preimenujejo. Spomnim se, da je Codacy lahko v pull requestu spustil nova opozorila, hkrati pa zavrnil pull request zaradi opozoril, ki niso povezana s spremembami v kodi tega PR.<\/li>\n<li>Po mojem mnenju je naju\u010dinkovitej\u0161a re\u0161itev opisana v knjigi <noindex><a rel=\"nofollow\" href=\"https:\/\/www.amazon.com\/Continuous-Delivery-Deployment-Automation-Addison-Wesley\/dp\/0321601912\">Kontinuirana isporuka<\/a><\/noindex> \u00bbmetoda zasuka\u00ab (\u00bbratcheting\u00ab). Osnovna ideja je, da je lastnost vsakr\u0161ne izdaje \u0161tevilo opozoril stati\u010dne analize, in dovoljena so le tista spremembe, ki skupno \u0161tevilo opozoril ne pove\u010dajo.<\/li>\n<\/ul>\n<p><\/p>\n<h2>Zasuk<\/h2>\n<p>\nDeluje tako:<\/p>\n<ol>\n<li>V za\u010detni fazi se zabele\u017ei v metapodatkih o izdaji \u0161tevilo opozoril v kodi, ki jih najdejo analizatorji. Tako se ob gradnji glavne veje v va\u0161em upravljalniku repozitorijev ne zabele\u017ei le 'razli\u010dica 7.0.2', temve\u010d 'razli\u010dica 7.0.2, ki vsebuje 100500 opozoril Checkstyle'. \u010ce uporabljate napreden upravljalnik repozitorijev (kot je Artifactory), je shranjevanje takih metapodatkov o va\u0161i izdaji enostavno.<\/li>\n<li>Zdaj vsak pull request pri gradnji primerja \u0161tevilo pridobljenih opozoril s tistim, ki ga ima trenutna izdaja. \u010ce PR pove\u010da to \u0161tevilo, koda ne prestane kvalitativnega preizkusa s stati\u010dno analizo. \u010ce se \u0161tevilo opozoril zmanj\u0161a ali ne spremeni - to prestane.<\/li>\n<li>Ob naslednji izdaji bo ponovno izra\u010dunano \u0161tevilo opozoril zabele\u017eeno v metapodatkih izdaje.<\/li>\n<\/ol>\n<p>\nTako pomalo, ali postepeno (kao kod rada zakreta\u010da), broj upozorenja \u0107e te\u017eiti nuli. Naravno, sistem se mo\u017ee prevariti dodavanjem novog upozorenja, ali ispravkom tu\u0111eg. To je u redu, jer na duge staze daje rezultat: upozorenja se obi\u010dno ispravljaju ne pojedina\u010dno, ve\u0107 odmah u grupama odre\u0111enog tipa, i sva lako uklonjiva upozorenja dosta brzo nestaju.<\/p>\n<p>Na ovom grafikonu prikazan je ukupni broj Checkstyle upozorenja tokom \u0161est meseci rada takvog \"zakreta\u010da\" na <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/CourseOrchestra\/celesta\">jednom od na\u0161ih open-source projekata<\/a><\/noindex>. Broj upozorenja se smanjio za red, pri \u010demu je to prirodno desilo, paralelno sa razvojem proizvoda!<\/p>\n<p><img decoding=\"async\" alt=\"Vklju\u010dite stati\u010dno analizo v proces, namesto da s pomo\u010djo le-te i\u0161\u010dete napake\" src=\"\/wp-content\/uploads\/2019\/05\/9529bb2fb32187057088e8d2c4203333.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nPrimjenjujem modifikovanu verziju ove metode, posebno ra\u010dunaju\u0107i upozorenja po modulima projekta i alatima analize, dok generisani YAML fajl sa metapodacima o izgradnji izgleda otprilike ovako:<\/p>\n<pre><code class=\"plaintext\">celesta-sql:\n  checkstyle: 434\n  spotbugs: 45\ncelesta-core:\n  checkstyle: 206\n  spotbugs: 13\ncelesta-maven-plugin:\n  checkstyle: 19\n  spotbugs: 0\ncelesta-unit:\n  checkstyle: 0\n  spotbugs: 0\n<\/code><\/pre>\n<p>\nU svakom naprednom CI sistemu \"zakreta\u010d\" se mo\u017ee implementirati za sve alate stati\u010dke analize, ne oslanjaju\u0107i se na pluginove i spoljne alate. Svaki od analizatora daje svoj izve\u0161taj u jednostavnom tekstualnom ili XML formatu, koji se lako mo\u017ee analizirati. Ostaje samo da se napi\u0161e potrebna logika u CI skripti. Mo\u017eete pogledati kako je to implementirano u na\u0161im open-source projektima na bazi Jenkins i Artifactory. <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/CourseOrchestra\/2bass\/blob\/dev\/Jenkinsfile\">ovde<\/a><\/noindex> ili <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/CourseOrchestra\/celesta\/blob\/dev\/Jenkinsfile\">ovde<\/a><\/noindex>. Oba primera zavise od biblioteke <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/inponomarev\/ratchetlib\">ratchetlib<\/a><\/noindex>: metod <code>countWarnings()<\/code> obi\u0107no broji xml tagove u datotekama koje generi\u0161u Checkstyle i Spotbugs, a <code>compareWarningMaps()<\/code> implementira taj zakreta\u010d, izbacuju\u0107i gre\u0161ku u slu\u010daju kada se broj upozorenja u bilo kojoj od kategorija pove\u0107a.<\/p>\n<p>Zanimljiv na\u010din implementacije \u201eratchet\u201d mogu\u0107e je za analizu pravopisa komentara, tekstualnih literalnih i dokumentacije uz pomo\u0107 aspell. Kao \u0161to je poznato, prilikom provere pravopisa, ne svaka re\u010d koja nije poznata standardnom re\u010dniku je pogre\u0161na; one mogu biti dodate u korisni\u010dki re\u010dnik. Ako se korisni\u010dki re\u010dnik napravi delom izvornog koda projekta, pravilo kvaliteta za pravopis mo\u017ee se formulirati na slede\u0107i na\u010din: izvo\u0111enje aspell-a sa standardnim i korisni\u010dkim re\u010dnikom. <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/CourseOrchestra\/celesta\/blob\/271dcfc8dc3ad65ac2d1dcaa39b7fd3ea8fb5891\/Jenkinsfile#L36\">ne bi trebalo<\/a><\/noindex> da pronalazi nikakve gre\u0161ke u pravopisu.<\/p>\n<h2>O va\u017enosti fiksiranja verzije analizatora<\/h2>\n<p>\nNa kraju se mora napomenuti slede\u0107e: bez obzira na to kako implementirate analizu u va\u0161em procesu isporuke, verzija analizatora mora biti fiksirana. Ako do\u0111e do samovoljna a\u017euriranja analizatora, prilikom izgradnje slede\u0107eg pull request-a mogu se \u201epojaviti\u201d nove gre\u0161ke koje nisu povezane sa promenom koda, ve\u0107 su rezultat toga \u0161to novi analizator jednostavno mo\u017ee prona\u0107i vi\u0161e gre\u0161aka \u2014 i to \u0107e pokvariti va\u0161 proces prihvatanja pull request-ova. A\u017euriranje analizatora mora biti svesna odluka. Ipak, stroga fiksacija verzije svake komponente izgradnje je u svakom slu\u010daju neophodan zahtev i tema za zasebnu raspravu.<\/p>\n<h2>Zaklju\u010dki<\/h2>\n<p><\/p>\n<ul>\n<li>Stati\u010dka analiza ne\u0107e vam prona\u0107i gre\u0161ke i ne pobolj\u0161ava kvalitet va\u0161eg proizvoda kao rezultat jednorazne primene. Pozitivan efekat na kvalitet donosi samo njeno stalno kori\u0161\u0107enje u procesu isporuke.<\/li>\n<li>Pronala\u017eenje gre\u0161aka uop\u0161te nije glavni cilj analize; ogromna ve\u0107ina korisnih funkcija dostupna je u opensource alatima.<\/li>\n<li>Implementirajte pravila kvaliteta prema rezultatima stati\u010dke analize na samom po\u010detku procesa isporuke, koriste\u0107i \u201eratchet\u201d za legacy kod.<\/li>\n<\/ul>\n<p><\/p>\n<h2>Povezave<\/h2>\n<p><\/p>\n<ol>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/www.amazon.com\/Continuous-Delivery-Deployment-Automation-Addison-Wesley\/dp\/0321601912\">Kontinuirana isporuka<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/www.youtube.com\/watch?v=8Cx3LHNjI24\">A. Kudrjavcev: Analiza programa: kako razumeti da ste dobar programer<\/a><\/noindex> izve\u0161taj o razli\u010ditim metodama analize koda (ne samo stati\u010dkoj!)<\/li>\n<\/ol>\n<p>Izvor: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/436868\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u041d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u044d\u0442\u0443 \u0441\u0442\u0430\u0442\u044c\u044e \u043c\u0435\u043d\u044f \u0441\u043f\u043e\u0434\u0432\u0438\u0433\u043b\u043e \u0431\u043e\u043b\u044c\u0448\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u043e\u0432 \u043e \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u043c \u0430\u043d\u0430\u043b\u0438\u0437\u0435, \u0432\u0441\u0451 \u0447\u0430\u0449\u0435 \u043f\u043e\u043f\u0430\u0434\u0430\u044e\u0449\u0438\u0445\u0441\u044f \u043d\u0430 \u0433\u043b\u0430\u0437\u0430. \u0412\u043e-\u043f\u0435\u0440\u0432\u044b\u0445, \u044d\u0442\u043e \u0431\u043b\u043e\u0433 PVS-studio, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0430\u043a\u0442\u0438\u0432\u043d\u043e \u043f\u0440\u043e\u0434\u0432\u0438\u0433\u0430\u0435\u0442 \u0441\u0435\u0431\u044f \u043d\u0430 \u0425\u0430\u0431\u0440\u0435 \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u043e\u0431\u0437\u043e\u0440\u043e\u0432 \u043e\u0448\u0438\u0431\u043e\u043a, \u043d\u0430\u0439\u0434\u0435\u043d\u043d\u044b\u0445 \u0438\u0445 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u043c \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445 \u0441 \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u043c \u043a\u043e\u0434\u043e\u043c. \u041d\u0435\u0434\u0430\u0432\u043d\u043e PVS-studio \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043b\u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 Java, \u0438, \u043a\u043e\u043d\u0435\u0447\u043d\u043e, \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 IntelliJ IDEA, \u0447\u0435\u0439 \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0439 \u0430\u043d\u0430\u043b\u0438\u0437\u0430\u0442\u043e\u0440 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043d\u0430 \u0441\u0435\u0433\u043e\u0434\u043d\u044f, \u043d\u0430\u0432\u0435\u0440\u043d\u043e\u0435, [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":24622,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-32848","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.4 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u041d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u044d\u0442\u0443 \u0441\u0442\u0430\u0442\u044c\u044e \u043c\u0435\u043d\u044f \u0441\u043f\u043e\u0434\u0432\u0438\u0433\u043b\u043e \u0431\u043e\u043b\u044c\u0448\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u043e\u0432 \u043e \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u043c \u0430\u043d\u0430\u043b\u0438\u0437\u0435, \u0432\u0441\u0451 \u0447\u0430\u0449\u0435 \u043f\u043e\u043f\u0430\u0434\u0430\u044e\u0449\u0438\u0445\u0441\u044f \u043d\u0430 \u0433\u043b\u0430\u0437\u0430.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/sl\/blog\/administrirovanie\/vnedryajte-staticheskij-analiz-v-protsess-a-ne-ishhite-s-ego-pomoshhyu-bagi\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.4\" \/>\n\t\t<meta property=\"og:locale\" content=\"sl_SI\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u0412\u043d\u0435\u0434\u0440\u044f\u0439\u0442\u0435 \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0430\u043d\u0430\u043b\u0438\u0437 \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441, \u0430 \u043d\u0435 \u0438\u0449\u0438\u0442\u0435 \u0441 \u0435\u0433\u043e \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0431\u0430\u0433\u0438 | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u041d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u044d\u0442\u0443 \u0441\u0442\u0430\u0442\u044c\u044e \u043c\u0435\u043d\u044f \u0441\u043f\u043e\u0434\u0432\u0438\u0433\u043b\u043e \u0431\u043e\u043b\u044c\u0448\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u043e\u0432 \u043e \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u043c \u0430\u043d\u0430\u043b\u0438\u0437\u0435, \u0432\u0441\u0451 \u0447\u0430\u0449\u0435 \u043f\u043e\u043f\u0430\u0434\u0430\u044e\u0449\u0438\u0445\u0441\u044f \u043d\u0430 \u0433\u043b\u0430\u0437\u0430.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/sl\/blog\/administrirovanie\/vnedryajte-staticheskij-analiz-v-protsess-a-ne-ishhite-s-ego-pomoshhyu-bagi\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2019-10-31T18:49:16+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2019-10-31T18:49:16+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Implementirajte stati\u010dku analizu u proces, a ne tra\u017eite uz njenu pomo\u0107 gre\u0161ke | ProHoster","description":"Pisanje ovog \u010dlanka inspirisalo me je veliko mno\u017estvo materijala o stati\u010dkoj analizi, koji sve \u010de\u0161\u0107e dolaze u vid.","canonical_url":"https:\/\/prohoster.info\/sl\/blog\/administrirovanie\/vnedryajte-staticheskij-analiz-v-protsess-a-ne-ishhite-s-ego-pomoshhyu-bagi","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"sl_SI","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u0412\u043d\u0435\u0434\u0440\u044f\u0439\u0442\u0435 \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0430\u043d\u0430\u043b\u0438\u0437 \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441, \u0430 \u043d\u0435 \u0438\u0449\u0438\u0442\u0435 \u0441 \u0435\u0433\u043e \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0431\u0430\u0433\u0438 | ProHoster","og:description":"\u041d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u044d\u0442\u0443 \u0441\u0442\u0430\u0442\u044c\u044e \u043c\u0435\u043d\u044f \u0441\u043f\u043e\u0434\u0432\u0438\u0433\u043b\u043e \u0431\u043e\u043b\u044c\u0448\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u043e\u0432 \u043e \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u043c \u0430\u043d\u0430\u043b\u0438\u0437\u0435, \u0432\u0441\u0451 \u0447\u0430\u0449\u0435 \u043f\u043e\u043f\u0430\u0434\u0430\u044e\u0449\u0438\u0445\u0441\u044f \u043d\u0430 \u0433\u043b\u0430\u0437\u0430.","og:url":"https:\/\/prohoster.info\/sl\/blog\/administrirovanie\/vnedryajte-staticheskij-analiz-v-protsess-a-ne-ishhite-s-ego-pomoshhyu-bagi","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2019-10-31T18:49:16+00:00","article:modified_time":"2019-10-31T18:49:16+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"32848","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":"2026-01-21 12:50:20","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-03-01 02:51:27","updated":"2026-01-21 12:50:20","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/sl\/wp-json\/wp\/v2\/posts\/32848","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/sl\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/sl\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/sl\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/sl\/wp-json\/wp\/v2\/comments?post=32848"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/sl\/wp-json\/wp\/v2\/posts\/32848\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/sl\/wp-json\/wp\/v2\/media\/24622"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/sl\/wp-json\/wp\/v2\/media?parent=32848"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/sl\/wp-json\/wp\/v2\/categories?post=32848"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/sl\/wp-json\/wp\/v2\/tags?post=32848"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}