Programmering

Introduktion til "designteknikker"

På sidste års JavaOne-konference deltog jeg i en session, hvor højttaleren talte om Suns plan for den virtuelle Java-maskine (JVM). I denne samtale sagde højttaleren, at Sun blandt andet planlagde at rydde op på nuværende præstationsflaskehalse i sin virtuelle maskine, som f.eks. Langsomme synkroniserede metoder og ydeevneomkostningerne ved affaldsindsamling. Højttaleren sagde Suns mål: Med forbedringerne af JVM behøver programmører ikke at tænke på at undgå virtuelle maskineflaskehalse, når de designede deres programmer; de behøver kun at tænke på at skabe "gode objektorienterede, trådsikre designs."

Højttaleren uddybede imidlertid ikke, hvad der faktisk udgør et godt objektorienteret, trådsikkert design. Det er målet med denne nye kolonne. Gennem artiklerne i Designteknikker kolonne, håber jeg at besvare spørgsmålet: Hvad er et godt Java-programdesign, og hvordan opretter du et?

Kolonnens fokus

Mit fokus i denne kolonne vil være at give praktiske designteknikker, som du kan bruge til dine daglige programmeringsopgaver. Jeg antager, at du er fortrolig med Java-sproget og API'erne. Jeg planlægger at diskutere teknikker, ideer og retningslinjer, der hjælper dig med at bruge sproget og API'erne i dine virkelige programmer.

For at give dig en idé om, hvad du kan forvente i denne kolonne, er her en liste over de slags emner, jeg planlægger at skrive om:

  • Måder til at forbedre designet af dine objekter
  • Bygge klassehierarkier
  • Hvad er grænseflader til?
  • Hvad er pointen med polymorfisme?
  • Valg mellem komposition og arv
  • Design for trådsikkerhed
  • Design til trådsamarbejde
  • Model / Controller / View-arkitekturen, der bruges af JFC-klasser
  • Design mønstre

Meget af det materiale, der allerede er skrevet om softwaredesign, kan anvendes på Java. Der er mange komplette designmetoder og tykke lærebøger, der beskriver dem. I denne kolonne vil jeg ikke promovere en metode frem for en anden. Jeg vil heller ikke fremme en ny metode til min egen opfindelse. Snarere vil jeg trække på og kombinere indsigter, som jeg har fået gennem flere eksisterende metoder og fundet nyttige i min egen programmeringspraksis.

Den tilgang til design, som jeg vil anbefale i disse artikler, stammer fra mine erfaringer gennem årene i kabinen: Designe ny software, forbedre gammel software, vedligeholde software skrevet af andre, vedligeholde software skrevet af mig selv, arbejde med forskellige sprog, værktøjer, computere og andre programmerbare maskiner. Min designfilosofi vil være meget "kabinetorienteret": baseret på og rettet mod kommerciel programmering i den virkelige verden.

Denne måned: Process beskrevet, "design" defineret

I denne indledende artikel i Designteknikker kolonne, vil jeg give en detaljeret redegørelse for begrebet softwaredesign baseret på min egen erfaring som udvikler. I den resterende del af denne artikel vil jeg diskutere processen med softwareudvikling og forklare, hvad jeg mener med udtrykket "design".

Softwareudviklingsprocessen

Efter min erfaring har processen med softwareudvikling tendens til at være temmelig kaotisk. Teammedlemmer kommer og går, kravene ændres, tidsplanerne ændres, hele projekter bliver annulleret, hele virksomheder går ud af drift osv. Programmørens job er at med succes navigere i dette kaos og til sidst producere et "kvalitets" produkt på en "rettidig" måde.

Udover at være kaotisk har softwareudviklingsprocessen også en tendens til at være ret iterativ. Da et softwareprodukt udvikles, udvikler det sig kontinuerligt baseret på feedback fra mange parter. Denne iterative proces fungerer fra frigivelse til frigivelse (hver udgivelse er en iteration) og inden for udviklingscyklussen for en enkelt udgivelse. Fra frigivelse til frigivelse, for eksempel, angiver feedback fra kunder med den aktuelle version, hvilke fejlrettelser og forbedringer der er vigtigst at lave i den næste version. Inden for udviklingscyklussen for en enkelt frigivelse justeres visionen om slutmålet løbende af kræfter i virksomheden, når udviklingen skrider frem.

På trods af kaos og iteration har jeg imidlertid fundet ud af, at de fleste udviklingsteam forsøger at håndhæve en vis struktur i deres udviklingsindsats. Med henblik på denne kolonne vil jeg løst opdele softwareudviklingsprocessen for en enkelt frigivelsescyklus i disse fire faser:

  1. Specifikation
  2. Design
  3. Implementering
  4. Integration og test

Med disse fire faser har jeg til hensigt at fange en struktur, som jeg har observeret i de fleste softwareudviklingsprojekter. Fordi hver virksomhed er forskellig, hvert team er forskelligt, og hvert projekt er forskelligt, udgør disse fire faser kun en grov oversigt over en typisk udviklingscyklus. I praksis kan nogle faser springes over eller ske i en anden rækkefølge. Og fordi den iterative karakter af softwareudvikling har en tendens til at boble op gennem enhver pålagt struktur, kan disse faser til en vis grad overlappe hinanden eller bløde ind i hinanden.

Når jeg taler om design i Designteknikker kolonne, jeg taler om de aktiviteter, der finder sted i trin to på ovenstående liste. For at give dig en bedre idé om, hvad jeg mener med hver fase, beskriver jeg hver enkelt i de næste fire sektioner.

Fase 1: Angivelse af problemdomænet

Det specifikationsfase af et softwareprojekt involverer at samle alle de berørte parter for at diskutere og definere slutproduktet af softwareudviklingsprocessen. Under specifikationen definerer du "visionen" - det mål, du vil sigte mod i resten af ​​projektet. Det leverede, der skulle komme ud af specifikationsfasen, er et skriftligt dokument, der definerer softwaresystemets krav.

Kravspecifikationen ligner meget en kontrakt. Det er en kontrakt mellem alle de berørte parter, men vigtigst af alt fra udviklerens synspunkt er det en kontrakt mellem udvikleren og den part, der ønsker slutproduktet i første omgang: måske en klient, en kunde, ledelse eller marketingafdelingen . Når en specifikation er aftalt i tal, men ikke er nedskrevet, er det grundlæggende en mundtlig kontrakt. Selvom en mundtlig kontrakt er juridisk bindende, er det i mange tilfælde en opskrift på problemer. Forskellige mennesker har tendens til at have forskellige erindringer om mundtlige aftaler, især når det kommer til detaljer. En uenighed om detaljer er endnu mere sandsynlig, hvis detaljerne aldrig blev drøftet som en del af den mundtlige aftale i første omgang, hvilket er et fælles træk ved mundtlige kontrakter.

Når alle involverede parter mødes og prøver at nedskrive kravene til et softwareprojekt, tvinger det en udforskning af problem domæne. Problemdomænet er slutproduktet beskrevet på et menneskeligt (ikke computerprogrammeringssprog). Det samme slutprodukt udtrykt på et computersprog er løsningsdomæne. I løbet af udforskningen af ​​problemdomænet kan mange tvetydige detaljer identificeres og diskuteres, og uenigheder kan løses lige fra starten.

En god specifikation giver dig et veldefineret mål at sigte efter, mens du udvikler dig. Men det garanterer ikke, at målet ikke bevæger sig. Nogle justeringer i visionen af ​​slutproduktet er næsten uundgåelige i design- og implementeringsfaserne; en god specifikation kan dog hjælpe med at reducere størrelsen af ​​sådanne justeringer. Hvis du springer over specifikationsfasen eller ikke dækker detaljerne tilstrækkeligt, kan det føre til den samme form for misforståelse mellem parterne, der kan opstå med en mundtlig kontrakt. Således har det først en god specifikation at fremme de efterfølgende design- og implementeringsfaser til en vellykket afslutning.

Fase 2: Design af løsningsdomænet

Når du har en skriftlig specifikation, som alle involverede er enige i, er du klar til det, jeg kalder designfase - processen med at planlægge og på en eller anden måde dokumentere arkitekturen i dit løsningsdomæne. Jeg inkluderer mange aktiviteter under navnet "design", herunder:

Definition af systemet:

  1. Opdeling af systemet i individuelle programmer (og dokumentation af det)
  2. Definition og dokumentation af grænsefladerne mellem de enkelte programmer
  3. Beslutning om og dokumentation af tredjepartsbiblioteker (Java-pakker), som dine Java-programmer bruger
  4. Når du beslutter dig for og dokumenterer nye biblioteker (Java-pakker), bygger du flere komponenter i dit system

Opbygning af prototyper til brugergrænseflade:

  1. Opbygning af prototyper til brugergrænseflader til de systemkomponenter, der har enhver brugergrænseflade

Udfører objektorienteret design:

  1. Design og dokumentation af klassehierarkier
  2. Design og dokumentation af de enkelte klasser og grænseflader

Definition af systemet

Som et første trin i designfasen skal du opdele dit system i dets komponentdele. For eksempel kan du kræve flere processer forskellige steder på et netværk. Du har muligvis nogle applets og nogle applikationer. Nogle komponenter i systemet kan være bestemt til at blive skrevet i Java, og andre ikke. Hvis du vil bruge JDBC, skal du muligvis vælge et JDBC-bibliotek fra tredjepart, der giver dig adgang til den valgte database. Alle disse beslutninger skal træffes, inden du kan begynde objektorienteret design af de enkelte programmer i systemet.

Når du definerer systemet, vil du sandsynligvis ønske at dokumentere dit arbejde i en eller flere tekniske specifikationer. Dokumentation giver dig mulighed for at kommunikere designet til andre interesserede parter i organisationen og få deres feedback. Du kan videregive specifikationen, indkalde et design review-møde og derefter præsentere systemdesignet på mødet. Gruppen kan diskutere dit design og forhåbentlig finde problemer og komme med forslag. At få feedback - og foretage justeringer af dit systemdesign som et resultat af feedbacken - er et eksempel på iteration i processen med softwareudvikling.

Opbygning af prototyper til brugergrænseflader

Opbygning af en prototype til brugergrænseflade er ofte en værdifuld aktivitet i designfasen. Når prototypen til brugergrænsefladen er afsluttet, kan de parter, der er enige om specifikationen, samles igen for at gennemgå preview-versionen. At have en prototype giver parterne endnu en chance for at visualisere og diskutere slutmålet. Ved at kræve, at alle, der accepterede specifikationen, gennemgår og logger af en prototype til brugergrænsefladen, hjælper du med at sikre, at alle parter har kompatible forventninger til slutproduktet. Med de visuelle værktøjer, der er tilgængelige i dag til udvikling af Java-baserede brugergrænseflader, kan udvikling af en brugergrænseflade-prototype være meget hurtig, og slutresultatet er en ramme af Java-kode, som du derefter kan udstyre med funktionalitet under implementeringsfasen.

Bemærk, at processen med at demonstrere en brugergrænseflade-prototype er et godt eksempel på den iterative karakter af udviklingsprocessen. Når de interesserede parter (som alle er enige om en skriftlig specifikation) faktisk ser prototyper til brugergrænsefladen, har de ofte nye ideer eller en bedre forståelse eller en mere detaljeret forståelse - med andre ord en klarere vision - om slutningen produkt. Under demonstrationen kan der foretages nogle justeringer af specifikationen. På dette tidspunkt er justeringen forhåbentlig dog mindre.

At lave et objektorienteret design

Når du designer et Java-program, skal du tænke i form af alle programmeringsteknologier, der tilbydes af Java-sproget, herunder multithreading, affaldsindsamling, struktureret fejlhåndtering og objektorientering. Men fordi det dominerende arkitektoniske træk ved Java-programmeringssprog er objektorientering, er en Java-programdesignfase grundlæggende en proces med objektorienteret design.

At lave et objektorienteret design indebærer oprettelse af arvshierarkier og design af felter og metoder for individuelle klasser og grænseflader. Tre grundlæggende kategorier af klasser, som du vil komme med i et design, er:

  1. Brugerinterfaceklasser
  2. Problem domæne klasser
  3. Datastyringsklasser

Brugergrænseflade klasser er dem, der komponerer programmets brugergrænseflade, såsom klasser, der repræsenterer windows og dialoger. Problem domæne klasser er dem, der repræsenterer objekter, som du identificerede i problemdomænet. For eksempel, hvis dit problemdomæne involverede elevatorer, har du muligvis en Elevator klasse i dit løsningsdomæne. Datastyringsklasser er dem, du opretter for at administrere objekter eller data. Hverken brugerinterfaceklasser eller datastyringsklasser har tilsvarende objekter i problemdomænet.

Fase 3: Implementering

Implementering koder. Skrivning til sløjfer, hvis udsagn, fangstklausuler, variabler og kommentarer; kompilering; enhedstest; bug fixing - det er implementering: den skarpe handling ved programmering.

Fase 4: Integration og test

Under integrations- og testfasen mødes projektteamets medlemmer, der hver har til opgave at opbygge en bestemt del af helheden, og prøver at få alle dele af softwaresystemet til at arbejde sammen. I løbet af denne fase finder teammedlemmerne ud af, hvor godt grænsefladerne mellem de enkelte systemkomponenter blev defineret og kommunikeret i systemdelingsfasen. Kodningen, der finder sted i denne fase, bør primært være bug fixing.

Dokumentation af softwaredesign

Der er mange tilgange til software design. Formelle metoder forsøger at guide dig gennem processen med at omdanne et problemdomæne til et løsningsdomæne. Ved design af Java-programmer kan du vælge at bruge en formel metode, kombinere flere formelle metoder eller at give afkald på formel metode og design ved sædet på dine bukser. Men uanset hvordan du angriber designfasen af ​​dit softwareprojekt, skal du på en eller anden måde dokumentere dit design.