Programavimas

Laukų ir metodų projektavimas

Šio mėnesio dalis Dizaino technika yra antroji mini stulpelių apie objektų projektavimą serijoje. Praėjusio mėnesio skiltyje, apimančioje objektų projektavimą tinkamam inicializavimui, kalbėjau apie tai, kaip suprojektuoti konstruktorius ir iniciatorius. Šį mėnesį ir kitą mėnesį aptarsiu faktinių klasės laukų ir metodų projektavimo principus. Po to aš parašysiu apie baigiamuosius darbus ir parodysiu, kaip sukurti objektus tinkamam valymui jų gyvenimo pabaigoje.

Šio straipsnio medžiaga (vengiant specialių duomenų reikšmių, naudojant konstantas, sumažinant susiejimą) ir kitas straipsnis (maksimalus suderinamumas) gali būti žinomi daugeliui skaitytojų, nes medžiaga yra paremta bendrais dizaino principais, kurie yra visiškai nepriklausomi nuo „Java“ programavimo kalbos . Nepaisant to, kadangi per tuos metus susidūriau su tiek daug kodeksų, kurie neišnaudoja šių principų, manau, kad jie nusipelno kartkartėmis būti pakartoti. Be to, šiame straipsnyje bandau parodyti, kaip šie bendrieji principai taikomi būtent „Java“ kalbai.

Laukų projektavimas

Kuriant laukus, pagrindinė nykščio taisyklė yra vengti vieno kintamojo naudoti keliems klasės atributams vaizduoti. Galite pažeisti šią taisyklę kintamajame žymėdami specialias reikšmes, kurių kiekviena turi savo ypatingą reikšmę.

Kaip čia naudojamas, atributas yra skiriamoji daikto ar klasės savybė. Du atributai a Kavos puodelis Pavyzdžiui, objektas gali būti:

  • Kavos kiekis puodelyje
  • Nesvarbu, ar puodelis švarus, ar nešvarus

Norėdami atidžiau pažvelgti į šią taisyklę, įsivaizduokite, kad kuriate Kavos puodelis virtualios kavinės klasė, aprašyta praėjusio mėnesio Dizaino technika stulpelį. Tarkime, kad norite modeliuoti, ar kavos puodelis jūsų virtualioje kavinėje buvo nuplautas ir ar paruoštas naudoti kitam klientui. Turėdami šią informaciją, galite įsitikinti, kad nenaudosite kavos puodelio, kol jis nebus nuplautas.

Jei nuspręsite, kad jums rūpi tik tai, ar puodelis buvo nuplautas, jei jis tuščias, galite naudoti specialią puodelio vertę vidinisKava laukas, kuris paprastai naudojamas norint stebėti kavos kiekį puodelyje, kad būtų pavaizduotas neplautas puodelis. Jei 473 mililitrai (16 skysčio uncijų) yra didžiausias kavos kiekis jūsų didžiausiame puodelyje, tada didžiausia vidinisKava paprastai būtų 473. Taigi, galite naudoti vidinisKava tarkime, 500 vertė (speciali vertė), rodanti neplautą tuščią puodelį:

// Šaltinio pakete failų laukuose / ex1 / CoffeeCup.java klasė CoffeeCup {private int innerCoffee; public Boolean isReadyForNextUse () {// Jei kavos puodelis nėra nuplautas, jis // nėra paruoštas kitam naudojimui, jei (innerCoffee == 500) {return false; } return true; } public void setCustomerDone () {internalCoffee = 500; // ...} public void wash () {internalCoffee = 0; // ...} // ...} 

Šis kodas duos Kavos puodelis prieštarauja norimam elgesiui. Šio požiūrio bėda yra ta, kad specialios reikšmės nėra lengvai suprantamos ir jos apsunkina kodo keitimą. Net jei komentare aprašote specialias vertes, kitiems programuotojams gali prireikti daugiau laiko, kad suprastumėte, ką daro jūsų kodas. Be to, jie niekada negali suprasti jūsų kodo. Jie gali neteisingai naudoti jūsų klasę arba ją pakeisti taip, kad pristato klaidą.

Pavyzdžiui, jei vėliau kažkas pridės 20 uncijų puodelį prie virtualios kavinės aukų, puodelyje būtų galima laikyti iki 592 mililitrų (ml) kavos. Jei programuotojas prideda naują puodelio dydį, nesuprasdamas, kad naudojate 500 ml, kad nurodytumėte, jog puodelį reikia plauti, tikėtina, kad bus įdiegta klaida. Jei jūsų virtualioje kavinėje esantis klientas nusipirko 20 uncijų puodelį, tada paėmė didelį 92 ml gurkšnį, tada puodelyje jo liko tiksliai 500 ml. Klientas būtų šokiruotas ir nepatenkintas, kai išgėrus tik 92 ml puodelis dingo jam rankoje ir pasirodė kriauklėje, paruoštas plauti. Net jei programuotojas, atlikdamas pakeitimą, supras, kad naudojate specialią vertę, teks pasirinkti kitą specialią neplauto atributo vertę.

Geresnis požiūris į šią situaciją yra turėti atskirą lauką, skirtą modeliuoti atskirą atributą:

// Šaltinio pakete failų laukuose / ex2 / CoffeeCup.java klasė CoffeeCup {private int innerCoffee; privatūs loginiai poreikiaiSkalbimas; public Boolean isReadyForNextUse () {// Jei kavos puodelis nėra nuplautas, tada jis // nėra paruoštas kitam naudojimui return! needsWashing; } public void setCustomerDone () {needsWashing = true; // ...} public void wash () {needsWashing = false; // ...} // ...} 

Čia vidinisKava laukas naudojamas tik kavos kiekiui puodelio atribute modeliuoti. Puodelio poreikių plovimo atributas yra modeliuojamas reikiaSkalbimas srityje. Ši schema yra lengviau suprantama nei ankstesnė schema, kurioje buvo naudojama speciali vertė vidinisKava ir netrukdys kam nors išplėsti didžiausią vertę vidinisKava.

Konstantų naudojimas

Dar viena nykščio taisyklė, kurios reikia laikytis kuriant laukus, yra konstantų (statinių galutinių kintamųjų) naudojimas pastovioms reikšmėms, kurios yra perduodamos metodams, grąžinamos iš jų arba naudojamos taikant metodus. Jei metodas tikisi vieno iš baigtinių pastovių verčių rinkinio viename iš jo parametrų, apibrėžiant konstantas, kliento programuotojams tampa aiškiau, ką reikia perduoti tame parametre. Panašiai, jei metodas pateikia vieną iš baigtinių reikšmių rinkinio, deklaravus konstantas, kliento programuotojams tampa aiškiau, ko tikėtis kaip išvesties. Pavyzdžiui, tai lengviau suprasti:

if (puodelis.getSize () == Kavos puodelis.TALL) {} 

nei tai suprasti:

jei (taurė.getSize () == 1) {} 

Taip pat turėtumėte apibrėžti konstantas vidiniam naudojimui klasės metodais - net jei šios konstantos nenaudojamos už klasės ribų, todėl jas lengviau suprasti ir pakeisti. Naudojant konstantas kodas tampa lankstesnis. Jei suprantate, kad neteisingai apskaičiavote vertę ir nenaudojote konstantos, turėsite pereiti savo kodą ir pakeisti kiekvieną sunkiai užkoduotą vertę. Tačiau jei jūs naudojote konstantą, turėsite ją pakeisti tik ten, kur ji apibrėžta kaip konstanta.

„Constants“ ir „Java“ kompiliatorius

Naudingas dalykas, kurį reikia žinoti apie „Java“ kompiliatorių, yra tai, kad jis su statiniais galutiniais laukais (konstantomis) elgiasi kitaip nei su kitų tipų laukais. Nuorodos į statinius galutinius kintamuosius, inicializuotus į kompiliavimo laiko konstantą, kompiliavimo metu išsprendžiamos į konstantos vertės vietinę kopiją. Tai galioja visų primityvių tipų ir tipų konstantoms java.lang.Stringas.

Paprastai, kai jūsų klasė nurodo kitą klasę - tarkim, klasę java.lang.Math - „Java“ kompiliatorius pateikia simbolines nuorodas į klasę Matematika į savo klasės failą. Pavyzdžiui, jei naudojamas jūsų klasės metodas Math.sin (), jūsų klasės faile bus dvi simbolinės nuorodos į Matematika:

  • Viena simbolinė nuoroda į klasę Matematika
  • Viena simbolinė nuoroda į Matematika's nuodėmė () metodas

Norėdami įvykdyti jūsų klasėje esantį kodą, į kurį nurodoma Math.sin (), JVM reikėtų pakrauti klasę Matematika išspręsti simbolines nuorodas.

Kita vertus, jei jūsų kodas nurodė tik statinį galutinės klasės kintamąjį PI deklaruota klasėje Matematika, „Java“ kompiliatorius nepateiks jokių simbolinių nuorodų į Matematika savo klasės faile. Vietoj to jis tiesiog įdėtų pažodinės vertės kopiją Math.PI į savo klasės failą. Norėdami vykdyti kodą, esantį jūsų klasėje, kurioje naudojamas Math.PI pastovus, JVM nereikės pakrauti klasės Matematika.

Šios „Java“ kompiliatoriaus funkcijos rezultatas yra tas, kad JVM nereikia daugiau dirbti, norint naudoti konstantas, nei naudojant pažodžius. Pirmenybė konstantoms, o ne literalams yra viena iš nedaugelio dizaino gairių, kuri padidina programos lankstumą nerizikuodama pabloginti programos našumą.

Trijų rūšių metodai

Likusioje šio straipsnio dalyje bus aptariami metodo projektavimo metodai, susiję su metodo naudojamais ar modifikuojamais duomenimis. Šiame kontekste norėčiau nustatyti ir įvardyti tris pagrindinius „Java“ programų metodus: naudingumo metodas būsenos požiūrio metodas, ir būsenos keitimo metodas.

Naudingumo metodas

Naudingumo metodas yra klasės metodas, kuris nenaudoja ir nekeičia savo klasės būsenos (klasės kintamųjų). Šis metodas tiesiog teikia naudingą paslaugą, susijusią su jo objekto klase.

Keli „Java“ API naudingumo metodų pavyzdžiai:

  • (Klasėje Sveikasis skaičius) public static int toString (int i) - grąžina naują Stygos objektas, nurodantis nurodytą skaičių 10 radix
  • (Klasėje Matematika) viešasis statinis gimtoji dviguba cos (dviguba a) - grąžina trigonometrinį kampo kosinusą

Būsenos požiūrio metodas

„State-view“ metodas yra klasės arba egzemplioriaus metodas, kuris pateikia tam tikrą klasės ar objekto vidinės būsenos vaizdą, nekeisdamas tos būsenos. (Šis metodas įžūliai nepaiso Heisenbergo neapibrėžtumo principo - žr. „Ištekliai“, jei jums reikia atnaujinti šį principą.) „State-view“ metodas gali tiesiog grąžinti klasės ar egzemplioriaus kintamojo vertę arba grąžinti vertę, apskaičiuotą iš keli klasės ar egzemplioriaus kintamieji.

Keletas „Java“ API būsenos rodymo metodų yra šie:

  • (Klasėje Objektas) viešoji styginių eilutė () - grąžina objekto eilutę
  • (Klasėje Sveikasis skaičius) viešojo baito baito vertė () - grąžina Sveikasis skaičius objektas kaip baitas
  • (Klasėje Stygos) public int indexOf (int ch) - grąžina indeksą pirmojo nurodyto simbolio atsiradimo eilutėje

Būsenos keitimo metodas

Būsenos keitimo metodas yra metodas, galintis transformuoti būsenos klasę, kurioje deklaruojamas metodas, arba, jei egzemplioriaus metodą, objektą, į kurį jis yra įtrauktas. Kai naudojamas būsenos keitimo metodas, tai reiškia „įvykį“ klasei ar objektui. Metodo kodas „tvarko“ įvykį, galbūt pakeisdamas klasės ar objekto būseną.

Keletas „Java“ API būsenos keitimo metodų yra šie:

  • (Klasėje „StringBuffer“) viešasis „StringBuffer“ priedas (int i) - pridedamas eilutės atvaizdas tarpt argumentas „StringBuffer“
  • (Klasėje „Hashtable“) viešas sinchronizuotas negaliojantis išvalyti () - išvalo „Hashtable“ kad joje nebūtų raktų
  • (Klasėje Vektorius) viešas galutinis sinchronizuotas negaliojantis addElement (objekto objektas) - prideda nurodytą komponentą prie Vektorius, padidindamas jo dydį vienu

Metodo susiejimo sumažinimas

Ginkluotas šiais naudingumo, būsenos rodymo ir būsenos keitimo metodų apibrėžimais, esate pasirengęs aptarti metodų susiejimą.

Kuriant metodus, vienas iš jūsų tikslų turėtų būti sumažinti sukabinimas - metodo ir jo aplinkos (kitų metodų, objektų ir klasių) tarpusavio priklausomybės laipsnis. Kuo mažiau susiejamas metodas ir jo aplinka, tuo šis metodas yra savarankiškesnis ir dizainas yra lankstesnis.

Metodai kaip duomenų transformatoriai

Suprasti susiejimą padeda galvoti apie metodus vien kaip apie duomenų transformatorius. Metodai priima duomenis kaip įvestį, atlieka tų duomenų operacijas ir generuoja duomenis kaip išvestį. Metodo susiejimo laipsnis visų pirma nustatomas pagal tai, kur jis gauna įvesties duomenis ir kur pateikia išvesties duomenis.

1 paveiksle parodytas grafinis metodo, kaip duomenų transformatoriaus, atvaizdavimas: Duomenų srauto schema pagal struktūrinį (ne objektinį) dizainą.

Įvestis ir išvestis

„Java“ metodas gali gauti įvesties duomenis iš daugelio šaltinių:

  • Tai gali reikalauti, kad skambinantysis nurodytų įvesties duomenis kaip parametrus, kai jie bus iškviečiami
  • Jis gali paimti duomenis iš visų pasiekiamų klasės kintamųjų, pvz., Pačios klasės kintamųjų ar bet kurių kitų klasės prieinamų kintamųjų
  • Jei tai yra egzemplioriaus metodas, jis gali paimti egzempliorių kintamuosius iš objekto, ant kurio jis buvo iškviestas

Panašiai metodas gali išreikšti savo rezultatą daugelyje vietų:

  • Tai gali grąžinti vertę - primityvų tipą arba objekto nuorodą
  • Tai gali pakeisti objektus, nurodytus nuorodomis, perduotomis kaip parametrai
  • Tai gali pakeisti bet kokius savo klasės klasės kintamuosius arba bet kokius prieinamus kitos klasės klasės kintamuosius
  • Jei tai yra egzemplioriaus metodas, jis gali pakeisti bet kokius objekto, į kurį jis buvo nukreiptas, egzempliorių kintamuosius
  • Tai gali sukelti išimtį

Atkreipkite dėmesį, kad parametrai, grąžinimo vertės ir išimtys nėra vieninteliai metodo įvesties ir išvesties tipai, paminėti aukščiau pateiktuose sąrašuose. Egzempliorių ir klasių kintamieji taip pat traktuojami kaip įvestis ir išvestis. Žiūrint į objektą, tai gali atrodyti ne intuityviai, nes prieiga prie „Java“ egzempliorių ir klasių kintamųjų yra „automatinė“ (jums nereikia nieko aiškiai perduoti metodui). Tačiau bandydami įvertinti metodo susiejimą, turite atsižvelgti į naudojamų ir modifikuotų duomenų rūšį ir kiekį, neatsižvelgiant į tai, ar kodo prieiga prie tų duomenų buvo „automatinė“, ar ne.

Minimaliai susieti naudingumo metodai

Mažiausias „Java“ susietas metodas yra naudingasis metodas, kuris:

  1. Priima duomenis tik iš jo parametrų
  2. Išreiškia savo išvestį tik per parametrus arba grąžinimo vertę (arba išmetant išimtį)
  3. Priima tik įvesties duomenis, kurie iš tikrųjų reikalingi metodui
  4. Grąžina tik išvesties duomenis, kurie iš tikrųjų yra gauti pagal metodą

Geras naudingumo metodas

Pavyzdžiui, metodas convertOzToMl () parodyta žemiau, priima tarpt kaip vienintelį įvestį ir grąžina tarpt kaip vienintelis jo rezultatas:

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