lørdag 4. november 2017

Programmering er en sosial aktivitet

For mange er nok dette en drøy påstand. (F.eks. tror jeg min tålmodige hustru vil ha problemer med å godta den.)

Ikke desto mindre er det et aspekt som det er grunn til å legge vekt på både i en læringssituasjon og i programmering som yrkesuøvelse. I innlegget om iterativ utvikling pekte jeg på "Extreme programming" som en metode med noen interessant og anvendelige prinsipper.

  • Problemløsning foregår i grupper. Alle i en gruppe har ansvar for løsningen
  • Problemløsning foregår i små oversiktlige, veldefinerte steg.
  • Testing foregår hyppig og testene er systematiske og planlagt.
  • Parprogrammering. Det vil si at det alltid er to personer foran datamaskinen. Den ene skriver og den andre spør, foreslår og kommenterer. Rollene byttes, avhengig av oppgave eller ideer
  • De enkelte stegene sjekkes ut mot oppdragsgiver

De to punktene som peker på gruppearbeid og parprogrammering er svært relevante også for undervising. Det er dette perspektivet, læringssituasjonen, jeg har som referanse i argumentasjonen nedenfor

Parprogrammering

Med parprogrammering mener vi at det alltid skal sitte to personer foran datamaskinen. Ofte betraktes dette som en nødløsning når f.eks. en klasse ikke har mange nok datamaskiner. Tvert imot er det en arbeidssituasjone med mange fordeler.

Det skal da være slik at de to samarbeider og deler kunnskap. Den ene skriver og den andre følger med og kommenterer og gir råd. Det er flere gevinster i dette

For det første den selvsagte at de tilsammen har mer kunnskap enn de har hver for seg.

For det andre er det slik at skrivingen i seg selv ofte virker litt blokkerende på resonnementet. Den lille ekstra vurdringen som er nyttig forsvinner mens du er opptatt med innrykk og parenteser. Den som ser på har akkurat den tiden til å resonnere og stille noen spørsmål.

Et trivielt eksempel er variabelnavn. Disse har en tendens til å oppstå nesten mens fingerenn er på vei ned på tastaturet og de blir ofte veldig korte, mens de burde vært laget med tanke på leselighet og eventuell omskrivning. Selv om det kan virke som litt overdrevent i øyeblikket kan det lønne seg å kalle en variabel "antallPunkter" istedet for "n".

Sidemannen kan komme med spørsmål av typen: "hvorfor deler du på 2 før du går inn i for-løkka ?". Hvis dette skjer er grunn til enten å skrive en kommentar som forklarer hvorfor, eller kanskje det etter litt ettertanke ikke skal gjøres.

Parprogrammering er mer enn at den ene skal lære av den andre. Det er selvsagt det også men tanken er at arbeidsformen i seg selv skal på virke arbeidet i positiv retning.

Det er et viktig poeng at arbeidsdelingen mellom tastaturansvarlig og kommentator skal veksle.

Gruppearbeid

Gruppearbeid og ansvarsdeling er jo ikke noe som er spesielt for programmering, men det er mitt intrykk at det ikke har fått den plassen det fortjener og at oppgaver ikke alltid legger opp til dette.

En kan godt tenke seg at en oppgave utformes slik at ulike grupper får ansvar for ulike deloppgaver. La oss se på et eksempel (som lar seg realisere i f.eks. Processing eller p5js). Oppgaven er ikke en begynneroppgave, men jeg bruker den her for for å illustrere tankegangen.

Anta at vi vil lage en løsning som skal kunne framstille ulike typer kurver (histogram, linjer, kakediagram,..) basert på data som er tilgjengelig i ulike typer dataformater (CSV, JSON, XML). Vi kan da formulere oppgave slik at vi setter opp et skjelett der vi spesifiserer hva en datafil skal inneholde og hva datasett skal kunne levere til en tegnefunksjon, typisk: getAntallVerdier, getVerdi(n), getNavn(n), getMaxVerdi(), getTittel()

En oppgave kan da være
"lage en klasse som leser en JSON-fil og etablerer et datasett-objekt med de spesifiserte leverings funksjonene"
,( eller i programmeringstermonologi: "implemeterer det ønskede interfacet".)

En annen oppgave kan være
"Skriv en funksjon som tar et generelt datasett som parameter og tegner et histogram"

For å teste sine egne delløsninger må alle gruppene ha et skjelett som tester at det de lager fungerer. De som arbeider med datasett kan minimalisere tegningen til f.eks. å skrive ut verdier som tekst, og de som arbeider med uttegning kan etablere dataset basert på variable, uten å lese og tolke filformater.

Deling

Det går an å legge opp oppgaver slik at deling og erfaringsutveksling foregår på en mindre organisert form. I blogginnlegget En rimelig oppgave beskrives en oppgave som har som å å produsere for utskrift. En av målene med dette er å skape en situasjon der elever/studenter kan vise sine produkter, sammenligne og kanskje bruke blyant til å komme med forslag til endringer.

Dersom produksjonen foregår mot websider som kan nås av andre er selvsagt også dette en måte å dele på. Diskusjoner og forslag kan formidles på alle slags måter på nettet og i samtaler, eller kanskje i plenumsvisninger.

Programmering er iterasjoner

Utvikling av ikke-trivielle programsystemer, systemløsninger, er en prosess som innebærer handtering av kompleksitet. Det har alltid vært en utvikling og løpende diskusjon om hvordan vi best skal handtere denne kompleksiteten på en metodisk måte som sikrer oss at vi får ut noe som er sikkert og vedlikeholdbart og som produserer det oppdragsgiveren vil ha.

Historisk sett har vi alltid hatt to skoler når det gjelder systemutvikling. Det kan sies mye om dette, men en kortform kan kanskje være slik:

På den ene siden har vi hatt "fossefalls"-metoden som baserer seg på at systemet kan gjennomanalyseres og designes på tegnebrettet, og at programmeringen blir en mer eller mindre mekanisk håndtverksjobb der alle spesifikasjonene er klare. Fordelene med dette er at vi gjøre en komplett analyse og lokaliserer alle de kritiske punktene i en tidlig fase av arbeidet. Ulempene er at verken utviklere eller oppdragsgiver er i stand til å se konsekvensene av krav eller beslutninger.

På den andre siden har vi hatt den iterative skolen som har har som basis at løsningen skal opp og stå fra dag en, og at den raffineres stegvis etter konsultasjon med oppdragsgiver. Fordelene er at vi avdekker designproblemer tidlig og at vi kan tilpasse oss erfaringene. Ulempene er at vi har dårligere kontroll over tidsplan og progresjon.

Det er den siste angrepsvinkelen som ser ut til å dominere programmeringsfagetfaget idag, og det er denne, som slik jeg ser det, er relevant for programmeringsundervisning. Det er de seneste årene utviklet noen tankesett som i aller høyeste grad er relevante.

Når vi sier at en metode er iterativ mener vi at vi definerer delmål og går fram stegvis. En sammenhengende metode som skal ivareta en slik arbeidsform er "Extreme Programming". Til tross for det noe dramatiske navnet er dette en jordnær arbeidsform som bygger på en del lettforståelige og effektive prinsipper. Slik vi ser det er disse prinsippene høyst aktuelle i programmeringsundervisning. De viktigste prinsippene, som vi bør vurdere, er:

  • Problemløsning foregår i grupper. Alle i en gruppe har ansvar for løsningen
  • Problemløsning foregår i små oversiktlige, veldefinerte steg.
  • Testing foregår hyppig og testene er systematiske og planlagt.
  • Parprogrammering. Det vil si at det alltid er to personer foran datamaskinen. Den ene skriver og den andre spør, foreslår og kommenterer. Rollene byttes, avhengig av oppgave eller ideer
  • De enkelte stegene sjekkes ut mot oppdragsgiver

De momentene som tar opp de sosiale aspektene og de som handler konkret omfeilretting er drøftet for seg. La oss se litt nærmere på iterasjonsperspektivet.

Vi kan se på et enkelt eksempel. Oppdraget er formulert slik:

 Tegn en windmølle

Steg 1

løsning

Tilbakemelding på dette vil typisk være at en windmølle har tre blader, ikke 2

Steg 2

løsning

Tilbakemelding på dette vil kanskje være at møllebladne må jo festes på et hus

Steg 3

løsning

Og så vil vi måtte vurdere om bladene skal ha en annen form og hvordan huset skal utformes. Kanskje vi skal la oss inspirere til å la brukeren bestemme vindstyrken ?

Det er flere ting å merke seg med dette enkle eksempelet.

  • Selv et enkelt eksempel som dette demonstrerer at det kan være nødvendig å gå stegvis fram.
  • Den som har vært gjennom programmeringsøvelser av denne typen noen ganger vil trolig lære å lage kode som er forberedt for endringer.
  • Ambisjonsnivået har en tendens til å øke etterhvert som løsningen utvikler seg. Dette er vel ikke alltid like bra og vi kan fort nærme oss det som er et problem for mange programmerere, et slags perfeksjonistsyndrom. Ting kan alltid bli bedre.
  • Presisjonen i oppgaven kunne vært klarere i utgangspuktet, selv om intensjonen trolig var å lansere en enkel øvelse i vinkelberegning.

Hvis vi summerer opp noe av dette så er vi fort over på det som er et kjent problem i iterativ programutvikling, og som på engelsk kalles "the planning game". Essensen i dette er at en slik iteartiv arbeidsform med små steg med egne tidsfrister ofte kommer i konflikt med det som er rimelig eller avtalt som total utviklingstid. Det er åpenbart at dette kan være en vanskelig problemstilling i næringslivet, men det er også verdt å merke seg at denne problemstillingen er relevant også i undervisning.

Det finnes mange metoder innen programmering som er nær beslektet med Extreme Programming, f.eks. Scrum som også har et eksplisitt beskrivelse av kreative faser i arbeidet

Linker

Extreme Programming
Scrum

fredag 3. november 2017

Programmering er en kreativ prosess

De fleste som betrakter programmering utenfra, altså uten å programmere selv, oppfatter det ofte som en slags øvelse i å skrive firkanta og uleselig tekst. Når det gjelder å skape nysgjerrighet og inspirere potensielle programmerere er det viktig å ta et slags oppgjør med slike holdninger. (nerdenes protest !).

Det er en generell og vanskelig diskusjon å vurdere innholdet i begrepet kreativitet. Et ganske vanskelig utgangspunkt er de som ensidig kopler begrepet til å komme opp med ideer uten å relatere det til verken handverkskompetanse eller gjennomføringsmuligheter. I og for seg en spennende aktivitet, men ikke nødvendigvis særlig produktiv. Det er min erfaring at en god del studenter som søker utdanning innen områder som digital design er hengt opp i et slikt holdningssett. De får ganske raskt sperrer når de innser at realisering av selv ganske enkle ideer krever både håndverk og systematisk planlegging. Det gjelder selvsagt ikke alle.

Det ligger en utfordring i å forsøke å få fram det kreative elementet i programmering, både for de som savner det og for de som ikke savner det. Etter min erfaring ligger de kreative utfordringene både i det du lager, produktet, og måten du konstruerer det på

Produktet

Mye av det vi som programmerere lager har et visuelt og ofte interaktivt grensesnitt mot brukeren. Vi skal presentere websider som helst skal fungere optimalt på ulike typer media, og vi skal lage konstrukjsoner som skal kunne vurderes og diskuteres ut fra utseende og funksjonalitet uten å kjenne alle detaljer i det som ligger bak. Det finnes naturlig nok metoder for å handtere prosesser for å finne gode løsninger som i stor grad følger aksepterte standarder, men det finnes også et stort rom for kreative, utradisjonelle løsninger

Spillprogrammering er på mange måter en historie for seg. Et spill skal formidle en setting, en metafor, og det skal implementere avansert interaksjon mellom spillere og mellom en spiller og de digitale omgivelsene.

Hvis vi setter dette inn i en opplæringssammenheng er det viktig å finne verktøy og oppgaver som utfordrer de kreative egenskapene. Det gjelder valg av programmeringsspråk og det gjelder valg av arbeisoppgaver. Vi må finne fram til oppgaver som hver for seg og i sammenheng gir en rask visuell respons på det som lages og som inviterer til å eksperimentere med løsninger.

For meg er det naturlig å se dette i sammenheng med de prinsippene som er nedfelt i Alan Kays referanse til Piaget når han bruker begrepet "Doing with Images Makes Symbols". Selv om Kays perspektiv i utgangspunktet ikke nødvendigvis er det kreative perspektivet, så er sammenhengen mellom konstruksjon og resultat et fundamentalt moment, på linje med det vi finner i tankegangen bak programmeringsspråket Logo. Vi må altså finne arbeidsoppgaver det det er kort vei fra programmeringen til den visuelle responsen. Jeg har skrevet mer om dette i innleggene "Piaget og programmering" og "En rimelig oppgave"

Det er også viktig å utvide perspektivet ut over "vanlige" skjermorientert programmer. Programmering av enheter av ymse slag som Lego, Arduino-enheter eller 3D-printing er en del av dette bildet.

Resonnementene mine over er direkte eller indirekte knyttet til en eller annen form for funksjonalitet. Vi vil finne kreative og gode løsninger for å vise fram noe eller gjøre det lett for brukeren av programmet å interagere med det vi lager. Det perspektivet som mangler er det som bruker digitale medier til å uttrykke noe. Det kan være et kunstverk, eller det kan være noe som skal promotere noe, en begivenhet, en sak eller et produkt, det vi kan kategorisere som reklame i vid forstand.

Mediene for dette er mange: Websider, TV, digitale plakater, projeksjoner på bygninger osv. For en programmerer som ser slikt materiale er det ikke vanskelig å se at det ligger ganske mye finurlig programmering bak for å få fram effekter av ulike slag, 3D-former, lyssetting, animasjon, relasjoner mellom objekter, for å nevne noen.

Et lite eksempel.

Dette eksempelet er ikke for å antyde at jeg er kunstner eller kunstekspert. Hensikten er bare å peke på at en digital innfalsvinkel kan gjøre noe med perspektivet

Den belgiske kunstneren Renè Magritte malte (første gang) i 1926 et bilde av en pipe som har tiltrukket seg en del oppmerksomhet. Som du ser på bildet under har han malt på bildet en tekst "Ceci n'est pas une pipe", eller på norsk "dette er ikke en pipe". Når Magritte ble spurt om hvordan han kunne mene dette svarte han: "Forsøk å stappe tobakk i den".

Det han forsøker å gjøre er altså å fokusere på forskjellen på en gjenstand og framstillingen av den. Det ligger langt utenfor min kompetanse å forsøke og forklare på en kort og konsistent måte surrealismens vesen og surrealistenes argumentasjon. Slik jeg oppfatter det, anser de en naturalistisk framstilling som lite interessant, og de forsøker å legge det "usynlige" inn i bildene. Magrittes naturalistiske bilde, med den gitte teksten, er slik forstått å understreke avstanden mellom bilde og "natur". De fleste av Magrittes bilder er ikke av denne naturtro typen. Tvert imot bruker han og andre surrealister argumentet til å endre den naturen han framstiller.

Hvis jeg nå, fra mitt teknologiske ståsted, vil ta dette et skritt videre kan jeg kanskje påstå om konstruksjonen nedenfor at "dette er ikke et bilde av en pipe" (Ceci n'est pas une image d'une pipe).

Med dette forstår jeg da at det finnes ikke noe fysisk bilde av noe som ser slik ut som det du ser på skjermen. Bildet skapes og gjenskapes hver gang vi ønsker å se det, i en eller annen synsvinkel.

Så kan man jo spørre seg hva surrealistene midt i forrige århundre ville ha laget dersom de kunne programmere interaktive framstillinger. I vår tid er det ikke akkurat mangel på manipulerte bilder med et visst "surrealistisk" preg.

Man kunne jo tenke seg at kommunikasjonsflaten mellom kunstner og publikum ville tjene på en dialog. Eller kanskje surrealismen ikke ville oppstått i den formen den fikk, dersom teknologien og mediebildet hadde vært som idag ?

For de som husker den første bølgen av digital kunst på 80-tallet har det skjedd mye med forutsetningen, men kanskje ikke like mye med aktiviteten ? Den gangen var det mitt inntrykk at det som ble vist fram var mislykkede eller manipulerte sirkelalgoritmer.

Konstruksjonen

Det som er vanskeligst å kommunisere til ferske programmerere er den kreative utfordringen og potensielle tilfredsstillelsen som ligger selve programmeringen.

Vi har i prinsipp nærmest ubegrensede muligheter når vi skal velge hvordan vi dekomponerer et problem og hvordan vi formulerer algoritmer.

Den metaforen som dukker opp i hodet mitt når jeg sliter med å finne "gode" løsninger er et slags landskap, med noen faste fjellformasjoner jeg kjenner igjen og noen uoversiktlige steinrøyser. For meg er det en kreativ utfordring å få orden på steinrøysene og stable stein i solide murer. En stein ligger ikke støtt hvis ikke underlaget er til å stole på. Når jeg står der med en stein i hånda har jeg mange muligheter og utfordringen er å finne en løsning som kan bringe meg videre.

Nå er det selvfølgelig slik at løsninger av den typen vi har vært innom ovefor i varierende grad er lagarbeid. Alle er ikke programmerere. Jeg tror imidlertid at det er slik at en viss insikt i prorammering er en forutsetning for å delta i et slikt lagarbeid på en konstruktiv måte.

Formidling av dette er etter min erfaring ganske vanskelig. For nye programmerere er ikke føleksen av handlefrihet så stor som den er hos de som har prøvd og feilet mange ganger. Igjen så dukker behovet for å kunne visualisere løsningen og å finne oppgaver som har kort vei fra kode til respons opp.

Linker

Piaget og programmering
En rimelig oppgave
Logo

torsdag 2. november 2017

Programmering er kopiering

Når vi skal løse et programmeringsproblem skriver vi i praksis aldri et program på blanke ark. Hovedregelen er at vi begynner jobben med å endre et program vi eller andre har skrevet før. Det vi tar med oss fra det vi kopierer fra kan være alt fra rene formalia som er nyttig eller nødvendig i alle programmer i det aktuelle språket, eller det kan være store deler av koden.

Praksis

Det kan være mange kilder for slik kopiering og omskriving.

Egne programmer

Dette gjør vi alltid og det er nyttig og i praksis nødvendig. Det er imidlertid noen momenter som en skal merke seg.

Det er lett å dra med seg dårlige løsninger og dårlige vaner uten å tenke på det, og det kan være at vi drar med oss løsninger eller lenker til ting som har gått ut på dato. De erfaringene vi gjør kan tilsi at vi bør gjøre noen endringer på "standardene" våre.

For eksempel bruker jeg alltid disse to filene når jeg starter arbeidet med en p5js-sketch:

<!DOCTYPE HTML>
<html lang="no">
<head>
 <meta charset="UTF-8"/> 
 <title>test</title> 
 <script src="https://borres.hiof.no/resources/p5js/p5.min.js">  
 </script>
 <script src="sketch.js"> </script>
</head>
<body> 
<div id="canvasHere"></div>
</body>
</html>
function setup() {
   var canvas = createCanvas(400, 400);
   canvas.parent('canvasHere');
}
function draw() {
   background(255,255,255);
   stroke(0,0,255);
   line(0,height/2,width,height/2);
}

lagrer dem som "test.html" og "sketch.js", åpner dem i editoren og jeg er i gang.

Min erfaring er at det er lett å undervurdere nytten av å skrive kommentarer til de løsningene vi bruker, både i selve koden og gjerne i en egen fil i det prosjektet vi arbeider med. Det er av og til forbløffende vanskelig å lese og endre sin egen kode som ble skrevet for noen måneder siden. Når vi skriver kode etablerer vi ofte et sett med logiske forutsetninger som vi sliter med å rekonstruere i en annen setting. Jeg har lært meg å lage en "readme.txt"-fil som har som eneste hensikt å forklare forutsetningene og løsningen for meg selv.

Medarbeideres programmer

Hvis vi arbeider sammen med andre i et prosjekt er dette både nødvendig og naturlig. Det bidrar til at flere øyne leser og flere tester blir gjort. I en startfase i programmering er det naturlig å bruke ganske enkle delingsmekanismer, som tilgang til en felles datalagringsplass og et eller annet kommunikasjonsmedium for å varsle om oppdateringer og endringer. Etterhvert er det naturlig å ta i bruk mer avanserte verktøy for versjonering.

Det er en rekke utviklingsmetodikk som på ulike måter og med ulike begrunnelser beskriver samarbeid i programutvikling og kodeproduksjon

Medstudenters programmer

I en studiesituasjon er dette en litt vanskelig problemstilling. På den ene siden er det åpenbart at det å dele erfaringer, ideer og programmer er et udiskutabelt gode. Når det gjelder gruppearbeid er situasjonen i prinsipp den samme som kommentert over.

På den andre siden er det vel alle underviseres erfaring at det foregår en del ureflektert kopiering for å bli ferdig med obligatoriske oppgaver innen tidsfristen. Det skjer uavhengig av tilbud om hjelp og veiledning. Det er av og til fristende som underviser ha en kynisk holdning til dette: Vil du ikke lære så er det din egen beslutning. På den annen side er det elementer i oppstart av en programmeringsundervisning som kan virke demotiverende på mange og føre til at arbeidsinnsatsen utesettes. Først og fremst gjelder dette trolig opplevelsen av å gjøre feil, av å mislykkes. Jeg har drøftet feilrettingsperspektivet i en annen artikkel.

Eksempler fra læremateriell

Dette er rimeligvis en god kilde, selv eksempler av og til kan være litt ensidige

Eksempler som er distribuert sammen med det utviklingsystemet vi bruker

Det varierer veldig hvor mye materiell som distribueres eller gjøres tilgjengelig i forbindelse med utviklingssystemer. Noen er eksemplariske gode og har svar på akkurat det vi lurer på. Det som ofte er et problem er at nivået på koden ikke er tilpasset nybegynnere.

Programmer vi finner på nettet

Dette er en interessant problemstilling og det er en del forhold som skiller programmering fra de fleste andre fagområder.

For det første er det en sterk kultur for å dele. Du vil finne forslag og forklaringen av de forunderligste problemer. Det finnes en rekke åpne utviklingsprosjekter der kode i nær sagt alle kompleksitetsgrader er tilgjengelige.

For det andre er det en slags "The truth is in the pudding" situasjon. Vi kan i de fleste tilfeller teste det vi finner og sjekke om det gjør det det gir seg ut for. Vi trenger normalt ikke gjøre systematisk bakgrunnssjekking for å se om noe er "sant". Dette er selvsagt ikke tilfeller der vi er ute etter mer avanserte systemer som f.eks. statistikkprogrammer eller lignende.

Metodisk

Som beskrevet over er kopiering og omskriving av kode en praksis som vi ikke greier oss uten, og etter mitt syn spiller det en avgjørende i rolle i læring. Det er interessant å se om vi kan finne angrepsvinkler der vi kan bruke kodekopiering systematisk i en oppstartfase.

Når det gjelder den grunnleggende forståelsen av syntaks og enkel algoritmeutforming kunne en tenke seg å la studentene få tilgang til kodebiter skrevet i forskjellige språk. Studentenes oppgave blir å forsøke å finne ut hva koden gjør og hva som må endres for å endre funksjonaliteten.

Vi kan illustrere det med et enkelt eksempel. Vi tar for oss en funksjon som skal summere tall fra 1 og opp til en grense. Vi kan se på dette i flere språk.

Java

int tall(int n){
  int sum=0;
  for(int i=1; i < n; i=i+1)
    sum=sum+i;
  return sum;
}
print tall(5);

JavaScript

function tall(n){
  var sum=0;
  for(var i=1; i < n; i=i+1)
    sum=sum+i;
  return sum
}
console.log(tall(5));

Python

def tall(n):
  sum=0
  for i in range(1,n):
    sum=sum+i
  return sum

print tall(5)

Basic

PRINT tall(5);

FUNCTION tall(n)
    sum=0
    FOR i = 1 TO n-1
        sum= sum + i
    NEXT i
    tall=sum
END FUNCTION

Det vi muligens kunne oppnå med dette er å illustrere noen prinsipper som er allmengyldige og det lar oss betrakte løsningen med litt forskjellige perspektiv. Det gir oss en anledning til å diskutere datatyper og syntaksregler.

Nå vil det være praktisk umulig å sette i gang en paralell prosess der vi inviterer studentene til å eksperimentere med flere utviklingsmiljøer. Den administrative jobben med å holde styr på omgivelsene vil trolig bli lang mer omfattende enn selve kodingen.

Vi kunne tenke oss et scenario der studentene arbeider, f.eks med JavaScript og undervisningen har innslag av kommenterte løsningsforslag i andre språk.

En åpenbar innvending er at dette er en veldig formalistisk angrepsvinkel og det vil neppe fungere som dominerende arbeidsform. Det kunne muligens brukes som et supplement, ikke i den kreative prosessen, men som en måte å få grep om noen syntaktiske og algoritmiske problemstillinger.