Defensiv programmering: Er det paranoia eller smart koding?

Hvorfor defensiv programmering er den beste måten for robust koding

Defensiv programmering er den eneste virkelige programmeringen.

Bildekreditter: Pixabay.com

Defensiv programmering er når en programmerer forventer problemer og skriver kode for å håndtere dem.

Det er som å se et bilulykke i fremtiden… .. og forbli rolig fordi du har forsikret for det.

Når det er sagt, er hele poenget med defensiv programmering beskyttelse mot feil du ikke forventer. En defensiv programmerer er på vakt for problemer, for å unngå det før det kan forårsake reelle problemer. Tanken er ikke å skrive kode som aldri svikter. Det er en utopisk drøm. Ideen om å få koden til å feile vakkert i tilfelle uventede problemer. Svikt vakkert kan bety noe av følgende.

Mislykkes tidlig: koden din skal sikre at alle viktige operasjoner avsluttes på forhånd, spesielt hvis de er beregningsdyktige eller kan påvirke data irreversibelt.

· Feil feil: der det er feil, skal koden sikre at den gir fra seg alle låser og ikke skaffer seg nye, ikke skriver filer og så videre.

· Mislykkes tydelig: Når noe er ødelagt, skal det returnere en veldig tydelig feilmelding og beskrivelse som kan gjøre det mulig for supportteamet å løse feilen.

Ok. Du kan kanskje krangle her.

Det er ingen problemer i dag. Koden min fungerer vakkert. Hvorfor skal jeg investere tid og krefter i et "fremtidig forventet" problem? Tross alt er vi gjentatte ganger blitt lært å bruke “You Ain't Gonna Need It” (YAGNI). Og du er en profesjonell programmerer og ikke en hobbysnekker som kan fortsette å legge til koden når du vil.

Nøkkelen her er pragmatisme.

Andrew Hunt beskriver i sin bok Pragmatic Programmer defensiv programmering som “Pragmatic Paranoia”.

Beskytt koden din mot andre menneskers feil og dine egne feil. Hvis du er i tvil, bekreft. Sjekk for datakonsistens og integritet. Du kan ikke teste for alle feil, så bruk påstander og unntaksbehandlere for ting som "ikke kan skje".

Sunn paranoid programmering er riktig type programmering. Men paranoia kan tas for langt. Nøkkelen er å oppnå den rette balansen.

Og her er noen måter å gjøre defensiv programmering på.

Spør deg selv: Hvis dette mislykkes?

Hver kodelinje gjør noe, så det første forsvarspunktet spør deg selv om koden mislykkes, hva.

Vurder for eksempel følgende kode som ikke er kompatibel.

CASE SY-INDEX. // Ikke-kompatibel; mangler NÅR ANDRE klausul
NÅR EN.
SKRIV ‘Én’.
NÅR 2.
SKRIFT ‘To’.
ENDCASE.

Her kan vi stille følgende spørsmål.

Hva skjer hvis sy-indeksen ikke er 1.

Hva skjer hvis sy-indeksen ikke er 2.

For å løse dette problemet legger vi til en ANDRE uttalelse.

CASE SY-INDEX.
NÅR EN.
SKRIV ‘Én’.
NÅR 2.
SKRIFT ‘To’.
NÅR ANDRE. // Overensstemmende
SKRIV "Uventet resultat"
ENDCASE.

Enkel. Er det ikke?

Det er denne "hva om" -tankegangen som skiller gode programmerere fra de som skriver kode og håper den aldri svikter. "Aldri" kommer alltid raskere enn forventet, og da blir koden begravet i en lenge glemt del av programmet, med feilmeldingene som ikke gir noen indikasjon på hvor problemet er og hvordan du løser det.

Det fine med denne defensive programmeringsteknikken er at det koster nesten ingen tid å legge til uttømmende typekontroll til koden din. Du er ikke "over koding". Du bare “sikrer” koden.

Kontroller grenseforholdene nøye.

Den aller første kontrollen er å kontrollere om du trenger en grensebetingelse, for tross alt fordi løkker er dyre.

Grenseforhold (eller kant) forholdene er der all handlingen skjer. Loop fra 0 til 100 og loopverdiene 1 til 98 er stort sett de samme (sperrer betingelser i koden selvfølgelig). Men sløyfe 0 er der koden kommer inn i sløyfen, og initialiseringsbetingelser er satt opp (og muligens satt opp feil). På samme måte er den siste sløyfen der ting går igjen, og hva sløyfen gjorde for verdier, stopper opp.

En sløyfe med høyst en iterasjon tilsvarer bruken av en IF-setning for betinget å utføre ett stykke kode. Ingen utviklere bør forvente å finne slik bruk av en loop-setning. Hvis forfatterens første intensjon virkelig var å betinget utføre ett stykke kode, bør en IF-uttalelse brukes på plass.

Vurder følgende ikke-kompatibel og kompatibel kode. Vi trenger ikke sløyfe i det hele tatt. Et enkelt IF vil gjøre.

            Eksempel på ikke-kompatibel kode
DATA resten TYPE i.
GJØR 20 GANGER.
resten = sy-indeks MOD 2.
cl_demo_output => write_text ().
EXIT. “Ikke-kompatibel, kjøres bare én gang. Vi kan bruke IF
ENDDO.
          Eksempel på samsvarende kode
DATA resten TYPE i.
GJØR 20 GANGER.
resten = sy-indeks MOD 2.
cl_demo_output => write_text ().
ENDDO.

Husk alltid at feilsøkingsløkker alltid involverer mesteparten av innsatsen i starten og slutten, og sørg for at hva som kommer inn og hva som kommer ut er riktig. Så når du er klar over grensevilkårene, kan ingenting annet virkelig gå galt med koden din.

Bruk TDD (Test Driven Development)

Den grunnleggende ideen om TDD er "skriv først testenheter, skriv deretter koden, deretter refaktoren, og deretter gjenta."

Enhetstester er automatiserte tester som sjekker om funksjoner fungerer som forventet. Den aller første enhetstesten din skal mislykkes, siden den er skrevet før du til og med har noen kodebase.

Du legger til litt i test case-koden. Du legger litt til produksjonskoden. De to kodestrømmene vokser samtidig til komplementære komponenter. Testene passer til produksjonskoden som et antistoff passer til et antigen.

Problemet med å teste kode er at du må isolere den koden. Det er ofte vanskelig å teste en funksjon hvis den funksjonen kaller andre funksjoner. For å skrive den testen må du finne ut på noen måte å koble fra funksjonen fra alle de andre. Med andre ord, behovet for å teste først tvinger deg til å tenke på god design.

Dette skaper et bedre, frakoblet design der du har bedre kontroll over ting etter hvert som koden utvikles.

Selv om du skriver prøvesaker på forhånd, kan det konsumere tid først, men det gir mange fordeler. Utviklere innrømmer at tidligere brukte de å skrive kodelinjer, skjønte at løsningene deres var irrelevante, og så begynte å kode igjen fra grunnen av.

I motsetning til utdaterte kodingspraksis, lar TDD utviklere gå tilbake til tegnebrettet og konsentrere seg om å utforme en lett, fleksibel arkitektur på forhånd.

Og det faktum å skrive testtilfeller på forhånd forhindrer feil som kan dukke opp senere og sparer tid, krefter og halsbrann.

Skriv alltid optimalisert kode.

Noen programmer (og programmerere) liker mye ressurser. Men når du kan, bruk det minste. Og for å bruke minimum skal koden din være så optimalisert som mulig.

Vanligvis er en sikker måte å optimalisere å slå på de optimaliseringene som kompilatoren gir innebygd.

Kompilatoroptimaliseringer forbedrer vanligvis kjøretiden fra noen få prosent til en faktor på 2. Noen ganger kan det også bremse produktet, så det må bare måles nøye før du tar den endelige samtalen. Moderne kompilatorer klarer seg imidlertid tilstrekkelig bra i denne forbindelse da de unngår mye av behovet for småskalaendringer av programmerere.

Foruten de vanlige kompilatoroptimaliseringene, er det flere andre innstillingsteknikker som kan brukes.

Samle vanlige subexpressions.

Hvis det skjer en kostbar beregning flere steder, er det bedre å beregne ett sted og huske resultatet. Ikke legg slike beregninger i en loop, med mindre det kreves.

Erstatt dyre operasjoner med billige.

Strengmanipulering er sannsynligvis en av de vanligste operasjonene i et program. Det kan imidlertid være en kostbar operasjon hvis det gjøres feil. På samme måte kan du i noen tilfeller forbedre ytelsen ved å erstatte multiplikasjon med en serie skiftoperasjoner. Selv der dette er effektivt (og det er ikke alltid det) produserer det veldig forvirrende kode. Så ta beslutningen med tanke på kodens lesbarhet også.

Eliminer Loops.

Looper er stort sett overhead. Forsøk å unngå løkker der det er mulig hvis det ikke er mye igjen.

Cache verdier som brukes ofte.

Caching drar fordel av lokalitet, tendensen til programmer og mennesker til å gjenbruke nylig brukte data. Bufring av bare det mest brukte tegnet eller data forbedrer ytelsen til programmet betydelig.

Omskriv på et lavere nivå språk.

Dette skal være siste utvei. Språk på lavere nivå har en tendens til å være mer effektive, selv om det er mer tidkrevende fra programmererens synspunkt. Noen ganger får vi betydelige forbedringer ved å skrive om avgjørende kode på språk på lavere nivå, men dette koster redusert portabilitet og vedlikehold blir veldig vanskelig. Så ta beslutningen nøye.

Husk på optimalisering, valg er kanskje 90% av spillet. Det er verdt å ta seg tid til å bestemme hva du gjør og å gjøre det riktig. Selvfølgelig: Det er også her den svarte magien ligger!

Og til slutt, Stol på ingen.

”Det er kjente kjente; det er ting vi vet vi vet, ”sa Donald Rumsfeld, forsvarsministeren under den andre Bush-administrasjonen, en gang på en pressekonferanse. ”Vi vet også at det er kjente ukjente; det vil si at vi vet at det er noen ting vi ikke vet. Men det er også ukjente ukjente - de vi ikke vet at vi ikke kjenner. "

Rumsfeld snakket om krigen i Irak, men det samme gjelder også for data. I et nøtteskall betyr dette å bekrefte alle data du ikke har fullstendig kontroll over.

Det er klart, brukerdata er alltid mistenkte. Brukere kan godt misforstå hva du synes er krystallklart. Prøv å foregripe problemer, og bekreft eller på annen måte rydde opp i alt som kommer inn.

Data om programinnstillinger er også utsatt for feil. INI-filer pleide å være en vanlig måte å lagre programinnstillinger. Fordi de var en tekstfil, var det mange som vante å redigere dem manuelt med en tekstredigerer, og muligens (sannsynligvis) skru opp verdiene. Registreringsdata, databasefiler - noen kan og finjustere dem en dag, så det lønner seg å bekrefte selv de tingene.

Kort sagt, dataene som kommer inn, må være rene hvis du har noe håp om at koden din skal gjøre det den er ment å gjøre. Hvis du noen gang har hørt uttrykket "Garbage in, Garbage Out", er det her det kom fra.

Som Edward Demming med rette har sagt.

”I Gud stoler vi på. Alle andre må ha med seg data. ”
Om forfatteren-:
Ravi Rajan er en global IT-programleder basert i Mumbai, India. Han er også en ivrig blogger, Haiku lyrikkforfatter, arkeologientusiast og historie gal. Ta kontakt med Ravi på LinkedIn, Medium og Twitter.