Jackson strukturerad programmering
Jackson strukturerad programmering ( JSP ) är en metod för strukturerad programmering utvecklad av den brittiske mjukvarukonsulten Michael A. Jackson och beskrivs i hans bok från 1975 Principles of Program Design . Tekniken för JSP är att analysera datastrukturerna för filerna som ett program måste läsa som input och producera som output, och sedan producera en programdesign baserad på dessa datastrukturer, så att programkontrollstrukturen hanterar dessa datastrukturer i en naturlig och intuitivt sätt.
JSP beskriver strukturer (av både data och program) med hjälp av tre grundläggande strukturer – sekvens, iteration och urval (eller alternativ). Dessa strukturer visas i diagram som (i praktiken) en visuell representation av ett reguljärt uttryck .
Introduktion
Michael A. Jackson utvecklade ursprungligen JSP på 1970-talet. Han dokumenterade systemet i sin bok från 1975 Principles of Program Design . I ett konferenssamtal 2001 gav han en retrospektiv analys av de ursprungliga drivkrafterna bakom metoden, och relaterade den till efterföljande mjukvaruutveckling. Jacksons mål var att göra COBOL batch-filbehandlingsprogram lättare att modifiera och underhålla, men metoden kan användas för att designa program för alla programmeringsspråk som har strukturerade kontrollkonstruktioner - sekvens, iteration och urval ("om/då/annan") .
Jackson Structured Programming liknade Warnier/Orrs strukturerade programmering även om JSP tog hänsyn till både input- och outputdatastrukturer medan Warnier/Orr-metoden nästan uteslutande fokuserade på strukturen för utströmmen.
Motivation för metoden
Vid den tidpunkt då JSP utvecklades var de flesta programmen batch-COBOL-program som behandlade sekventiella filer lagrade på band. Ett typiskt program läste igenom sin indatafil som en sekvens av poster, så att alla program hade samma struktur - en enda huvudslinga som bearbetade alla poster i filen, en i taget. Jackson hävdade att denna programstruktur nästan alltid var fel, och uppmuntrade programmerare att leta efter mer komplexa datastrukturer. I kapitel 3 i Principer för programdesign presenterar Jackson två versioner av ett program, en designad med JSP, den andra med den traditionella enkelslingastrukturen. Här är hans exempel, översatt från COBOL till Java. Syftet med dessa två program är att känna igen grupper av upprepade poster (rader) i en sorterad fil, och att producera en utdatafil som listar varje post och antalet gånger som det förekommer i filen.
Här är den traditionella versionen med en slinga av programmet.
0
0
Stränglinje ; _ int count = ; String firstLineOfGroup = null ; // start single main loop while (( line = in . readLine ()) != null ) { if ( firstLineOfGroup == null || ! line . equals ( firstLineOfGroup )) { if ( firstLineOfGroup != null ) { System . ut . println ( firstLineOfGroup + " " + count ); } räkna = ; firstLineOfGroup = linje ; } räkna ++ ; } if ( firstLineOfGroup != null ) { System . ut . println ( firstLineOfGroup + " " + count ); }
Här är en JSP-liknande version av samma program. Observera att det (till skillnad från det traditionella programmet) har två slingor, en kapslad inuti den andra. Den yttre slingan bearbetar grupper av upprepade poster, medan den inre slingan bearbetar de individuella posterna i en grupp.
0
Stränglinje ; _ int numberOfLinesInGroup ; linje = i . readLine (); // börja yttre slinga: process 1 group while ( line != null ) { numberOfLinesInGroup = ; String firstLineOfGroup = line ; // börja inre loop: bearbeta 1 post i gruppen medan ( line != null && line . equals ( firstLineOfGroup )) { numberOfLinesInGroup ++ ; linje = i . readLine (); } System . ut . println ( firstLineOfGroup + " " + numberOfLinesInGroup ); }
Jackson kritiserar den traditionella single-loop-versionen för att den misslyckas med att bearbeta strukturen för indatafilen (upprepade grupper av poster som innehåller upprepade individuella poster) på ett naturligt sätt. Ett tecken på dess onaturliga design är att den, för att fungera korrekt, är tvungen att inkludera en speciell kod för att hantera den första och sista posten i filen.
Den grundläggande metoden
JSP använder semiformella steg för att fånga den befintliga strukturen av ett programs in- och utdata i själva programmets struktur.
Avsikten är att skapa program som är lätta att modifiera under sin livstid. Jacksons stora insikt var att kravändringar vanligtvis är mindre justeringar av de befintliga strukturerna. För ett program som är konstruerat med JSP, matchar ingångarna, utgångarna och programmets interna strukturer, så små ändringar av ingångarna och utgångarna bör översättas till små ändringar i programmet.
JSP strukturerar program i termer av fyra komponenttyper:
- grundläggande verksamhet
- sekvenser
- iterationer
- urval
Metoden börjar med att beskriva ett programs indata i termer av de fyra grundläggande komponenttyperna. Den fortsätter sedan med att beskriva programmets utgångar på samma sätt. Varje ingång och utgång är modellerad som ett separat Data Structure Diagram ( DSD). För att få JSP att fungera för datorintensiva applikationer, såsom digital signalbehandling (DSP) är det också nödvändigt att rita algoritmstrukturdiagram, som fokuserar på interna datastrukturer snarare än in- och utdatastrukturer.
Ingångs- och utdatastrukturerna förenas sedan eller slås samman till en slutlig programstruktur, känd som ett programstrukturdiagram (PSD). Detta steg kan innebära tillägg av en liten mängd kontrollstruktur på hög nivå för att kombinera ingångarna och utgångarna. Vissa program bearbetar all inmatning innan de gör någon utmatning, medan andra läser in en post, skriver en post och itererar. Sådana tillvägagångssätt måste fångas i PSD.
PSD, som är språkneutral, implementeras sedan i ett programmeringsspråk. JSP är inriktat på programmering på kontrollstrukturnivå, så de implementerade designerna använder bara primitiva operationer, sekvenser, iterationer och val. JSP används inte för att strukturera program på nivån av klasser och objekt, även om det på ett användbart sätt kan strukturera kontrollflödet inom en klasss metoder.
JSP använder en diagramnotation för att beskriva strukturen för ingångar, utgångar och program, med diagramelement för var och en av de grundläggande komponenttyperna.
En enkel operation ritas som en ruta.
En sekvens av operationer representeras av rutor förbundna med linjer. I exemplet nedan är A en sekvens som består av operationerna B, C och D.
En iteration representeras återigen med sammanfogade rutor. Dessutom har den itererade operationen en stjärna i det övre högra hörnet av sin ruta. I exemplet nedan är A en iteration iteration av noll eller fler anrop av operation B.
Urval liknar en sekvens, men med en cirkel ritad i det övre högra hörnet av varje valfri operation. I exemplet är A ett urval av en och endast en av operationerna B, C eller D.
Observera att det i ovanstående diagram är element A som är sekvensen eller iterationen, inte elementen B, C eller D (som i ovanstående diagram är alla elementära). Jackson ger 'Look-down-regeln' för att bestämma vad ett element är, dvs titta på elementen under ett element för att ta reda på vad det är.
Ett fungerande exempel
Som ett exempel, här är hur en JSP-programmerare skulle designa och koda en körlängdskodare . En körlängdskodare är ett program vars indata är en ström av byte som kan ses som att den förekommer i körningar , där en körning består av en eller flera förekomster av byte med samma värde. Utdata från programmet är en ström av bytepar, där varje bytepar är en komprimerad beskrivning av en körning. I varje par är den första byten värdet på den upprepade byten i en körning och den andra byten är ett tal som anger antalet gånger som det värdet upprepades i körningen. Till exempel skulle en körning av åtta förekomster av bokstaven "A" i ingångsströmmen ("AAAAAAAA") producera "A8" som ett bytepar i utströmmen. Körlängdskodare används ofta för att grovt komprimera bitmappar.
Med JSP är det första steget att beskriva datastrukturen(-erna) för ett programs indataström(ar). Programmet har bara en ingångsström, bestående av noll eller fler körningar med samma bytevärde. Här är JSP-datastrukturdiagrammet för ingångsströmmen.
Det andra steget är att beskriva utdatastrukturen, som i detta fall består av noll eller fler iterationer av bytepar.
Nästa steg är att beskriva överensstämmelsen mellan komponenterna i input- och outputstrukturerna.
Nästa steg är att använda överensstämmelsen mellan de två datastrukturerna för att skapa en programstruktur som är kapabel att bearbeta indatastrukturen och producera utdatastrukturen. (Ibland är detta inte möjligt. Se diskussionen om strukturkrockar nedan.)
När programstrukturen är klar skapar programmeraren en lista över de beräkningsoperationer som programmet måste utföra, och programstrukturdiagrammet kompletteras genom att hänga dessa operationer från de lämpliga strukturella komponenterna.
- läsa en byte
- kom ihåg byte
- ställ räknaren till noll
- inkrementräknare
- output ihågkommen byte
- utgångsräknare
I detta skede listas också villkor för iterationer (loopar) och val (if-then-else eller fallsatser) och läggs till i programstrukturdiagrammet.
- medan det finns fler byte
- medan det finns fler byte och denna byte är samma som körningens första byte och antalet kommer fortfarande att passa i en byte
När diagrammet är klart kan det översättas till vilket programmeringsspråk som helst som används. Här är en översättning till C.
#include <stdio.h> #include <stdlib.h> int main ( int argc , char * argv []) { int c ; int first_byte ; int count ; c = getchar (); /* få första byten */ while ( c != EOF ) { /* bearbeta den första byten i körningen */ first_byte = c ; räkna = 1 ; c = getchar (); /* få nästa byte */ /* bearbeta de efterföljande byten i körningen */ while ( c != EOF && c == first_byte && count < 255 ) { /* bearbeta en byte med samma värde */ count ++ ; c = getchar (); /* få nästa byte */ } putchar ( first_byte ); putchar ( antal ); } returnera EXIT_SUCCESS ; }
Tekniker för att hantera svåra designproblem
I principer för programdesign kände Jackson igen situationer som utgjorde specifika typer av designproblem och gav tekniker för att hantera dem.
En av dessa situationer är ett fall där ett program behandlar två indatafiler, snarare än en. 1975 var ett av de vanliga "onda problemen" hur man designade ett transaktionsbearbetningsprogram. I ett sådant program körs en sekventiell fil med uppdateringsposter mot en sekventiell huvudfil, vilket ger en uppdaterad huvudfil som utdata. (Till exempel, på natten skulle en bank köra ett batchprogram som skulle uppdatera saldona på sina kunders konton baserat på register över insättningar och uttag som de hade gjort den dagen.) Principer för programdesign gav en standardlösning för det problemet , tillsammans med en förklaring av logiken bakom designen.
En annan sorts problem handlade om vad Jackson kallade "igenkänningssvårigheter" och idag skulle vi kalla parsingsproblem. Den grundläggande JSP-designtekniken kompletterades med POSIT- och QUIT-operationer för att möjliggöra designen av vad vi nu skulle kalla en backtracking-parser.
JSP kände också igen tre situationer som kallas "strukturkrockar" - en gränskrock, en beställningskrock och en interleaving-krock - och tillhandahöll tekniker för att hantera dem. I strukturkrockssituationer är in- och utdatastrukturerna så inkompatibla att det inte är möjligt att producera utdatafilen från indatafilen. Det är faktiskt nödvändigt att skriva två program – det första bearbetar inmatningsströmmen, bryter ner den i mindre bitar och skriver dessa bitar till en mellanfil. Det andra programmet läser den mellanliggande filen och producerar önskad utdata.
JSP och objektorienterad design
JSP utvecklades långt innan objektorienterad teknologi blev tillgänglig. Den och dess efterföljande metod JSD behandlar inte det som nu skulle kallas "objekt" som samlingar av mer eller mindre oberoende metoder. Istället, efter CAR Hoares arbete , beskriver JSP och JSD mjukvaruobjekt som samrutiner .
Se även
externa länkar
- En gratis grafisk JSP Editor skriven i JAVA
- En JSP-redigerare
- En kort historik om Jackson-metoderna
- Jackson Workbench webbplats