Rhowch ddadansoddiad statig ar waith yn y broses, yn hytrach na'i ddefnyddio i ddod o hyd i fygiau

Cefais fy ysgogi i ysgrifennu'r erthygl hon gan y swm mawr o ddeunyddiau ar ddadansoddi statig sy'n dod yn gynyddol i'm sylw. Yn gyntaf, hyn Blog PVS-stiwdio, sy'n hyrwyddo ei hun yn weithredol ar Habré gyda chymorth adolygiadau o wallau a ddarganfuwyd gan eu hofferyn mewn prosiectau ffynhonnell agored. PVS-stiwdio ar waith yn ddiweddar Cefnogaeth Java, ac, wrth gwrs, datblygwyr IntelliJ IDEA, y mae'n debyg mai eu dadansoddwr adeiledig yw'r mwyaf datblygedig ar gyfer Java heddiw, methu aros i ffwrdd.

Wrth ddarllen adolygiadau o'r fath, fe gewch y teimlad ein bod yn siarad am elixir hud: pwyswch y botwm, a dyma hi - rhestr o ddiffygion o flaen eich llygaid. Mae'n ymddangos, wrth i ddadansoddwyr wella, bydd mwy a mwy o fygiau'n cael eu canfod yn awtomatig, a bydd y cynhyrchion sy'n cael eu sganio gan y robotiaid hyn yn dod yn well ac yn well, heb unrhyw ymdrech ar ein rhan ni.

Ond nid oes unrhyw elixirs hud. Hoffwn siarad am yr hyn na sonnir amdano fel arfer mewn swyddi fel “dyma'r pethau y gall ein robot ddod o hyd iddynt”: yr hyn na all dadansoddwyr ei wneud, beth yw eu rôl a'u lle go iawn yn y broses cyflwyno meddalwedd, a sut i'w gweithredu'n gywir .

Rhowch ddadansoddiad statig ar waith yn y broses, yn hytrach na'i ddefnyddio i ddod o hyd i fygiau
Ratchet (ffynhonnell: wikipedia).

Yr hyn na all dadansoddwyr statig byth ei wneud

Beth yw dadansoddi cod ffynhonnell, o safbwynt ymarferol? Rydym yn darparu rhywfaint o god ffynhonnell fel mewnbwn, ac fel allbwn, mewn amser byr (llawer byrrach na rhedeg profion) rydym yn cael rhywfaint o wybodaeth am ein system. Y cyfyngiad sylfaenol ac anorchfygol yn fathemategol yw na allwn gael ond dosbarth gweddol gyfyng o wybodaeth yn y modd hwn.

Yr enghraifft fwyaf enwog o broblem na ellir ei datrys gan ddefnyddio dadansoddiad statig yw problem cau i lawr: Mae hon yn theorem sy'n profi ei bod yn amhosibl datblygu algorithm cyffredinol a all benderfynu o god ffynhonnell rhaglen a fydd yn dolennu neu'n terfynu mewn amser cyfyngedig. Estyniad o'r theorem hon yw Theorem Rice, sy'n nodi, ar gyfer unrhyw briodwedd nad yw'n ddibwys i swyddogaethau cyfrifadwy, fod penderfynu a yw rhaglen fympwyol yn gwerthuso swyddogaeth ag eiddo o'r fath yn broblem algorithmig anhydrin. Er enghraifft, mae'n amhosibl ysgrifennu dadansoddwr a all benderfynu o unrhyw god ffynhonnell a yw'r rhaglen sy'n cael ei dadansoddi yn weithrediad algorithm sy'n cyfrifo, dyweder, sgwario cyfanrif.

Felly, mae gan ymarferoldeb dadansoddwyr statig gyfyngiadau anorchfygol. Ni fydd dadansoddwr statig byth yn gallu canfod ym mhob achos bethau megis, er enghraifft, digwyddiad "eithriad pwyntydd null" mewn ieithoedd sy'n caniatáu gwerth nwl, neu ym mhob achos i benderfynu ar ddigwyddiad " priodoledd heb ei ganfod" mewn ieithoedd sydd wedi'u teipio'n ddeinamig. Y cyfan y gall y dadansoddwr statig mwyaf datblygedig ei wneud yw tynnu sylw at achosion arbennig, y mae eu nifer, ymhlith yr holl broblemau posibl gyda'ch cod ffynhonnell, heb or-ddweud, yn ostyngiad yn y bwced.

Nid yw dadansoddiad statig yn ymwneud â dod o hyd i fygiau

O'r uchod, mae'r casgliad a ganlyn: nid yw dadansoddiad statig yn fodd o leihau nifer y diffygion mewn rhaglen. Byddwn yn mentro dweud: pan gaiff ei gymhwyso i'ch prosiect am y tro cyntaf, bydd yn dod o hyd i leoedd “diddorol” yn y cod, ond, yn fwyaf tebygol, ni fydd yn dod o hyd i unrhyw ddiffygion sy'n effeithio ar ansawdd eich rhaglen.

Mae'r enghreifftiau o ddiffygion a ddarganfuwyd yn awtomatig gan ddadansoddwyr yn drawiadol, ond ni ddylem anghofio bod yr enghreifftiau hyn wedi'u canfod trwy sganio set fawr o gronfeydd cod mawr. Yn ôl yr un egwyddor, mae hacwyr sy'n cael y cyfle i roi cynnig ar nifer o gyfrineiriau syml ar nifer fawr o gyfrifon yn y pen draw yn dod o hyd i'r cyfrifon hynny sydd â chyfrinair syml.

A yw hyn yn golygu na ddylid defnyddio dadansoddiad statig? Wrth gwrs ddim! Ac am yr un rheswm yn union ei bod yn werth gwirio pob cyfrinair newydd i sicrhau ei fod wedi'i gynnwys yn y rhestr stopio o gyfrineiriau “syml”.

Mae dadansoddiad statig yn fwy na dod o hyd i fygiau

Mewn gwirionedd, mae'r problemau sy'n cael eu datrys yn ymarferol trwy ddadansoddi yn llawer ehangach. Wedi'r cyfan, yn gyffredinol, dadansoddiad statig yw unrhyw wiriad o godau ffynhonnell a wneir cyn eu lansio. Dyma rai pethau y gallwch chi eu gwneud:

  • Gwirio arddull codio yn ystyr ehangaf y gair. Mae hyn yn cynnwys gwirio fformatio, edrych am y defnydd o gromfachau gwag/ychwanegol, gosod trothwyon ar fetrigau fel nifer y llinellau/cymhlethdod seiclomatig dull, ac ati - unrhyw beth a allai amharu ar ddarllenadwyedd a chynaliadwyedd y cod. Yn Java, teclyn o'r fath yw Checkstyle, yn Python - flake8. Gelwir rhaglenni'r dosbarth hwn fel arfer yn “linters”.
  • Nid yn unig y gellir dadansoddi cod gweithredadwy. Gall (a dylid!) gwirio ffeiliau adnoddau fel JSON, YAML, XML, .properties yn awtomatig am ddilysrwydd. Wedi'r cyfan, mae'n well darganfod bod strwythur JSON wedi torri oherwydd rhai dyfynbrisiau heb eu paru ar gam cynnar o ddilysu Cais Tynnu'n awtomatig nag yn ystod gweithredu'r prawf neu amser rhedeg? Mae offer priodol ar gael: e.e. YAMLlint, JSONLint.
  • Mae llunio (neu ddosrannu ar gyfer ieithoedd rhaglennu deinamig) hefyd yn fath o ddadansoddiad statig. Yn gyffredinol, mae casglwyr yn gallu cynhyrchu rhybuddion sy'n nodi problemau gydag ansawdd cod ffynhonnell ac ni ddylid eu hanwybyddu.
  • Weithiau mae llunio yn fwy na dim ond llunio cod gweithredadwy. Er enghraifft, os oes gennych ddogfennaeth yn y fformat AsciiDoctor, yna ar hyn o bryd o'i droi'n HTML/PDF y triniwr AsciiDoctor (Ategyn Maven) yn gallu rhoi rhybuddion, er enghraifft, am gysylltiadau mewnol sydd wedi torri. Ac mae hwn yn reswm da i beidio â derbyn y Cais Tynnu gyda newidiadau dogfennaeth.
  • Mae gwirio sillafu hefyd yn fath o ddadansoddiad statig. Cyfleustodau aspell yn gallu gwirio sillafu nid yn unig mewn dogfennaeth, ond hefyd mewn codau ffynhonnell rhaglen (sylwadau a llythrennol) mewn amrywiol ieithoedd rhaglennu, gan gynnwys C/C++, Java a Python. Mae gwall sillafu yn y rhyngwyneb defnyddiwr neu ddogfennaeth hefyd yn ddiffyg!
  • Profion cyfluniad (am yr hyn ydyn nhw - gweler. hyn и hyn adroddiadau), er eu bod yn cael eu gweithredu mewn amser rhedeg prawf uned fel pytest, mewn gwirionedd hefyd yn fath o ddadansoddiad statig, gan nad ydynt yn gweithredu codau ffynhonnell yn ystod eu gweithredu.

Fel y gallwch weld, chwilio am chwilod yn y rhestr hon sy'n chwarae'r rôl leiaf pwysig, ac mae popeth arall ar gael trwy ddefnyddio offer ffynhonnell agored am ddim.

Pa rai o'r mathau hyn o ddadansoddiadau statig y dylech eu defnyddio yn eich prosiect? Wrth gwrs, gorau po fwyaf! Y prif beth yw ei weithredu'n gywir, a fydd yn cael ei drafod ymhellach.

Piblinell cyflawni fel hidlydd aml-gam a dadansoddiad statig fel ei gam cyntaf

Mae'r trosiad clasurol ar gyfer integreiddio parhaus yn biblinell lle mae newidiadau'n llifo, o newidiadau cod ffynhonnell i gyflenwi i gynhyrchu. Mae'r dilyniant safonol o gamau yn y biblinell hon yn edrych fel hyn:

  1. dadansoddiad statig
  2. crynhoad
  3. profion uned
  4. profion integreiddio
  5. Profion UI
  6. gwirio â llaw

Nid yw newidiadau a wrthodwyd yn Nfed cam y biblinell yn cael eu trosglwyddo i gam N+1.

Pam yn union fel hyn ac nid fel arall? Yn rhan brofi'r biblinell, bydd profwyr yn adnabod y pyramid profi adnabyddus.

Rhowch ddadansoddiad statig ar waith yn y broses, yn hytrach na'i ddefnyddio i ddod o hyd i fygiau
Prawf pyramid. Ffynhonnell: erthygl Martin Fowler.

Ar waelod y pyramid hwn mae profion sy'n haws eu hysgrifennu, yn gyflymach i'w gweithredu, ac nad ydynt yn dueddol o fethu. Felly, dylai fod mwy ohonynt, dylent gwmpasu mwy o god a chael eu gweithredu yn gyntaf. Ar frig y pyramid, mae'r gwrthwyneb yn wir, felly dylid lleihau nifer y profion integreiddio a UI i'r lleiafswm angenrheidiol. Y person yn y gadwyn hon yw'r adnodd drutaf, araf ac annibynadwy, felly mae ar y diwedd a dim ond yn perfformio'r gwaith os na ddaeth y camau blaenorol o hyd i unrhyw ddiffygion. Fodd bynnag, defnyddir yr un egwyddorion i adeiladu piblinell mewn rhannau nad ydynt yn uniongyrchol gysylltiedig â phrofi!

Hoffwn gynnig cyfatebiaeth ar ffurf system hidlo dŵr aml-gam. Mae dŵr budr (newidiadau â diffygion) yn cael ei gyflenwi i'r mewnbwn; yn yr allbwn mae'n rhaid i ni dderbyn dŵr glân, lle mae'r holl halogion diangen wedi'u dileu.

Rhowch ddadansoddiad statig ar waith yn y broses, yn hytrach na'i ddefnyddio i ddod o hyd i fygiau
Hidlydd aml-gam. Ffynhonnell: Wikimedia Commons

Fel y gwyddoch, mae hidlwyr glanhau wedi'u cynllunio fel bod pob rhaeadr dilynol yn gallu hidlo ffracsiwn cynyddol fanach o halogion. Ar yr un pryd, mae gan raeadrau puro mwy bras trwybwn uwch a chost is. Yn ein cyfatebiaeth, mae hyn yn golygu bod gatiau ansawdd mewnbwn yn gyflymach, yn gofyn am lai o ymdrech i ddechrau, ac yn fwy diymhongar eu hunain ar waith - a dyma'r dilyniant y cânt eu hadeiladu ynddo. Rôl dadansoddiad statig, sydd, fel y deallwn yn awr, yn gallu chwynnu dim ond y diffygion mwyaf difrifol, yw rôl y grid “mwd” ar ddechrau cyntaf y rhaeadru hidlo.

Nid yw dadansoddiad statig ynddo'i hun yn gwella ansawdd y cynnyrch terfynol, yn union fel nad yw "hidlydd mwd" yn gwneud dŵr yn yfedadwy. Ac eto, ar y cyd ag elfennau eraill o'r biblinell, mae ei bwysigrwydd yn amlwg. Er y gallai'r camau allbwn, mewn hidlydd amlran, ddal popeth y mae'r camau mewnbwn yn ei wneud, mae'n amlwg pa ganlyniadau a fydd yn deillio o ymgais i wneud â chamau puro manwl yn unig, heb gamau mewnbwn.

Pwrpas y “trap mwd” yw rhyddhau rhaeadrau dilynol rhag dal diffygion difrifol iawn. Er enghraifft, o leiaf, ni ddylai’r sawl sy’n adolygu’r cod gael ei dynnu gan god sydd wedi’i fformatio’n anghywir a thorri safonau codio sefydledig (fel cromfachau ychwanegol neu ganghennau sydd wedi’u nythu’n rhy ddwfn). Dylai bygiau fel NPEs gael eu dal gan brofion uned, ond os bydd y dadansoddwr hyd yn oed cyn y prawf yn nodi i ni fod byg yn sicr o ddigwydd, bydd hyn yn cyflymu ei drwsio'n sylweddol.

Credaf ei bod bellach yn glir pam nad yw dadansoddiad statig yn gwella ansawdd y cynnyrch os caiff ei ddefnyddio'n achlysurol, a dylid ei ddefnyddio'n gyson i hidlo newidiadau â diffygion gros. Mae'r cwestiwn a fydd defnyddio dadansoddwr statig yn gwella ansawdd eich cynnyrch yn cyfateb yn fras i ofyn, "A fydd ansawdd yfed dŵr a gymerir o bwll budr yn gwella os caiff ei basio trwy golandr?"

Gweithredu i mewn i brosiect etifeddiaeth

Cwestiwn ymarferol pwysig: sut i roi dadansoddiad statig ar waith yn y broses integreiddio barhaus fel “giât ansawdd”? Yn achos profion awtomatig, mae popeth yn amlwg: mae yna set o brofion, mae methiant unrhyw un ohonynt yn ddigon o reswm i gredu nad oedd y cynulliad yn pasio'r giât ansawdd. Mae ymgais i osod giât yn yr un modd yn seiliedig ar ganlyniadau dadansoddiad statig yn methu: mae gormod o rybuddion dadansoddi yn y cod etifeddiaeth, nid ydych am eu hanwybyddu'n llwyr, ond mae hefyd yn amhosibl rhoi'r gorau i gludo cynnyrch dim ond oherwydd ei fod yn cynnwys rhybuddion dadansoddwr.

Pan gaiff ei ddefnyddio am y tro cyntaf, mae'r dadansoddwr yn cynhyrchu nifer fawr o rybuddion ar unrhyw brosiect, ac nid yw'r mwyafrif helaeth ohonynt yn gysylltiedig â gweithrediad priodol y cynnyrch. Mae'n amhosibl cywiro'r holl sylwadau hyn ar unwaith, ac nid oes angen llawer ohonynt. Wedi'r cyfan, rydym yn gwybod bod ein cynnyrch yn ei gyfanrwydd yn gweithio, hyd yn oed cyn cyflwyno dadansoddiad statig!

O ganlyniad, mae llawer yn gyfyngedig i ddefnydd achlysurol o ddadansoddi statig, neu ei ddefnyddio yn y modd gwybodaeth yn unig, pan fydd adroddiad dadansoddwr yn cael ei gyhoeddi yn ystod y gwasanaeth. Mae hyn yn cyfateb i absenoldeb unrhyw ddadansoddiad, oherwydd os oes gennym eisoes lawer o rybuddion, yna mae digwyddiad arall (ni waeth pa mor ddifrifol) wrth newid y cod yn mynd heb i neb sylwi.

Mae'r dulliau canlynol o gyflwyno gatiau ansawdd yn hysbys:

  • Gosod terfyn ar gyfanswm nifer y rhybuddion neu nifer y rhybuddion wedi'u rhannu â nifer y llinellau cod. Mae hyn yn gweithio'n wael, oherwydd bod giât o'r fath yn caniatáu i newidiadau gyda diffygion newydd basio drwodd, cyn belled nad eir y tu hwnt i'w terfyn.
  • Trwsio, ar adeg benodol, yr holl hen rybuddion yn y cod fel y'u hanwybyddwyd, a gwrthod adeiladu pan fydd rhybuddion newydd yn digwydd. Darperir y swyddogaeth hon gan PVS-studio a rhai adnoddau ar-lein, er enghraifft, Codacy. Ni chefais y cyfle i weithio yn PVS-studio, oherwydd ar gyfer fy mhrofiad gyda Codacy, eu prif broblem yw bod pennu beth yw gwall “hen” a beth sy'n “newydd” yn algorithm eithaf cymhleth nad yw bob amser yn gweithio. yn gywir, yn enwedig os caiff ffeiliau eu haddasu neu eu hailenwi'n helaeth. Yn fy mhrofiad i, gallai Codacy anwybyddu rhybuddion newydd mewn cais tynnu, tra ar yr un pryd peidio â phasio cais tynnu oherwydd rhybuddion nad oeddent yn gysylltiedig â newidiadau yn y cod cysylltiadau cyhoeddus penodol.
  • Yn fy marn i, yr ateb mwyaf effeithiol yw'r un a ddisgrifir yn y llyfr Cyflawniad Parhaus “dull ratcheting”. Y syniad sylfaenol yw bod nifer y rhybuddion dadansoddi statig yn eiddo i bob datganiad, a dim ond newidiadau a ganiateir nad ydynt yn cynyddu cyfanswm nifer y rhybuddion.

Ratchet

Mae'n gweithio fel hyn:

  1. Yn y cam cychwynnol, gwneir cofnod yn y metadata am ryddhau nifer y rhybuddion yn y cod a ddarganfuwyd gan y dadansoddwyr. Felly, pan fyddwch chi'n adeiladu i fyny'r afon, mae rheolwr eich ystorfa yn ysgrifennu nid yn unig “rhyddhau 7.0.2”, ond “rhyddhau 7.0.2 yn cynnwys 100500 o rybuddion arddull siec.” Os ydych chi'n defnyddio rheolwr storfa uwch (fel Artifactory), mae'n hawdd storio metadata o'r fath am eich datganiad.
  2. Nawr mae pob cais tynnu, pan gaiff ei adeiladu, yn cymharu nifer y rhybuddion canlyniadol â nifer y rhybuddion sydd ar gael yn y datganiad cyfredol. Os yw PR yn arwain at gynnydd yn y nifer hwn, yna nid yw'r cod yn pasio'r giât ansawdd ar gyfer dadansoddiad statig. Os bydd nifer y rhybuddion yn lleihau neu ddim yn newid, yna mae'n pasio.
  3. Yn y datganiad nesaf, bydd y nifer o rybuddion a ailgyfrifwyd yn cael eu cofnodi eto yn y metadata rhyddhau.

Felly fesul tipyn ond yn raddol (fel pan fydd clicied yn gweithio), bydd nifer y rhybuddion yn tueddu i sero. Wrth gwrs, gall y system gael ei thwyllo trwy gyflwyno rhybudd newydd, ond cywiro rhybudd rhywun arall. Mae hyn yn normal, oherwydd dros bellter hir mae'n rhoi canlyniadau: mae rhybuddion yn cael eu cywiro, fel rheol, nid yn unigol, ond mewn grŵp o fath penodol ar unwaith, ac mae pob rhybudd hawdd ei dynnu yn cael ei ddileu yn eithaf cyflym.

Mae'r graff hwn yn dangos cyfanswm nifer y rhybuddion Checkstyle am chwe mis o weithredu “ratchet” o'r fath ymlaen un o'n prosiectau OpenSource. Mae nifer y rhybuddion wedi gostwng yn ôl trefn maint, a digwyddodd hyn yn naturiol, ochr yn ochr â datblygu cynnyrch!

Rhowch ddadansoddiad statig ar waith yn y broses, yn hytrach na'i ddefnyddio i ddod o hyd i fygiau

Rwy'n defnyddio fersiwn wedi'i addasu o'r dull hwn, gan gyfrif rhybuddion ar wahân fesul modiwl prosiect ac offeryn dadansoddi, gan arwain at ffeil YAML gyda metadata adeiladu sy'n edrych yn rhywbeth fel hyn:

celesta-sql:
  checkstyle: 434
  spotbugs: 45
celesta-core:
  checkstyle: 206
  spotbugs: 13
celesta-maven-plugin:
  checkstyle: 19
  spotbugs: 0
celesta-unit:
  checkstyle: 0
  spotbugs: 0

Mewn unrhyw system CI uwch, gellir gweithredu clicied ar gyfer unrhyw offer dadansoddi statig heb ddibynnu ar ategion ac offer trydydd parti. Mae pob dadansoddwr yn cynhyrchu ei adroddiad ei hun mewn testun syml neu fformat XML sy'n hawdd ei ddadansoddi. Y cyfan sydd ar ôl yw ysgrifennu'r rhesymeg angenrheidiol yn y sgript CI. Gallwch weld sut mae hyn yn cael ei weithredu yn ein prosiectau ffynhonnell agored yn seiliedig ar Jenkins ac Artifactory yma neu yma. Mae'r ddwy enghraifft yn dibynnu ar y llyfrgell ratchetlib: dull countWarnings() yn cyfrif tagiau xml mewn ffeiliau a gynhyrchir gan Checkstyle a Spotbugs yn y ffordd arferol, a compareWarningMaps() yn gweithredu'r un glicied, gan daflu gwall pan fydd nifer y rhybuddion yn unrhyw un o'r categorïau yn cynyddu.

Mae gweithrediad diddorol o'r "ratchet" yn bosibl ar gyfer dadansoddi sillafu sylwadau, llythrennau testun a dogfennaeth gan ddefnyddio aspell. Fel y gwyddoch, wrth wirio sillafu, nid yw pob gair anhysbys i'r geiriadur safonol yn anghywir; gellir eu hychwanegu at eiriadur y defnyddiwr. Os gwnewch eiriadur personol yn rhan o god ffynhonnell y prosiect, yna gellir llunio'r giât ansawdd sillafu fel hyn: rhedeg aspell gyda geiriadur safonol ac arferiad ni ddylai dod o hyd i ddim gwallau sillafu.

Am bwysigrwydd trwsio'r fersiwn dadansoddwr

I gloi, y pwynt i'w nodi yw, ni waeth sut rydych chi'n gweithredu dadansoddiad yn eich piblinell gyflenwi, rhaid i fersiwn y dadansoddwr fod yn sefydlog. Os ydych chi'n caniatáu i'r dadansoddwr ddiweddaru'n ddigymell, yna wrth gydosod y cais tynnu nesaf, gall diffygion newydd “ymddangos” nad ydyn nhw'n gysylltiedig â newidiadau cod, ond sy'n gysylltiedig â'r ffaith bod y dadansoddwr newydd yn gallu dod o hyd i fwy o ddiffygion - a bydd hyn yn torri ar eich proses o dderbyn ceisiadau tynnu. Dylai uwchraddio dadansoddwr fod yn weithred ymwybodol. Fodd bynnag, yn gyffredinol mae gosod fersiwn pob cydran o'r cynulliad yn anhyblyg yn ofyniad angenrheidiol ac yn destun trafodaeth ar wahân.

Canfyddiadau

  • Ni fydd dadansoddiad statig yn dod o hyd i fygiau i chi ac ni fydd yn gwella ansawdd eich cynnyrch o ganlyniad i un cais. Dim ond trwy ei ddefnyddio'n gyson yn ystod y broses gyflenwi y gellir cael effaith gadarnhaol ar ansawdd.
  • Nid dod o hyd i fygiau yw'r brif dasg o ddadansoddi o gwbl; mae mwyafrif helaeth y swyddogaethau defnyddiol ar gael mewn offer ffynhonnell agored.
  • Gweithredu giatiau ansawdd yn seiliedig ar ganlyniadau dadansoddiad statig ar gam cyntaf un y bibell gyflenwi, gan ddefnyddio “ratchet” ar gyfer cod etifeddiaeth.

cyfeiriadau

  1. Cyflawniad Parhaus
  2. A. Kudryavtsev: Dadansoddi rhaglenni: sut i ddeall eich bod yn rhaglennydd da adrodd ar wahanol ddulliau o ddadansoddi cod (nid yn unig yn sefydlog!)

Ffynhonnell: hab.com

Ychwanegu sylw