Programiranje

Preveč parametrov v metodah Java, 6. del: Vrnitev metode

V trenutni seriji objav, ki jih pišem o zmanjšanju števila parametrov, potrebnih za klic Java metod in konstruktorjev, sem se doslej osredotočil na pristope, ki neposredno vplivajo na same parametre (vrste po meri, predmeti parametrov, vzorec gradnika, preobremenitev metode in poimenovanje metode). Glede na to bi se morda zdelo presenetljivo, če bi prispevek v tej seriji posvetil temu, kako metode Java zagotavljajo povratne vrednosti. Vrnjene vrednosti metod pa lahko vplivajo na parametre, ki jih metode sprejmejo, ko se razvijalci odločijo, da zagotovijo vrednosti "vrnitve", tako da nastavijo ali spremenijo predvidene parametre namesto ali poleg bolj tradicionalnih mehanizmov vračanja metod.

V podpisu metode lahko določite "tradicionalne načine", kako metoda, ki ne gradi, vrne vrednost. Najpogosteje priznan pristop za vrnitev vrednosti iz metode Java je prek deklariranega tipa vrnitve. To pogosto deluje dobro, vendar je ena izmed motenj, ki se najpogosteje zgodi, dovoljena, da vrne samo eno vrednost iz metode Java.

Mehanizem za ravnanje z izjemami Java je tudi drug pristop za ohranjanje "rezultata" metode kličočim. Zlasti preverjene izjeme se kličočemu oglašujejo prek klavzule o metu. Jim Waldo pravzaprav v svoji knjigi Java: Dobri deli navaja, da je lažje razumeti izjeme Java, če nekdo misli na izjeme Java kot na drugo vrsto vrnitve metode, ki je omejena na Throwable type.

Čeprav so vrsta vrnjene metode in vržene izjeme mišljene kot primarni pristopi k metodam za vrnitev informacij kličočim, je včasih skušnjava vrniti podatke ali stanje prek parametrov, posredovanih v metodo. Kadar mora metoda vrniti več informacij, se lahko vrnitve Java vrednosti z eno vrednostjo zdijo omejujoče. Čeprav izjeme omogočajo drug način za povratno komunikacijo s kličočim, se zdi skoraj splošno dogovorjeno, da je treba izjeme uporabljati le za poročanje o izjemnih situacijah, ne pa tudi za poročanje o "običajnih" podatkih ali za uporabo v nadzornem toku. Glede na to, da je iz metode mogoče vrniti samo en objekt ali primitiv in da izjeme omogočajo vrnitev le Mečljivo in bi ga bilo treba uporabljati le za poročanje o izjemnih situacijah, za razvijalca Java postaja vse bolj privlačno ugrabiti parametre kot nadomestno pot za vračanje podatkov klicatelju.

Tehnika, ki jo lahko razvijalec uporabi za uporabo parametrov metode kot nosilcev za povratne podatke, je sprejemanje spremenljivih parametrov in spreminjanje stanja predanih predmetov. Metoda lahko spremeni vsebino teh spremenljivih predmetov, nato pa klicatelj dostopa do predmeta, ki ga je zagotovil, da določi nove nastavitve stanja, ki jih je uporabila klicana metoda. Čeprav je to mogoče storiti s katerim koli spremenljivim objektom, se zbirke zdijo še posebej privlačne za razvijalce, ki s pomočjo parametrov poskušajo vrednosti vrniti klicatelju.

Prenos stanja nazaj v klicano prek predvidenih parametrov ima nekaj pomanjkljivosti. Ta pristop pogosto krši načelo najmanjšega začudenja, saj večina razvijalcev Jave verjetno pričakuje, da bodo parametri dohodni in ne izhodni (in Java ne nudi nobene podpore kode za določanje razlike). Bob Martin v svoji knjigi Clean Code pravi tako: "Na splošno se je treba izogibati izhodnim argumentom." Druga pomanjkljivost uporabe argumentov kot sredstva za metodo, ki kličočemu zagotovi stanje ali izhod, je, da to prispeva k neredu argumentov, posredovanih metodi. S tem v mislih se preostanek tega prispevka osredotoča na alternative vračanju več vrednosti prek posredovanih parametrov.

Čeprav metode Java lahko vrnejo samo en predmet ali primitiv, to v resnici ni velika omejitev, če pomislimo, da je objekt lahko skoraj vse, kar si želimo. Obstaja več pristopov, ki sem jih videl, vendar jih ne priporočam. Eden od teh je vrnitev matrike ali zbirke primerkov predmeta z vsakim Predmet biti ločena in ločena in pogosto nepovezana "stvar". Na primer, metoda lahko vrne tri vrednosti kot tri elemente polja ali zbirke. Različica tega pristopa je, da uporabite par tuple ali n velikosti n za vrnitev več povezanih vrednosti. Druga različica tega pristopa je vrnitev zemljevida Java, ki preslika poljubne ključe na pripadajočo vrednost. Tako kot pri drugih rešitvah tudi ta pristop odvečno bremeni stranko, da ve, kakšni so ti ključi, in dostopa do vrednosti zemljevida prek teh ključev.

Naslednji seznam kode vsebuje več teh manj privlačnih pristopov za vrnitev več vrednosti brez ugrabitve parametrov metode za vrnitev več vrednosti.

Vrnitev več vrednosti prek splošnih podatkovnih struktur

 // ================================================== =============== // OPOMBA: Ti primeri so namenjeni zgolj ponazoritvi točke // in NISO priporočljivi za proizvodno kodo. // ================================================== =============== / ** * Navedite informacije o filmu. * * @return Podatki o filmu v obliki matrike, kjer se podrobnosti preslikajo na * elemente z naslednjimi indeksi v matriki: * 0: Naslov filma * 1: Leto izdaje * 2: Režiser * 3: Ocena * / javni objekt [] getMovieInformation () {final Object [] movieDetails = {"World War Z", 2013, "Marc Forster", "PG-13"}; vrni filmPodrobnosti; } / ** * Navedite podatke o filmu. * * @return Podatki o filmu v obliki seznama s podrobnostmi * v tem vrstnem redu: naslov filma, leto izdaje, režiser, ocena. * / javni seznam getMovieDetails () {return Arrays.asList ("Enderjeva igra", 2013, "Gavin Hood", "PG-13"); } / ** * Navedite podatke o filmu. * * @return Podatki o filmu v obliki zemljevida. Značilnosti filma lahko * dobite tako, da na zemljevidu poiščete te ključne elemente: "Naslov", "Leto", * "Direktor" in "Ocena" ./ * / javni zemljevid getMovieDetailsMap () {končni zemljevid HashMap = nov HashMap (); map.put ("Naslov", "Prezren jaz 2"); map.put ("Leto", 2013); map.put ("Režiser", "Pierre Coffin in Chris Renaud"); map.put ("Ocena", "PG"); povratni zemljevid; } 

Zgoraj prikazani pristopi res izpolnjujejo namen, da podatkov prek klicanih metod ne pošljejo nazaj klicatelju prek parametrov priklicanih metod, vendar je klicatelj še vedno nepotrebno obremenjen zaradi poznavanja podrobnih podatkov o vrnjeni strukturi podatkov. Lepo je zmanjšati število parametrov na metodo in ne kršiti načela najmanjšega presenečenja, vendar ni tako lepo, če od stranke zahtevamo, da pozna zapletenost zapletene podatkovne strukture.

Predmete raje pišem za svoje vrnitve, kadar moram vrniti več kot eno vrednost. To je nekoliko več dela kot uporaba matrike, zbirke ali strukture nabora, vendar se zelo malo dodatnega dela (običajno nekaj minut s sodobnimi ID-ji Java) izplača z berljivostjo in tekočnostjo, ki pri teh bolj splošnih pristopih ni na voljo. Namesto da bi morali razlagati z Javadoc ali zahtevati od uporabnikov moje kode, da natančno preberejo mojo kodo, da bi vedeli, kateri parametri so v katerem vrstnem redu na voljo v matriki ali zbirki ali katera vrednost je kakšna v naboru, imajo lahko moji vrnjeni objekti metode, ki stranki natančno povedo, kaj zagotavljajo.

Delčki kode, ki sledijo, ponazarjajo preprosto Film razred, ki ga v veliki meri generirajo NetBeans in ga je mogoče uporabiti kot vrsto vrnitve skupaj s kodo, ki bi lahko vrnila primerek tega razreda namesto bolj splošne in manj berljive podatkovne strukture.

Movie.java

paket prah v.primeri; uvoz java.util.Objects; / ** * Preprost razred filma, da dokaže, kako enostavno je v enem samem načinu Java vrniti več vrednosti * in odjemalcu zagotoviti berljivost. * * @author Dustin * / javni razred filma {zasebni končni niz FilmTitle; zasebno končno int letoIzpuščeno; zasebni final String movieDirectorName; zasebni final String movieRating; javni film (String movieTitle, int yearReleased, String movieDirectorName, String movieRating) {this.movieTitle = movieTitle; this.yearReleased = yearReleased; this.movieDirectorName = MovieDirectorName; this.movieRating = movieRating; } javni String getMovieTitle () {vrni filmTitle; } public int getYearReleased () {vrnitev yearReleased; } javni niz getMovieDirectorName () {vrni filmDirectorName; } javni 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 (this.movieDirectorName); hash = 89 * hash + Objects.hashCode (this.movieRating); vrni hash; } @Override public boolean equals (Object obj) {if (obj == null) {return false; } if (getClass ()! = obj.getClass ()) {return false; } končni film drugo = (film) obj; if (! Objects.equals (this.movieTitle, other.movieTitle)) {return false; } if (this.yearReleased! = other.yearReleased) {return false; } if (! Objects.equals (this.movieDirectorName, other.movieDirectorName)) {return false; } if (! Objects.equals (this.movieRating, other.movieRating)) {return false; } vrni true; } @Override public String toString () {return "Movie {" + "movieTitle =" + movieTitle + ", yearReleased =" + yearReleased + ", movieDirectorName =" + movieDirectorName + ", movieRating =" + movieRating + '}'; }} 

Vrnitev več podrobnosti v enem predmetu

 / ** * Navedite podatke o filmu. * * @return Informacije o filmu. * / javni film getMovieInfo () {vrni nov film ("Oblivion", 2013, "Joseph Kosinski", "PG-13"); } 

Preprosto pisanje Film pouk mi je vzel približno 5 minut. S čarovnikom za ustvarjanje razreda NetBeans sem izbral ime in paket razreda ter nato vpisal štiri atribute razreda. Od tam sem preprosto uporabil NetBeansov mehanizem "Vstavi kodo", da sem vstavil metode "get" accessor skupaj z razveljavljenimi metodami toString (), hashCode () in equals (Object). Če ne bi mislil, da nekaj od tega potrebujem, bi lahko pouk olajšal, toda resnično ga je enostavno ustvariti takšnega, kot je. Zdaj imam veliko bolj uporabno vrsto vrnitve in to se odraža v kodi, ki uporablja razred. Za vrsto vrnitve ne potrebuje skoraj toliko Javadoc komentarjev, ker ta tip govori sam zase in oglašuje svojo vsebino s svojimi metodami "get". Menim, da se majhen dodaten napor za ustvarjanje teh preprostih razredov za vrnitev več vrednosti obrestuje z velikimi dividendami v primerjavi z alternativami, kot je vrnitev stanja prek parametrov metode ali uporaba bolj splošnih in težjih za uporabo struktur povratnih podatkov.

Ni presenetljivo, da je vrsta po meri, ki vsebuje več vrednosti, ki se vrnejo klicatelju, privlačna rešitev. Navsezadnje je to konceptualno zelo podobno konceptom, o katerih sem že pisal blog, v zvezi z uporabo predmetov po meri in parametrov za posredovanje več sorodnih parametrov, namesto da bi jih posredovali posamezno. Java je objektno usmerjen jezik, zato me preseneča, ko v kodi Java ne vidim pogosteje uporabljenih predmetov za organiziranje parametrov IN vrnitev vrednosti v lepem paketu.

Prednosti in prednosti

Prednosti uporabe predmetov parametrov po meri za predstavljanje in inkapsuliranje več povratnih vrednosti so očitne. Parametri metode lahko ostanejo "vhodni" parametri, ker so lahko vse izhodne informacije (razen informacij o napakah, sporočenih prek mehanizma izjem) v objektu po meri, ki ga metoda vrne. To je čistejši pristop kot uporaba generičnih nizov, zbirk, zemljevidov, nabora ali drugih generičnih podatkovnih struktur, ker vsi ti alternativni pristopi razvojna prizadevanja preusmerijo na vse potencialne stranke.

Stroški in slabosti

Vidim zelo malo slabosti pri pisanju vrst po meri z več vrednostmi, ki naj bi se uporabljale kot vrste vrnitve iz metod Java. Morda je najpogosteje zahtevan strošek cena pisanja in testiranja teh razredov, vendar je ta strošek precej majhen, ker so ti razredi ponavadi preprosti in ker sodobni IDE večino dela opravijo namesto nas. Ker IDE naredijo to samodejno, je koda praviloma pravilna. Razredi so tako preprosti, da jih pregledovalci kode zlahka preberejo in jih je enostavno preizkusiti.

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