Gå til innhold

ProgrammeringsBaren! Småprat, om det du elsker!


Anbefalte innlegg

Videoannonse
Annonse

... Jeg tenkte mer på ett faktabasert forklaring, med cons og pros satt sammen.

BDD er både en filosofi og en samling med flere praksiser, og det er vanskelig å gi en kort og konsis beskrivelse. Hovedpoenget er at BDD-praktikanter fokuserer på å forstå forretningsproblemet sammen med kunden / den som har problemet. Det er retningslinjer for hvordan man kommuniserer, og dette tar man med seg når man implementerer selve løsningen.

 

Ett viktig prinsipp er utenfra-og-inn programmering, og det har jeg skrevet endel om her.

 

BDD'ere skriver også automatiserte tester på et noe høyere nivå enn i tradisjonell testdreven utvikling, og bruker ofte et naturlig språk som kan leses av ikke-teknikere. Et verktøy for å få dette til er Cucumber, som jeg også har blogget om. Tilsvarende verktøy for .NET-utviklere heter SpecFlow.

 

Formålet med BDD (i én setning) er å begrense kommunikasjonsproblemene mellom teknikerne og ikke-teknikerne ved å sørge for at de snakker SAMME SPRÅK, og dermed redusere antall feil og mangler i den resulterende løsningen!

 

Hjalp det?

Endret av torbjørn marø
Lenke til kommentar

Jeg har alltid trodd at for-løkker introduserte nye bindinger for variablene til venstre for "in". Men neida, de gjenbruker bindinger dersom de finnes i det leksikale skopet.

 

Må si jeg synes måten python håndterer bindinger på virker svært lite elegant.

Python er ikke alene om dette, fungerer akkurat likt i JavaScript, Ruby m.fl.

Lenke til kommentar

Jeg har alltid trodd at for-løkker introduserte nye bindinger for variablene til venstre for "in". Men neida, de gjenbruker bindinger dersom de finnes i det leksikale skopet.

 

Må si jeg synes måten python håndterer bindinger på virker svært lite elegant.

 

Hvorfor spiller det noen rolle hvordan dette håndteres behind the scenes?

Lenke til kommentar

Jeg har alltid trodd at for-løkker introduserte nye bindinger for variablene til venstre for "in". Men neida, de gjenbruker bindinger dersom de finnes i det leksikale skopet.

 

Hvorfor spiller det noen rolle hvordan dette håndteres behind the scenes?

Problemet er at det gjør det mulig å bruke variabler som allerede er definert utenfor løkka som itereringsvariabel. 99% av gangene dette gjøres er det en feil. I de tilfellene det gjøres bevisst kommuniserer koden dårlig, og man bør derfor alltid passe på å bruke unike navn på itereringsvariabler.

 

Bare for å illustrere hva vi snakker om her, så alle er med (eksempel i JavaScript):

 

var i = 10;

// her kan det være noe koee som bruker i

for (i = 1; i <= 3; i++)
   console.log(i); // skriver ut 1, 2 og 3

// Og hva er verdien av i nå??? Svaret er 4!

 

Dette gir mening, men er skummelt. Små metoder hjelper betraktelig. Fornuftig navngivning ligeså..

Endret av torbjørn marø
Lenke til kommentar

Jeg har alltid trodd at for-løkker introduserte nye bindinger for variablene til venstre for "in". Men neida, de gjenbruker bindinger dersom de finnes i det leksikale skopet.

 

Hvorfor spiller det noen rolle hvordan dette håndteres behind the scenes?

Problemet er at det gjør det mulig å bruke variabler som allerede er definert utenfor løkka som itereringsvariabel. 99% av gangene dette gjøres er det en feil. I de tilfellene det gjøres bevisst kommuniserer koden dårlig, og man bør derfor alltid passe på å bruke unike navn på itereringsvariabler.

 

Bare for å illustrere hva vi snakker om her, så alle er med (eksempel i JavaScript):

 

var i = 10;

// her kan det være noe koee som bruker i

for (i = 1; i <= 3; i++)
   console.log(i); // skriver ut 1, 2 og 3

// Og hva er verdien av i nå??? Svaret er 4!

 

Dette gir mening, men er skummelt. Små metoder hjelper betraktelig. Fornuftig navngivning ligeså..

 

 

AFAIK blir er et scope i javascript begrenset av funksjonen koden kjører i, med mindre du bruker let (js 1.7):

<script type="application/javascript;version=1.7"/>
var i = 10;

// her kan det være noe koee som bruker i

for (let i = 1; i <= 3; i++)
   document.write(i); // skriver ut 1, 2 og 3

// i=10
document.write(i);
</script>

 

alternativt kan en skrive dette i andre js-versjoner med en IIFE (Immediately-Invoked Function Expression)

 

 

 

 

var i = 10;

(function(){
   for (var i = 1; i <= 3; i++) {
       document.write(i); // skriver ut 1, 2 og 3
   }
})();

// i=10
document.write(i);

 

Jeg ser egentlig ikke noe problem i dette. Om du benytter et språk bør du jo uansett vite dette, og da er det jo ingen problem å ta høyde for det..

Endret av dabear
Lenke til kommentar

Har programmert litt python i kveld.

 

Jeg har alltid trodd at for-løkker introduserte nye bindinger for variablene til venstre for "in". Men neida, de gjenbruker bindinger dersom de finnes i det leksikale skopet.

 

Må si jeg synes måten python håndterer bindinger på virker svært lite elegant.

 

Jeg trodde også dette. Testet i Java, men der er det dog ikke mulig å erklære en ny variabel inni en for statement som hadde kunnet overskygge en ytre variabel. Overskygging er ikke mulig.

 

Men at dette er usedvanlig dårlig av nevnte språk; Java, Python, Ruby og JavaScript er uten en tvil. Personlig har jeg alltid vært skeptisk til hvordan bindinger virker i Python (hele denne historien med global/local), men jeg trodde da de øvrige hadde greid dette på en mindre hjerneskadet måte.

Lenke til kommentar

Jeg ser egentlig ikke noe problem i dette. Om du benytter et språk bør du jo uansett vite dette, og da er det jo ingen problem å ta høyde for det..

Som jeg nevnte for litt siden liker jeg normalt sett språk som gir meg lov til å skyte meg selv i foten om det er det jeg ønsker. MEN denne diskusjonen viser at mange synes dette er uintuitivt, og er man ikke forsiktig - og ikke skriver ren nok kode - er det desverre lett for at man innfører feil. Jeg tar altså høyde for det selv, men ser problemet likevel.

Lenke til kommentar
Gjest Slettet+9871234

Som jeg nevnte for litt siden liker jeg normalt sett språk som gir meg lov til å skyte meg selv i foten om det er det jeg ønsker. MEN denne diskusjonen viser at mange synes dette er uintuitivt, og er man ikke forsiktig - og ikke skriver ren nok kode - er det desverre lett for at man innfører feil. Jeg tar altså høyde for det selv, men ser problemet likevel.

Man bør vel kunne forvente av en programmerer at vedkommende vet hvilket "scope" variablene vedkommende definerer (bruker) gjelder i.

 

Personlig vil jeg også definere en "closure" som en innkapslet omgivelse.

Lenke til kommentar

Man bør vel kunne forvente av en programmerer at vedkommende vet hvilket "scope" variablene vedkommende definerer (bruker) gjelder i.

 

Personlig vil jeg også definere en "closure" som en innkapslet omgivelse.

 

Samtidig bør man kunne forvente at en programmerer aldri lager bugs. Og alltid leverer i tide.

 

Fra spøk til alvor, poenget er at skopregler bør være så enkle som mulig. I "lispete" språk blir variabler introdusert med let() og gjelder nøyaktig innenfor let-blokken. Det vil si at den nærmeste omsluttende let() som definerer en variabel er den gjeldene. That's it. Alle konstruksjoner som definerer variabler burde også definere dem i et tilsvarende skop. Prinsippet om minst overraskelse gjelder.

 

Jeg undersøkte javaspesifikasjonen nøye, for() vil faktisk lage egne bindinger som ikke gjelder utenfor. Det er dog ikke tillatt å bruke et navn som allerede finnes i skopet som iterator-navn. Greit nok.

Lenke til kommentar

Jeg har alltid trodd at for-løkker introduserte nye bindinger for variablene til venstre for "in". Men neida, de gjenbruker bindinger dersom de finnes i det leksikale skopet.

 

Er ikke dette en fordel, da? Noen ganger vil man ha bruk for å fortsette der løkken slapp, og da er det kjekt at den endelige verdien til tellervariabelen er tilgjengelig utenfor løkken.

 

Ta for eksempel nullterminerte strenger i C. Først går man gjennom strengen s med en for-løkke fra i = 0 til i < strlen(s) (som er én mindre enn lengden til arrayet). Så, når løkken er ferdig, kan man terminere strengen med s = '\0'; (som setter siste element til null).

 

Vi gjør altså en ting med elementene 1 … n − 1 og en annen med element nr. n. Hvis for-løkken hadde sitt eget skop, måtte vi først ha lagret n i sin egen variabel len, og så skrevet for(... i < len ...) og s[len] = '\0';.

 

Endret av epsil
Lenke til kommentar
Er ikke dette en fordel, da? Noen ganger vil man ha bruk for å fortsette der løkken slapp, og da er det kjekt at den endelige verdien til tellervariabelen er tilgjengelig utenfor løkken.

Enig med dette,for og og ta litt om dette i python.

Viss variabler var var lokal til for løkker sitt scope,

da ville disse løkker være ubrukelig for mange problemer.

>>> total = 0
>>> for i in range(5):
...     total += i
...     
>>> total
10

Viss for løkken hadde sitt eget scope,ville totalt blitt 0.

 

Nå skrives ofte for løkker i python som list comprehensions.

Her kan være ønskelig at variabler ikke lekker ut til global scope.

Derfor har man gjort forandinger på dette i python 3.

#python 2.7
>>> [x ** 3 for x in range(5)]
[0, 1, 8, 27, 64]
>>> x
4

#python 3
>>> [x ** 3 for x in range(5)]
[0, 1, 8, 27, 64]
>>> x
Traceback (most recent call last):
 File "<interactive input>", line 1, in <module>
NameError: name 'x' is not defined

Her får vi NameError,så x lekker ikke ut til global scope.

Endret av SNIPPSAT
  • Liker 1
Lenke til kommentar
Er ikke dette en fordel, da? Noen ganger vil man ha bruk for å fortsette der løkken slapp, og da er det kjekt at den endelige verdien til tellervariabelen er tilgjengelig utenfor løkken.

Enig med dette,for og og ta litt om dette i python.

Viss variabler var var lokal til for løkker sitt scope,

da ville disse løkker være ubrukelig for mange problemer.

>>> total = 0
>>> for i in range(5):
...     total += i
...     
>>> total
10

Viss for løkken hadde sitt eget scope,ville totalt blitt 0.

 

Her har du misforstått. Hvis løkken hadde eget skop kunne du ikke refere til "i" utenfor løkken. Hvis skopregelene er strengt leksikalske vil jo "total" være synlig inni løkken, siden den bindingen finnes i et skop som nettopp omslutter dette.

Lenke til kommentar

Er ikke dette en fordel, da? Noen ganger vil man ha bruk for å fortsette der løkken slapp, og da er det kjekt at den endelige verdien til tellervariabelen er tilgjengelig utenfor løkken.

 

 

Det er ikke alle språk som definerer hva iterator verdien faktisk er etter at løkken er ferdig. Grunnen er at da er kompilatoren litt mer fritt til å optimalisere med post increment instruksjoner, verdien blir liggende i et register og aldri skrives til memory, osv.

 

 

Man kan jo enkelt få det til ved å lage en følge variabel

 

j = -1
for i in range(5):
  sys.stdout.write("i is " + str(i) + "\n")
  j = i
sys.stdout.write("j is " + str(j) + "\n")

 

Kompilatoren kan detektere at j ikke brukes annet enn etter at loopen er ferdig og optimalisere dette slik at man ikke har en tilordning i hver iterasjon.

 

Videre så er det ikke alltid klart for seg hvordan variabler bindes.

 

Hva ville du tro at denne Python snutten skriver ut?

 

l = []
for i in range(5):
   l.append(lambda: i)
for f in l:
   sys.stdout.write("f returnerer " + str(f()) + "\n")

  • Liker 1
Lenke til kommentar

Ah, nå skjønner jeg hva du mener. Problemet her er at i språk som python er det ikke alltid en syntaktisk forskjell på variabeldeklarasjon og verditilorning. (jeg håper det er en semantisk, men python og skop er en trist historie). Nå vet ikke jeg nøyaktig hvordan python implementerer variablene sine (og implementasjoner gjør sikkert også forskellige ting her), men det ihvertfall vanlig for de fleste programmeringsspråk at det ikke vil bli noen "ny" total-variabel i eksemplet ditt, det vil si det er en tilordning og ikke en erklæring.

 

Det jeg mente var at variabler som er erklært inni løkken er bare gyldige innad. Dette inkluderer også eventuelle iterasjonsvariabler.

 

Verditilordning er en annen ting, da gir man en allerede erklært variabel en ny verdi.

Lenke til kommentar

>>> total = 0
>>> for i in range(5):
...     total += i
...     
>>> total
10

Viss for løkken hadde sitt eget scope,ville totalt blitt 0.

 

Det er iteratorvariablen man snakker om, ikke alt som finnes i kroppen til løkken.

 

Det er som det er blitt sagt her at da finnes ikke i etter loopen er ferdig. I Common Lisp blir det slik:

 

(let ((total 0))
 (loop for i from 0 below 5
    do (incf total i))
 (format t "total er ~D~%" total)
 (format t "i er ~D~%" i))

 

Kompilatoren vil skrike fordi i ikke er deklarert i scopet hvor den brukes. Dersom jeg bare tolker koden skriver den ut "total er 10" og gir en UNBOUND-VARIABLE condition.

Lenke til kommentar

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
  • Hvem er aktive   0 medlemmer

    • Ingen innloggede medlemmer aktive
×
×
  • Opprett ny...