Programavimas

Per daug parametrų „Java“ metoduose, 6 dalis: metodas grąžina

Dabartinėje pranešimų serijoje, kurią rašau apie „Java“ metodams ir konstruktoriams iškviesti reikalingų parametrų skaičiaus mažinimą, iki šiol sutelkiau dėmesį į metodus, kurie tiesiogiai veikia pačius parametrus (pasirinktinius tipus, parametrų objektus, kūrėjo modelį, metodo perkrovą ir metodo pavadinimas). Atsižvelgiant į tai, man gali pasirodyti nuostabu skirti šios serijos įrašą apie tai, kaip „Java“ metodai teikia grąžinimo vertes. Tačiau metodų grąžinimo vertės gali turėti įtakos parametrams, kuriuos metodai priima, kai kūrėjai nusprendžia pateikti „grąžinimo“ reikšmes nustatydami arba keisdami pateiktus parametrus, o ne tradicinius metodų grąžinimo mechanizmus ar juos papildydami.

„Tradicinius būdus“, kai nekonstruktoriaus metodas grąžina vertę, abu galima nurodyti metodo paraše. Dažniausiai pripažįstamas vertės grąžinimo iš „Java“ metodo metodas yra deklaruojamas grąžinimo tipas. Tai dažnai veikia gerai, tačiau vienam iš dažniausiai pasitaikančių nusivylimų leidžiama grąžinti tik vieną reikšmę iš „Java“ metodo.

„Java“ išimčių tvarkymo mechanizmas taip pat yra kitas būdas išsaugoti metodo „rezultatą“ skambinantiesiems. Pažymėtos išimtys, visų pirma, reklamuojamos skambinančiajam per metimo sąlygą. Tiesą sakant, Jimas Waldo knygoje „Java: gerosios dalys“ teigia, kad lengviau suprasti „Java“ išimtis, kai pagalvojama apie „Java“ išimtis, nes kito tipo metodas grįžta tik į „Throwable“ tipą.

Nors metodo grąžinimo tipas ir išmetamos išimtys yra numatyti kaip pagrindiniai metodai, kaip grąžinti informaciją skambinantiesiems, kartais kyla pagunda grąžinti duomenis ar būseną per metodui perduotus parametrus. Kai metodas turi pateikti daugiau nei vieną informaciją, „Java“ metodų vienos vertės grąžos gali atrodyti ribojančios. Nors išimtys yra kitas būdas susisiekti su skambinančiuoju, atrodo, kad beveik visuotinai sutariama, jog išimtys turėtų būti naudojamos tik pranešant apie išskirtines situacijas, o ne pranešant apie „įprastus“ duomenis arba naudojamos valdymo sraute. Atsižvelgiant į tai, kad iš metodo gali būti grąžintas tik vienas objektas arba primityvas ir kad išimtys leidžia grąžinti tik a Metamas ir turėtų būti naudojamas tik pranešant apie išskirtines situacijas, „Java“ kūrėjui tampa vis patraukliau užgrobti parametrus kaip alternatyvų būdą, kaip grąžinti duomenis skambinančiajam.

Metodas, kurį kūrėjas gali naudoti metodo parametrams kaip duomenų grąžinimo laikmenoms, yra priimtini kintantys parametrai ir perduotų objektų būsenos mutacija. Šių kintamų objektų turinys gali būti pakeistas taikant metodą, o paskui skambintojas gali pasiekti pateiktą objektą, kad nustatytų naujus būsenos nustatymus, kurie buvo taikomi iškviečiamu metodu. Nors tai galima padaryti su bet kuriuo kintamu objektu, kolekcijos atrodo ypač patrauklios kūrėjui, bandančiam perduoti reikšmes skambinančiajam per parametrus.

Yra keli trūkumai, kai būsena perduodama iškviečiamam per pateiktus parametrus. Šis požiūris dažnai pažeidžia mažiausio nuostabos principą, nes dauguma „Java“ kūrėjų tikriausiai tikisi, kad parametrai bus „INcoming“, o ne „OUTgoing“ (o „Java“ neteikia jokio kodo palaikymo, kad būtų nurodytas skirtumas). Bobas Martinas savo knygoje „Švarus kodas“ tai įvardija taip: „Apskritai reikėtų vengti išvesties argumentų“. Kitas argumentų, kaip metodo priemonės, suteikiantis būseną ar išvestį skambinančiajam, trūkumas yra tas, kad tai padidina metodo argumentų netvarką. Atsižvelgiant į tai, likusioje šio įrašo dalyje daugiausiai dėmesio skiriama kelių verčių grąžinimo per perduotus parametrus alternatyvoms.

Nors „Java“ metodai gali grąžinti tik vieną objektą ar primityvų dalyką, tačiau tai tikrai nėra didelis apribojimas, kai manoma, kad objektas gali būti beveik viskas, ko mes norime. Yra keletas požiūrių, kuriuos mačiau, bet nerekomenduoju. Vienas iš jų yra objektų egzempliorių masyvo ar rinkinio grąžinimas su kiekvienu Objektas būdamas skirtingas ir aiškus bei dažnai nesusijęs „dalykas“. Pavyzdžiui, metodas gali pateikti tris reikšmes kaip tris masyvo ar kolekcijos elementus. Šio metodo variantas yra naudoti poros porą arba n dydžio porą, kad būtų grąžintos kelios susietos vertės. Dar vienas šio požiūrio variantas yra grąžinti „Java“ žemėlapį, kuriame susieti savavališki raktai su jų susieta verte. Kaip ir taikant kitus sprendimus, šis metodas klientui užkrauna nepagrįstą naštą žinoti, kas yra tie raktai, ir per tuos raktus pasiekti žemėlapio vertes.

Kitame kodų sąraše yra keli iš šių mažiau patrauklių būdų grąžinti kelias reikšmes, neužgrobiant metodo parametrų, kad būtų grąžintos kelios vertės.

Kelių verčių grąžinimas naudojant bendrąsias duomenų struktūras

 // ================================================== =============== // PASTABA: Šie pavyzdžiai skirti tik tam, kad paaiškintų tašką // ir NĖRA rekomenduojami gamybos kodui. // ================================================== =============== / ** * Pateikite informaciją apie filmą. * * @return Filmo informacija masyvo forma, kurioje išsami informacija susiejama su * elementais su šiais masyvo rodyklėmis: * 0: filmo pavadinimas * 1: išleidimo metai * 2: režisierius * 3: įvertinimas * / viešasis objektas [] getMovieInformation () {final Object [] movieDetails = {"Pasaulinis karas Z", 2013 m., "Marcas Forsteris", "PG-13"}; grąžinti filmąIšsami informacija; } / ** * Pateikite informaciją apie filmą. * * @return Filmo informacija sąrašo forma, kurioje pateikiama išsami informacija * tokia tvarka: filmo pavadinimas, išleidimo metai, režisierius, įvertinimas. * / public list getMovieDetails () {return Arrays.asList („Enderio žaidimas“, 2013 m., „Gavinas Hudas“, „PG-13“); } / ** * Pateikite informaciją apie filmą. * * @return Filmo informacija žemėlapio forma. Filmo charakteristikas * galite sužinoti žemėlapyje, ieškodami šių pagrindinių elementų: „Pavadinimas“, „Metai“, * „Režisierius“ ir „Reitingas“ ./ * / public Map getMovieDetailsMap () {final HashMap map = new HashMap (); map.put („Pavadinimas“, „Niekingas aš 2“); map.put („Metai“, 2013); map.put („Režisierius“, „Pierre'as Coffinas ir Chrisas Renaudas“); map.put („Įvertinimas“, „PG“); grįžimo žemėlapis; } 

Aukščiau parodyti metodai atitinka ketinimą neperduoti duomenų skambinančiajam pagal iškviestų metodų parametrus, tačiau skambintojui vis tiek tenka nereikalinga našta žinoti intymią informaciją apie grąžintą duomenų struktūrą. Malonu sumažinti metodo parametrų skaičių ir nepažeisti mažiausios nuostabos principo, tačiau nėra taip malonu reikalauti, kad klientas žinotų sudėtingos duomenų struktūros subtilybes.

Aš norėčiau parašyti pasirinktinius objektus savo grąžinimams, kai man reikia grąžinti daugiau nei vieną reikšmę. Tai šiek tiek daugiau darbo nei naudojant masyvą, kolekciją ar dvigubą struktūrą, tačiau labai nedidelis papildomas darbas (paprastai kelios minutės naudojant šiuolaikinius „Java IDE“) atsiperka skaitomumu ir sklandumu, kurio nėra naudojant šiuos bendresnius metodus. Užuot turėjęs aiškintis „Javadoc“ ar reikalauti, kad mano kodo vartotojai atidžiai perskaitytų mano kodą, žinotų, kokie parametrai pateikiami pagal masyvo ar kolekcijos eilės tvarką arba kuri reikšmė yra pakete, mano pasirinktiniuose grąžinimo objektuose gali būti apibrėžti metodai juos, kurie klientui tiksliai nurodo, ką jie teikia.

Toliau pateikti kodo fragmentai iliustruoja paprastą Filmas klasę, kurią daugiausia sugeneravo „NetBeans“ ir kuri gali būti naudojama kaip grąžinimo tipas kartu su kodu, kuris galėtų grąžinti tos klasės egzempliorių, o ne bendresnę ir mažiau skaitomą duomenų struktūrą.

Filmas.java

pakuotė dustin.pavyzdžiai; importuoti java.util.Object; / ** * Paprasta filmų klasė, padedanti parodyti, kaip lengva pateikti kelias reikšmes * vienu „Java“ metodu ir grąžinti klientui. * * @author Dustin * / viešosios klasės filmas {privatus finalinis styginių filmasTitle; privatus paskutinis tarpt. išleistas; privatus finalinis styginių filmasDirectorName; privatus finalinis styginių filmas Įvertinimas; public Movie (String movieTitle, int yearReleased, String movieDirectorName, String movieRating) {this.movieTitle = movieTitle; this.yearReleased = metaiReleased; this.movieDirectorName = movieDirectorName; this.movieRating = movieRating; } viešoji eilutė getMovieTitle () {return movieTitle; } public int getYearReleased () {return yearReleased; } viešoji eilutė getMovieDirectorName () {return movieDirectorName; } public String getMovieRating () {return movieRating; } @Paisyti viešojo int hashCode () {int hash = 3; maišos = 89 * maišos + Objektai.hashCode (this.movieTitle); maišas = 89 * maiša + tai.metaiIšleista; hash = 89 * maiša + Objects.hashCode (this.movieDirectorName); hash = 89 * maiša + Objects.hashCode (this.movieRating); grąžinimo maišos; } @Paisyti viešosios loginės loginės vertės lygu (Object obj) {if (obj == null) {return false; } if (getClass ()! = obj.getClass ()) {grąžinti klaidingą; } final Movie other = (Filmas) obj; if (! Objects.equals (this.movieTitle, other.movieTitle)) {grąžinti klaidingą; } if (tai.metu Išleista! = kita.metu Išleista) {grąžinti klaidingą; } if (! Objects.equals (this.movieDirectorName, other.movieDirectorName)) {grąžinti klaidingą; } if (! Objects.equals (this.movieRating, other.movieRating)) {return false; } return true; } @Paisyti viešą eilutę toString () {return "Movie {" + "movieTitle =" + movieTitle + ", yearReleased =" + yearReleased + ", movieDirectorName =" + movieDirectorName + ", movieRating =" + movieRating + '}'; }} 

Kelių detalių grąžinimas viename objekte

 / ** * Pateikite informaciją apie filmą. * * @return Filmo informacija. * / public Movie getMovieInfo () {grąžinti naują filmą („Užmarštis“, 2013 m., „Joseph Kosinski“, „PG-13“); } 

Paprastas Filmas klasė man užtruko apie 5 minutes. „NetBeans“ klasės kūrimo vedliu pasirinkau klasės pavadinimą ir paketą, tada įrašiau keturis klasės atributus. Iš ten paprasčiausiai naudojau „NetBeans“ „Insert Code“ mechanizmą, kad įterpčiau „get“ prieigos metodus kartu su nepaisytais toString (), hashCode () ir equals (Object) metodais. Jei nemanau, kad man to reikia, galėčiau išlaikyti klasę paprastesnę, tačiau ją tikrai lengva sukurti tokią, kokia yra. Dabar aš turiu daug labiau naudojamą grąžinimo tipą ir tai atspindi kodas, kuriame naudojama klasė. Jam nereikia beveik tiek daug „Javadoc“ komentarų apie grąžinimo tipą, nes tas tipas kalba pats už save ir reklamuoja savo turinį „get“ metodais. Manau, kad nedaug papildomų pastangų sukurti šias paprastas klases, skirtas grąžinti kelias vertes, atsiperka su didžiuliais dividendais, palyginti su tokiomis alternatyvomis kaip grįžtanti būsena naudojant metodo parametrus arba naudojant bendresnes ir sunkiau naudojamas grąžinimo duomenų struktūras.

Nenuostabu, kad pasirinktinis tipas, kuriuo laikomos kelios vertės, kurias reikia grąžinti skambinančiajam, yra patrauklus sprendimas. Galų gale, tai konceptualiai labai panašu į sąvokas, apie kurias anksčiau rašiau tinklaraštyje, susijusias su pasirinktinių tipų ir parametrų objektų naudojimu keliems susijusiems parametrams perduoti, o ne kiekvienam atskirai. „Java“ yra į objektą orientuota kalba, todėl mane nustebina, kai nematau objektų, dažniau naudojamų „Java“ kode parametrams IR grąžinti vertes gražiame pakete.

Privalumai ir pranašumai

Pasirinktinių parametrų objektų naudojimo keliems grąžinimo vertėms atspindėti ir apibendrinti privalumai yra akivaizdūs. Metodo parametrai gali likti „įvesties“ parametrais, nes visą išvesties informaciją (išskyrus klaidų informaciją, perduodamą per išimties mechanizmą) galima pateikti metodo grąžintame pasirinktiniame objekte. Tai yra švaresnis požiūris nei naudojant bendruosius masyvus, kolekcijas, žemėlapius, rinkinius ar kitas bendrąsias duomenų struktūras, nes visi šie alternatyvūs metodai nukreipia kūrimo pastangas į visus potencialius klientus.

Išlaidos ir trūkumai

Matau labai mažai trūkumų rašant pasirinktinius tipus su keliomis reikšmėmis, kurie bus naudojami kaip „Java“ metodų grąžinimo tipai. Galbūt dažniausiai nurodoma kaina yra šių klasių rašymo ir testavimo kaina, tačiau šios išlaidos yra gana mažos, nes šios klasės yra paprastos ir todėl, kad šiuolaikiniai IDE už mus daugiausiai dirba. Kadangi IDE tai daro automatiškai, kodas paprastai yra teisingas. Klasės yra tokios paprastos, kad jas lengvai perskaito kodų apžvalgininkai ir jas lengva išbandyti.

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