Programiranje

Oblikovanje polj in metod

Ta mesec obrok za Tehnike oblikovanja je drugi v mini seriji stolpcev o oblikovanju predmetov. V stolpcu prejšnjega meseca, ki je zajemal oblikovanje objektov za pravilno inicializacijo, sem govoril o tem, kako oblikovati konstruktorje in inicializatorje. Ta mesec in naslednji mesec bom razpravljal o načelih oblikovanja dejanskih področij in metod predavanja. Po tem bom pisal o zaključnikih in pokazal, kako oblikovati predmete za pravilno čiščenje na koncu njihovega življenja.

Gradivo za ta članek (izogibanje posebnim vrednostim podatkov, uporaba konstant, zmanjšanje povezovanja) in naslednji članek (maksimiranje kohezije) je morda znano številnim bralcem, saj gradivo temelji na splošnih načelih oblikovanja, ki so precej neodvisna od programskega jezika Java . Ker pa sem se v preteklih letih srečal s toliko kode, ki teh načel ne izkorišča, mislim, da si zaslužijo občasno ponovitev. Poleg tega v tem članku poskušam pokazati, kako ta splošna načela veljajo zlasti za jezik Java.

Oblikovanje polj

Pri načrtovanju polj je glavno pravilo izogibanje uporabi ene spremenljivke za predstavitev več atributov razreda. To pravilo lahko kršite tako, da v spremenljivki označite posebne vrednosti, od katerih ima vsaka svoj poseben pomen.

Kot se uporablja tukaj, atribut je značilnost predmeta ali razreda. Dva atributa a Kavna skodelica predmet, na primer, je lahko:

  • Količina kave, ki jo vsebuje skodelica
  • Ali je skodelica čista ali umazana

Če si želite natančneje ogledati to pravilo, si predstavljajte, da načrtujete a Kavna skodelica razred za virtualno kavarno, opisano v prejšnjem mesecu Tehnike oblikovanja stolpec. Predpostavimo, da želite modelirati, ali je bila skodelica za kavo v vaši virtualni kavarni oprana in je pripravljena za uporabo s strani naslednje stranke. S temi informacijami lahko zagotovite, da kavne skodelice ne boste več uporabili, preden jo operete.

Če se odločite, da vas zanima samo, ali je bila skodelica oprana, če je prazna, lahko uporabite posebno vrednost innerCoffee polje, ki se običajno uporablja za beleženje količine kave v skodelici, ki predstavlja neoprano skodelico. Če je največja količina kave v vaši največji skodelici 473 mililitrov (16 unč tekočine), potem je največja innerCoffee običajno bi bilo 473. Tako lahko uporabite innerCoffee vrednost, recimo 500 (posebna vrednost), ki označuje prazno skodelico, ki je neoprana:

// V izvornem paketu v datotečnih poljih / ex1 / CoffeeCup.java razred CoffeeCup {private int innerCoffee; public boolean isReadyForNextUse () {// Če skodelica za kavo ni oprana, potem // ni pripravljena za naslednjo uporabo if (innerCoffee == 500) {return false; } vrni true; } javna void setCustomerDone () {innerCoffee = 500; // ...} javno prazno prazno () {innerCoffee = 0; // ...} // ...} 

Ta koda bo dala Kavna skodelica ugovarja želenemu vedenju. Težava tega pristopa je, da posebne vrednosti niso zlahka razumljive in otežujejo spreminjanje kode. Tudi če v komentarju opišete posebne vrednosti, bo morda drugim programerjem treba več časa, da bodo razumeli, kaj počne vaša koda. Poleg tega morda nikoli ne bodo razumeli vaše kode. Lahko nepravilno uporabljajo vaš razred ali ga spremenijo tako, da uvedejo napako.

Če na primer kasneje nekdo ponudbi virtualne kavarne doda skodelico 20 unč, bi bilo v skodelico mogoče shraniti do 592 mililitrov (ml) kave. Če programer doda novo velikost skodelice, ne da bi se zavedal, da s 500 ml označujete, da je treba skodelico oprati, bo verjetno prišlo do napake. Če bi stranka v vaši virtualni kavarni kupila skodelico 20 unč in nato zaužila velik 92-mililitrski koktajl, bi ji v skodelici ostalo natanko 500 ml. Kupec bi bil šokiran in nezadovoljen, ko bi mu po zaužitju le 92 ml skodelica izginila iz roke in se pojavila v umivalniku, pripravljena za pranje. Tudi, če bi programer, ki je izvedel spremembo, ugotovil, da uporabljate posebno vrednost, bi bilo treba izbrati drugo posebno vrednost za neoprani atribut.

Boljši pristop k tej situaciji je ločeno polje za modeliranje ločenega atributa:

// V izvornem paketu v datotečnih poljih / ex2 / CoffeeCup.java razred CoffeeCup {private int innerCoffee; zasebno logično potrebe za pranje; public boolean isReadyForNextUse () {// Če skodelica za kavo ni oprana, potem // ni pripravljena za naslednjo uporabo return! needsWashing; } javna void setCustomerDone () {needsWashing = true; // ...} javno prazno pranje () {needsWashing = false; // ...} // ...} 

Tukaj innerCoffee polje se uporablja samo za modeliranje količine kave v atributu skodelice. Atribut pomivanja skodelice je modeliran z potrebe pranja polje. Ta shema je lažje razumljiva kot prejšnja shema, ki je uporabljala posebno vrednost innerCoffee in ne bi preprečil, da bi nekdo razširil največjo vrednost za innerCoffee.

Uporaba konstant

Drugo pravilo, ki ga je treba upoštevati pri ustvarjanju polj, je uporaba konstant (statičnih končnih spremenljivk) za konstantne vrednosti, ki se posredujejo, vrnejo ali uporabijo znotraj metod. Če metoda v enem od svojih parametrov pričakuje eno od končnih množic konstantnih vrednosti, definiranje konstant pripomore k temu, da je odjemalskim programerjem bolj jasno, kaj je treba posredovati v tem parametru. Če metoda vrne eno od končnih množic vrednosti, razglasitev konstant odjemalskim programerjem postane bolj očitno, kaj lahko pričakujejo kot rezultat. To je na primer lažje razumeti:

če (cup.getSize () == CoffeeCup.TALL) {} 

kot je to razumeti:

če (cup.getSize () == 1) {} 

Prav tako bi morali določiti konstante za interno uporabo z metodami razreda - tudi če se te konstante ne uporabljajo zunaj razreda - zato jih je lažje razumeti in spremeniti. Uporaba konstant naredi kodo bolj prilagodljivo. Če se zavedate, da ste napačno izračunali vrednost in niste uporabili konstante, boste morali pregledati kodo in spremeniti vsak pojav trdo kodirane vrednosti. Če pa ste uporabili konstanto, jo boste morali spremeniti le tam, kjer je definirana kot konstanta.

Konstante in prevajalnik Java

Koristno je vedeti o prevajalniku Java, da statična končna polja (konstante) obravnava drugače kot druge vrste polj. Sklici na statične končne spremenljivke, inicializirane v konstanto časa prevajanja, se v času prevajanja razrešijo na lokalno kopijo vrednosti konstante. To velja za konstante vseh primitivnih tipov in vrst java.lang.String.

Običajno se vaš razred nanaša na drug razred - recimo na razred java.lang.Math - prevajalnik Java postavi simbolična sklicevanja na razred Matematika v datoteko predavanja za vaš razred. Na primer, če se prikliče metoda vašega razreda Math.sin (), bo datoteka predavanja vsebovala dve simbolni sklici na Matematika:

  • Simbolično sklicevanje na razred Matematika
  • Simbolično sklicevanje na Matematikaje greh () metoda

Za izvedbo kode v vašem razredu, ki se nanaša na Math.sin (), bi moral JVM naložiti razred Matematika za razrešitev simboličnih sklicev.

Če se je po drugi strani vaša koda nanašala samo na statično spremenljivko končnega razreda PI razglašen v razredu Matematika, prevajalnik Java ne bi dal nobene simbolične reference na Matematika v datoteki predavanja za vaš razred. Namesto tega bi preprosto postavil kopijo dobesedne vrednosti Math.PI v datoteko razreda vašega predavanja. Za izvedbo kode v razredu, ki uporablja Math.PI konstantno, JVM ne bi bilo treba naložiti razreda Matematika.

Rezultat te funkcije prevajalnika Java je, da JVM ni treba bolj trdo delati, da bi uporabljal konstante kot da uporablja literale. Prednost konstantam pred dobesednimi je ena redkih smernic za načrtovanje, ki povečuje prožnost programa, ne da bi pri tem tvegala poslabšanje zmogljivosti programa.

Tri vrste metod

Preostanek tega članka bo obravnaval tehnike načrtovanja metode, ki se nanašajo na podatke, ki jih metoda uporablja ali spreminja. V tem kontekstu bi rad opredelil in poimenoval tri osnovne vrste metod v programih Java: uporabna metoda metoda stanja stanja, in metoda spremembe stanja.

Uporabna metoda

Uporabna metoda je metoda razreda, ki ne uporablja ali spreminja stanja (spremenljivke razreda) svojega razreda. Ta vrsta metode preprosto nudi koristno storitev, povezano s svojim razredom predmeta.

Nekaj ​​primerov uporabnih metod iz Java API je:

  • (V razredu Celo število) javni statični int toString (int i) - vrne novo Vrvica objekt, ki predstavlja določeno celo število v radiksu 10
  • (V razredu Matematika) javni statični nativni dvojni cos (dvojni a) - vrne trigonometrični kosinus kota

Metoda stanja stanja

Metoda pogleda stanja je metoda razreda ali primerka, ki vrne nekaj pogleda na notranje stanje razreda ali predmeta, ne da bi to stanje spremenila. (Ta vrsta metode drzno ne upošteva Heisenbergovega načela negotovosti - glejte Vire, če potrebujete osvežitev po tem principu.) Metoda pogleda stanja lahko preprosto vrne vrednost spremenljivke razreda ali primerka ali pa vrne vrednost, izračunano iz več spremenljivk razreda ali primerka.

Nekaj ​​primerov metod pogleda stanja iz API-ja Java je:

  • (V razredu Predmet) javni String toString () - vrne nizovno predstavitev predmeta
  • (V razredu Celo število) javni bajt byteValue () - vrne vrednost Celo število objekt kot bajt
  • (V razredu Vrvica) javni int indeksOf (int ch) - vrne indeks v nizu prvega pojavljanja določenega znaka

Metoda spremembe stanja

Metoda spremembe stanja je metoda, ki lahko preoblikuje stanje razreda, v katerem je metoda deklarirana, ali, če je metoda primerka, objekt, na katerega se prikliče. Ko se prikliče metoda spremembe stanja, predstavlja "dogodek" za razred ali predmet. Koda metode "obdeluje" dogodek, kar lahko spremeni stanje razreda ali predmeta.

Nekaj ​​primerov metod spreminjanja stanja iz Java API je:

  • (V razredu StringBuffer) javni dodatek StringBuffer (int i) - doda nizno predstavitev int argument za StringBuffer
  • (V razredu Hashtable) javna sinhronizirana void clear () - počisti Hashtable tako da ne vsebuje ključev
  • (V razredu Vektor) javni končni sinhronizirani void addElement (objekt obj) - doda določeno komponento na konec Vektor, povečala svojo velikost za eno

Zmanjšanje povezovanja metode

Oboroženi s temi opredelitvami metod uporabnosti, stanja in sprememb stanja ste pripravljeni na razpravo o spenjanju metod.

Med načrtovanjem metod bi moral biti eden od vaših ciljev minimalizirati sklopka - stopnja medsebojne odvisnosti metode in njenega okolja (druge metode, predmeti in razredi). Manj je povezav med metodo in okoljem, bolj neodvisna je ta metoda in bolj prilagodljiva je zasnova.

Metode kot podatkovni transformatorji

Da bi razumeli spenjanje, pomaga razmišljati o metodah zgolj kot o pretvornikih podatkov. Metode sprejemajo podatke kot vhodne podatke, izvajajo operacije nad njimi in generirajo podatke kot izhodne podatke. Stopnja povezanosti metode je odvisna predvsem od tega, kje dobi vhodne podatke in kam postavi izhodne podatke.

Slika 1 prikazuje grafični prikaz metode kot podatkovnega transformatorja: Diagram toka podatkov iz strukturirane (ne objektno usmerjene) zasnove.

Vhod in izhod

Metoda v Javi lahko dobi vhodne podatke iz številnih virov:

  • Od klicatelja lahko zahteva, da ob vpoklicu navede svoje vhodne podatke kot parametre
  • Zajema lahko podatke iz vseh dostopnih spremenljivk razreda, kot so lastne spremenljivke razreda ali katere koli dostopne spremenljivke razreda drugega razreda
  • Če gre za metodo primerka, lahko zagrabi spremenljivke primerka iz predmeta, na katerem je bil poklican

Metoda lahko izrazi svoje rezultate na mnogih mestih:

  • Vrne lahko vrednost, bodisi primitivni tip bodisi sklic na objekt
  • Lahko spremeni predmete, na katere se sklicujejo reference, posredovane kot parametri
  • Spremeni lahko katero koli spremenljivko razreda svojega razreda ali katero koli dostopno spremenljivko razreda drugega razreda
  • Če gre za metodo primerka, lahko spremeni vse spremenljivke primerka predmeta, na katerem je bil poklican
  • Lahko vrže izjemo

Upoštevajte, da parametri, vrnjene vrednosti in vržene izjeme niso edine vrste vhodov in izhodov metode, omenjene na zgornjih seznamih. Spremenljivke primerka in razreda se prav tako obravnavajo kot vhod in izhod. Z objektno usmerjenega vidika se to morda zdi neintuitivno, ker je dostop do spremenljivk primerka in razreda v Javi "samodejen" (metodi ni treba izrecno ničesar posredovati). Pri poskusu merjenja povezave metode pa morate pogledati vrsto in količino podatkov, ki jih koda uporablja in spreminja, ne glede na to, ali je bil dostop kode do teh podatkov "samodejen".

Minimalno povezane uporabne metode

Najmanj povezana metoda, ki je možna v Javi, je uporabna metoda, ki:

  1. Vnese samo iz svojih parametrov
  2. Izrazi svoje rezultate samo s svojimi parametri ali vrnjeno vrednostjo (ali z vrnitvijo izjeme)
  3. Kot vhod sprejema samo podatke, ki jih metoda dejansko potrebuje
  4. Vrne kot izhod samo podatke, ki jih metoda dejansko ustvari

Dobra uporabna metoda

Na primer metoda convertOzToMl () prikazano spodaj sprejema int kot edini vhod in vrne int kot edini rezultat:

$config[zx-auto] not found$config[zx-overlay] not found