Ohjelmointi

Liian monta parametria Java-menetelmissä, osa 6: Menetelmä palauttaa

Tämänhetkisessä postaussarjassa, jonka kirjoitan Java-menetelmien ja -rakentajien kutsumiseksi tarvittavien parametrien vähentämisestä, olen keskittynyt toistaiseksi lähestymistapoihin, jotka vaikuttavat suoraan parametreihin (mukautetut tyypit, parametriobjektit, rakennustyökalu, menetelmän ylikuormitus ja menetelmän nimeäminen). Tämän vuoksi saattaa tuntua yllättävältä, että omistan tämän sarjan viestin siitä, kuinka Java-menetelmät tuottavat palautusarvoja. Menetelmien palautusarvot voivat kuitenkin vaikuttaa parametreihin, jotka menetelmät hyväksyvät, kun kehittäjät päättävät antaa "paluu" -arvot asettamalla tai muuttamalla annettuja parametreja perinteisten menetelmien palautusmekanismien sijaan tai niiden lisäksi.

Molemmat "perinteiset tavat", joilla ei-konstruktorimenetelmä palauttaa arvon, voidaan määrittää menetelmän allekirjoituksessa. Yleisimmin tunnustettu tapa palauttaa arvo Java-menetelmästä tapahtuu sen ilmoitetun palautustyypin kautta. Tämä toimii usein hyvin, mutta yksi yleisimmin esiintyvistä turhautumisista sallitaan palauttaa vain yksi arvo Java-menetelmästä.

Javan poikkeusten käsittelymekanismi on myös toinen tapa säilyttää menetelmän "tulos" soittajille. Erityisesti tarkistetut poikkeukset ilmoitetaan soittajalle heittolausekkeen kautta. Itse asiassa Jim Waldo toteaa kirjassaan Java: Hyvät osat, että Java-poikkeuksia on helpompi ymmärtää, kun ajatellaan Java-poikkeuksia toisen tyyppisenä menetelmänä, joka palaa vain heitettäväksi.

Vaikka menetelmän palautustyyppi ja heitetyt poikkeukset on tarkoitettu ensisijaisiksi lähestymistavoiksi menetelmille tietojen palauttamiseksi soittajille, joskus on houkuttelevaa palauttaa tietoja tai tilaa menetelmään siirrettyjen parametrien kautta. Kun menetelmän on palautettava useampi kuin yksi tieto, Java-menetelmien yhden arvon palautus voi tuntua rajoittavalta. Vaikka poikkeukset tarjoavat toisen tavan kommunikoida takaisin soittajalle, näyttää olevan melkein yleisesti yhtä mieltä siitä, että poikkeuksia tulisi käyttää vain poikkeustilanteiden ilmoittamiseen eikä "normaalien" tietojen ilmoittamiseen tai ohjausvirtaan. Ottaen huomioon, että menetelmästä voidaan palauttaa vain yksi esine tai alkukanta ja että poikkeukset sallivat vain a: n palauttamisen Heitettävä ja sitä tulisi käyttää vain poikkeustilanteiden ilmoittamiseen, Java-kehittäjälle on entistä houkuttelevampaa kaapata parametrit vaihtoehtoisena reittinä tietojen palauttamiseksi soittajalle.

Tekniikka, jota kehittäjä voi käyttää menetelmän parametrien soveltamiseen paluudatan kantajina, on hyväksyä muutettavat parametrit ja mutatoida siirrettyjen objektien tila. Näiden muuttuvien objektien sisältöä voidaan muuttaa menetelmän avulla, ja sitten soittaja voi käyttää toimittamaansa objektia määrittääkseen uudet tila-asetukset, joita kutsutulla menetelmällä on sovellettu. Vaikka tämä voidaan tehdä minkä tahansa muutettavan objektin kanssa, kokoelmat näyttävät erityisen houkuttelevilta kehittäjälle, joka yrittää välittää arvoja soittajalle parametrien kautta.

Tilan palauttamiseen kutsutulle on annettu joitain haittoja annettujen parametrien kautta. Tämä lähestymistapa rikkoo usein vähäisimmän hämmästyksen periaatetta, koska useimmat Java-kehittäjät todennäköisesti odottavat parametrien olevan saapuvia eikä lähteviä (eikä Java tarjoa kooditukea eron määrittämiseksi). Bob Martin ilmaisee asian näin Clean Code -kirjassaan "Yleisesti tuotannon perusteluja tulisi välttää". Toinen haittapuoli argumenttien käytöstä keinona menetelmässä tilan tai ulostulon toimittamiseksi soittajalle on, että tämä lisää menetelmälle välitettyjen argumenttien sotkua. Tätä silmällä pitäen tämän viestin loppuosa keskittyy vaihtoehtoihin palauttaa useita arvoja syötettyjen parametrien kautta.

Vaikka Java-menetelmät voivat palauttaa vain yhden objektin tai primitiivisen, tämä ei todellakaan ole suuri rajoitus, kun otetaan huomioon, että esine voi olla melkein mitä tahansa haluamme sen olevan. Olen nähnyt useita lähestymistapoja, mutta en suosittele. Yksi näistä on taulukon tai objektijoukko-kokoelman palauttaminen jokaisen kanssa Esine olla erilainen ja erillinen ja usein etuyhteydettömänä "juttu". Esimerkiksi menetelmä saattaa palauttaa kolme arvoa taulukon tai kokoelman kolmeksi elementiksi. Tämän lähestymistavan muunnelma on käyttää parinparin tai n-kokoisen sekvenssin palauttamaan useita liittyviä arvoja. Yksi muunnelma tästä lähestymistavasta on palauttaa Java-kartta, joka kartoittaa mielivaltaiset avaimet niihin liittyvään arvoon. Kuten muissakin ratkaisuissa, tämä lähestymistapa asettaa asiakkaalle kohtuutonta taakkaa tietää, mitkä avaimet ovat, ja käyttää kartan arvoja näiden avainten kautta.

Seuraava koodiluettelo sisältää useita näistä vähemmän houkuttelevista lähestymistavoista useiden arvojen palauttamiseksi kaappaamatta menetelmäparametreja useiden arvojen palauttamiseksi.

Useiden arvojen palauttaminen yleisten tietorakenteiden kautta

 // ================================================== =============== // HUOMAUTUS: Nämä esimerkit on tarkoitettu vain havainnollistamaan pistettä // eikä niitä suositella tuotantokoodille. // ================================================== =============== / ** * Anna elokuvan tiedot. * * @return Elokuvatiedot taulukon muodossa, jossa yksityiskohdat on kartoitettu * elementteihin, joiden taulukossa on seuraavat indeksit: * 0: Elokuvan nimi * 1: Julkaisuvuosi * 2: Ohjaaja * 3: Luokitus * / julkinen objekti [] getMovieInformation () {final Object [] movieDetails = {"World War Z", 2013, "Marc Forster", "PG-13"}; palaa elokuvaDetails; } / ** * Anna elokuvan tiedot. * * @return Elokuvan tiedot luettelona, ​​jossa on yksityiskohtaiset tiedot * tässä järjestyksessä: elokuvan nimi, julkaisuvuosi, ohjaaja, luokitus. * / public list getMovieDetails () {return Arrays.asList ("Ender's Game", 2013, "Gavin Hood", "PG-13"); } / ** * Anna elokuvan tiedot. * * @return Elokuvan tiedot karttamuodossa. Elokuvan ominaisuudet voidaan * saada etsimällä kartalta seuraavia avaintekijöitä: "Otsikko", "Vuosi", * "Ohjaaja" ja "Luokitus" ./ * / public Map getMovieDetailsMap () {final HashMap map = new HashMap (); map.put ("Otsikko", "Halpaava Me 2"); map.put ("Vuosi", 2013); map.put ("Ohjaaja", "Pierre Coffin ja Chris Renaud"); map.put ("Rating", "PG"); paluukartta; } 

Edellä esitetyt lähestymistavat täyttävät aikomuksen olla välittämättä dataa takaisin soittajalle kutsutun menetelmän parametrien kautta, mutta soittajalle on edelleen tarpeetonta taakkaa tietää palautetun tietorakenteen läheiset yksityiskohdat. On mukavaa vähentää parametrien määrää menetelmään eikä rikkoa vähäisimmän yllätyksen periaatetta, mutta ei ole niin mukavaa vaatia asiakasta tuntemaan monimutkaisen tietorakenteen monimutkaisuudet.

Kirjoitan mieluummin mukautettuja objekteja palautuksia varten, kun minun on palautettava useampi kuin yksi arvo. Se on vähän enemmän työtä kuin matriisin, kokoelman tai dupleksirakenteen käyttö, mutta hyvin pieni määrä ylimääräistä työtä (tyypillisesti muutama minuutti nykyaikaisilla Java IDE: llä) kannattaa luettavuudella ja sujuvuudella, jota ei ole saatavana näillä yleisemmillä lähestymistavoilla. Sen sijaan, että minun tarvitsisi selittää Javadocilla tai vaatia koodini käyttäjiä lukemaan koodini huolellisesti, jotta tiedetään, mitkä parametrit järjestyksessä tai taulukossa on järjestyksessä tai mikä arvo on sarjassa, mukautetuilla palautusobjekteillani voi olla määritelty menetelmä ne, jotka kertovat asiakkaalle tarkalleen, mitä he tarjoavat.

Seuraavat koodinpätkät kuvaavat yksinkertaista Elokuva luokka, jonka suurimmaksi osaksi NetBeans on tuottanut ja jota voidaan käyttää palautustyyppinä yhdessä koodin kanssa, joka voisi palauttaa kyseisen luokan ilmentymän yleisemmän ja vähemmän luettavan tietorakenteen sijaan.

Elokuva.java

pakkaus pölyä.esimerkkejä; tuoda java.util.Kohteet; / ** * Yksinkertainen elokuvaluokka osoittaa, kuinka helppoa on antaa useita arvoja * yhdellä Java-menetelmällä ja palauttaa luettavuus asiakkaalle. * * @author Dustin * / julkisen luokan elokuva {yksityinen finaali String movieTitle; yksityinen viimeinen kansainvälinen vuosi yksityinen finaali String movieDirectorName; yksityinen lopullinen Jousisoitinelokuva julkinen elokuva (String movieTitle, int yearReleased, String movieDirectorName, String movieRating) {this.movieTitle = movieTitle; this.yRReased = vuosiReleased; this.movieDirectorName = elokuvaDirectorName; this.movieRating = movieRating; } public String getMovieTitle () {return movieTitle; } public int getYearReleased () {return yearReleased; } public String getMovieDirectorName () {return movieDirectorName; } public String getMovieRating () {return movieRating; } @Override public int hashCode () {int hash = 3; hash = 89 * hash + Objects.hashCode (this.movieTitle); hash = 89 * hash + this.yearReleased; hash = 89 * hash + Objects.hashCode (tämä.movieDirectorName); hash = 89 * hash + Objects.hashCode (this.movieRating); paluu hajautus; } @Override public boolean equals (Object obj) {if (obj == null) {return false; } if (getClass ()! = obj.getClass ()) {return väärä; } lopullinen elokuva muu = (elokuva) obj; jos (! Objects.equals (this.movieTitle, other.movieTitle)) {return false; } if (tämä.vuosiReleased! = muu.vuosiReleased) {return false; } if (! Objects.equals (this.movieDirectorName, other.movieDirectorName)) {return false; } if (! Objects.equals (this.movieRating, other.movieRating)) {return false; } return true; } @Override public string toString () {return "Movie {" + "movieTitle =" + movieTitle + ", yearReleased =" + yearReleased + ", movieDirectorName =" + movieDirectorName + ", movieRating =" + movieRating + '}'; }} 

Palautetaan useita yksityiskohtia yksittäisessä objektissa

 / ** * Anna elokuvan tiedot. * * @return Elokuvatiedot. * / public Movie getMovieInfo () {return new Movie ("Oblivion", 2013, "Joseph Kosinski", "PG-13"); } 

Yksinkertainen kirjoittaminen Elokuva luokka kesti noin 5 minuuttia. Valitsin luokan nimen ja paketin NetBeans-luontitoiminnolla ja kirjoitin sitten luokan neljä määritettä. Sieltä käytin yksinkertaisesti NetBeansin "Lisää koodi" -mekanismia "get" -käyttäjämenetelmien lisäämiseen ohitettujen toString (), hashCode () ja equals (Object) -menetelmien kanssa. Jos en usko tarvitsevani sitä, voisin pitää luokan yksinkertaisempana, mutta se on todella helppo luoda sellaisenaan. Minulla on nyt paljon käyttökelpoisempi palautustyyppi, ja tämä näkyy luokkaa käyttävässä koodissa. Se ei tarvitse melkein yhtä paljon Javadoc-kommentteja palautustyypistä, koska kyseinen tyyppi puhuu puolestaan ​​ja mainostaa sisältöään "get" -menetelmillä. Minusta tuntuu, että pieni määrä lisäponnisteluja näiden yksinkertaisten luokkien luomiseksi useiden arvojen palauttamiseksi maksaa valtavasti osinkoja verrattuna vaihtoehtoihin, kuten palautustila menetelmäparametrien kautta tai yleisempien ja vaikeampien palautusdatarakenteiden käyttäminen.

Ei ole liian yllättävää, että mukautettu tyyppi, jolla pidetään useita soittajalle palautettavia arvoja, on houkutteleva ratkaisu. Loppujen lopuksi tämä on käsitteellisesti hyvin samanlainen kuin käsitteet, joista blogin kirjoitin aiemmin ja jotka liittyivät mukautettujen tyyppien ja parametrien objektien käyttämiseen useiden toisiinsa liittyvien parametrien välittämiseen sen sijaan, että ne välittäisivät kaikki erikseen. Java on olio-kieli, joten se yllättää minut, kun en näe Java-koodissa useammin käytettyjä objekteja parametrien JA palautusarvojen järjestämiseen mukavassa paketissa.

Edut ja edut

Mukautettujen parametriobjektien edut useiden palautusarvojen esittämiseen ja kapselointiin ovat ilmeisiä. Menetelmän parametrit voivat jäädä "syöttöparametreiksi", koska kaikki lähtötiedot (paitsi poikkeusmekanismin kautta välitetyt virhetiedot) voidaan antaa menetelmän palauttamassa mukautetussa objektissa. Tämä on puhtaampi lähestymistapa kuin yleisten taulukoiden, kokoelmien, karttojen, tuplien tai muiden yleisten tietorakenteiden käyttö, koska kaikki nämä vaihtoehtoiset lähestymistavat siirtävät kehitystyön kaikille potentiaalisille asiakkaille.

Kustannukset ja haitat

Näen hyvin vähän haittapuolta kirjoittamalla mukautettuja tyyppejä, joissa on useita arvoja käytettäväksi palautustyyppeinä Java-menetelmistä. Ehkä yleisimmin ilmoitettu hinta on näiden luokkien kirjoittamisen ja testaamisen hinta, mutta kustannukset ovat melko pienet, koska nämä luokat ovat yleensä yksinkertaisia ​​ja koska modernit IDE: t tekevät suurimman osan työstä meille. Koska IDE: t tekevät sen automaattisesti, koodi on yleensä oikea. Luokat ovat niin yksinkertaisia, että koodiarvostelijat ovat helposti luettavissa ja testattavissa.

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