Konstante u Javi: uzorci i anti-uzorci

1. Uvod

U ovom ćemo članku naučiti o korištenju konstanti u Javi s naglaskom na uobičajene uzorke i anti-obrasce.

Počet ćemo s nekim osnovnim konvencijama za definiranje konstanti. Odatle ćemo prijeći na uobičajene anti-uzorke prije nego što završimo s osvrtom na uobičajene uzorke.

2. Osnove

Konstanta je varijabla čija se vrijednost neće promijeniti nakon što je definirana.

Pogledajmo osnove definiranja konstante:

privatni statički konačni int OUR_CONSTANT = 1;

Neki od uzoraka koje ćemo pogledati adresirat će javnost ili privatni odluka o modifikatoru pristupa. Mi činimo svoje konstante statički i konačni i dajte im odgovarajući tip, bilo da je to Java primitiv, klasa ili nabrajanje. Ime bi trebalo biti velika slova s ​​riječima odvojenim podvlakama, ponekad poznat i kao vrišteći zmijski slučaj. Konačno, pružamo samu vrijednost.

3. Anti-uzorci

Prvo, krenimo s učenjem što ne treba raditi. Pogledajmo nekoliko uobičajenih anti-obrazaca s kojima bismo se mogli susresti u radu s Java konstantama.

3.1. Čarobni brojevi

Magični brojevi su numerički literali u bloku koda:

if (broj == 3.14159265359) {// ...}

Teško ih razumiju drugi programeri. Uz to, ako koristimo broj u cijelom kodu, teško je riješiti promjenu vrijednosti. Umjesto toga trebali bismo definirati broj kao konstantu.

3.2. Klasa velikih globalnih konstanti

Kad započnemo projekt, moglo bi biti prirodno stvoriti razred s imenom Konstante ili Utils s namjerom da se definiraju sve konstante tamošnje primjene. Za manje projekte to bi moglo biti u redu, ali razmotrimo nekoliko razloga zašto ovo nije idealno rješenje.

Prvo, zamislimo da imamo stotinu ili više konstanti, sve u našem razredu konstanti. Ako se klasa ne održi, kako bi se išlo u korak s dokumentacijom i povremeno refaktoriralo konstante u logičke grupacije, postat će prilično nečitljivo. Mogli bismo završiti i s dvostrukim konstantama s malo drugačijim imenima. Ovaj pristup vjerojatno će nam stvoriti probleme s čitljivošću i održavanjem u bilo čemu osim u najmanjim projektima.

Pored logistike održavanja Konstante klase, pozivamo i druge probleme održavanja potičući preveliku međuovisnost s ovom jedinstvenom globalnom konstantnom klasom i raznim drugim dijelovima naše aplikacije.

S tehničke strane, Java prevodilac stavlja vrijednost konstante u referenciranje varijabli u klasama u kojima ih koristimo. Dakle, ako promijenimo jednu od naših konstanti u klasi konstanti i samo prekompajliramo tu klasu, a ne referentnu klasu, možemo dobiti nedosljedne konstantne vrijednosti.

3.3. Stalno sučelje protiv uzoraka

Stalni obrazac sučelja je kada definiramo sučelje koje sadrži sve konstante za određenu funkcionalnost, a zatim imamo klase koje trebaju te funkcionalnosti za implementaciju sučelja.

Definirajmo konstantno sučelje za kalkulator:

javno sučelje CalculatorConstants {double PI = 3.14159265359; dvostruko UPPER_LIMIT = 0x1.fffffffffffffP + 1023; enum Operacija {ADD, SUBTRACT, MULTIPLY, DIVIDE}; }

Dalje ćemo implementirati naš KalkulatorContants sučelje:

javna klasa GeometryCalculator implementira CalculatorConstants {javni dvostruki operateOnTwoNumbers (double numberOne, double numberTwo, Operation operation) {// Kôd za izvršavanje operacije}}

Prvi argument protiv upotrebe konstantnog sučelja je da se on protivi svrsi sučelja. Trebali bismo koristiti sučelja za stvaranje ugovora za ponašanje koje će pružati naše izvedbene klase. Kada kreiramo sučelje puno konstanti, ne definiramo nikakvo ponašanje.

Drugo, upotreba stalnog sučelja otvara nas za probleme u vremenu izvođenja uzrokovane zasjenjenjem polja. Pogledajmo kako bi se to moglo dogoditi definiranjem a GORNJA GRANICA konstanta unutar našeg GeometryCalculator razred:

javni statički konačni dvostruki UPPER_LIMIT = 100000000000000000000.0;

Jednom kad definiramo tu konstantu u našem GeometryCalculator klase, vrijednost skrivamo u KalkulatorContants sučelje za našu klasu. Tada bismo mogli dobiti neočekivane rezultate.

Još jedan argument protiv ovog anti-obrasca je taj što uzrokuje onečišćenje prostora imena. Naše KalkulatorContants sada će biti u prostoru imena bilo koje naše klase koja implementira sučelje, kao i bilo koje njihove podklase.

4. Obrasci

Ranije smo pogledali odgovarajući obrazac za definiranje konstanti. Pogledajmo neke druge dobre prakse za definiranje konstanti u našim aplikacijama.

4.1. Opće dobre prakse

Ako su konstante logički povezane s klasom, možemo ih tamo samo definirati. Ako skup konstanti promatramo kao članove pobrojanog tipa, možemo koristiti nabrajanje da ih definira.

Definirajmo neke konstante u a Kalkulator razred:

Kalkulator javne klase {javni statički konačni dvostruki PI = 3,14159265359; privatni statički završni dvostruki UPPER_LIMIT = 0x1.ffffffffffffffP + 1023; javna enum operacija {ADD, SUBTRACT, DIVIDE, MULTIPLY} javna dvostruka operacijaOnTwoNumbers (double numberOne, double numberTwo, Operation operation) {if (numberOne> UPPER_LIMIT) {throw new IllegalArgumentException ("'numberOne' is prevelik"); } if (numberTwo> UPPER_LIMIT) {baciti novo IllegalArgumentException ("'numberTwo' je prevelik"); } dvostruki odgovor = 0; prekidač (operacija) {case ADD: answer = numberOne + numberTwo; pauza; case IZUZMI: odgovor = numberOne - numberTwo; pauza; slučaj DIJELI: odgovor = numberOne / numberTwo; pauza; slučaj VIŠE: odgovor = brojOn * brojDva; pauza; } odgovor na povratak; }}

U našem smo primjeru definirali konstantu za GORNJA GRANICA koje planiramo koristiti samo u Kalkulator klase, pa smo to postavili privatni. Želimo da se drugi razredi mogu koristiti PI i Operacija enum, pa smo ih postavili na javnost.

Razmotrimo neke od prednosti upotrebe nabrajanje za Operacija. Prva prednost je što ograničava moguće vrijednosti. Zamislite da naša metoda uzima vrijednost za vrijednost operacije s očekivanjem da je dostavljen jedan od četiri konstantna niza. Lako možemo predvidjeti scenarij u kojem programer koji poziva metodu šalje vlastitu vrijednost niza. Uz nabrajanje, vrijednosti su ograničene na one koje definiramo. Također možemo vidjeti da su enumi posebno pogodni za upotrebu u sklopka izjave.

4.2. Stalne klase

Sad kad smo pogledali neke opće dobre prakse, razmotrimo slučaj kada bi klasa konstanti mogla biti dobra ideja. Zamislimo da naša aplikacija sadrži paket klasa koje trebaju izvoditi razne vrste matematičkih izračuna. U ovom slučaju, vjerojatno ima smisla za nas definirati klasu konstanti u tom paketu za konstante koje ćemo koristiti u našim klasama izračuna.

Stvorimo a MathConstants razred:

javni završni razred MathConstants {javni statički završni dvostruki PI = 3,14159265359; statički konačni dvostruki GOLDEN_RATIO = 1.6180; statički konačni dvostruki GRAVITATIONAL_ACCELERATION = 9,8; statički konačni dvostruki EULERS_NUMBER = 2.7182818284590452353602874713527; javna enum operacija {ADD, SUBTRACT, DIVIDE, MULTIPLY} private MathConstants () {}}

Prvo što bismo trebali primijetiti je to naš razred je konačni kako bi se spriječilo njegovo produljenje. Uz to, definirali smo i privatni konstruktor tako da se ne može instancirati. Konačno, možemo vidjeti da smo primijenili i ostale dobre prakse o kojima smo raspravljali ranije u članku. Naša konstanta PI je javnost jer predviđamo da mu treba pristupiti izvan našeg paketa. Ostale konstante koje smo ostavili kao paket-privatni, tako da im možemo pristupiti unutar našeg paketa. Napravili smo sve naše konstante statički i konačni i imenovao ih u slučaju vrišteće zmije. Operacije su određeni skup vrijednosti, pa smo koristili nabrajanje da ih definira.

Vidimo da se naša specifična klasa konstanti na razini paketa razlikuje od velike globalne klase konstanti jer je lokalizirana za naš paket i sadrži konstante relevantne za klase tog paketa.

5. Zaključak

U ovom smo članku razmotrili prednosti i nedostatke nekih od najpopularnijih uzoraka i anti-uzoraka koji se vide prilikom upotrebe konstanti u Javi. Počeli smo s nekim osnovnim pravilima oblikovanja, prije nego što smo pokrili anti-uzorke. Nakon što smo saznali nekoliko uobičajenih anti-obrazaca, pogledali smo uzorke koje često vidimo primijenjene na konstante.

Kao i uvijek kod je dostupan na GitHub-u.