9 virhettä, joita kannattaa välttää Java-ohjelmoinnissa
Rafal Sawicki
Java-kehittäjä
Mitä virheitä tulisi välttää Java-ohjelmoinnissa? Seuraavassa kappaleessa vastaamme tähän kysymykseen.
Java on suosittu kieli, jolla on vakiintunut asema maailman ohjelmistokehitys. Se on vahva ja monipuolinen ohjelmointikieli. Noin 3 miljardia laitetta maailmassa käyttää Java ja siksi sitä käytettäessä tehtiin ainakin 3 miljardia virhettä. Tässä artikkelissa keskitytään siihen, miten niitä ei enää tehdä.
1. Samanaikaisen muokkauksen poikkeuksen saaminen
Tämä on ylivoimaisesti yleisin virhe, johon olen törmännyt. Urani alkuaikoina tein sen itsekin monta kertaa. Tämä virhe tapahtuu, kun yrität muuttaa kokoelmaa, kun käyt sitä läpi. The ConcurrentModificationException voi tulla esiin myös silloin, kun työskentelet useiden säikeiden kanssa, mutta keskitytään nyt perusskenaarioon.
Oletetaan, että sinulla on Kokoelma käyttäjiä, joista osa on aikuisia ja osa ei. Tehtävänäsi on suodattaa lapset pois.
for (Käyttäjä : käyttäjät) {
if (!user.isAdult()) {
users.remove(user);
}
}
Edellä mainitun koodi päättyy saamiseen ConcurrentModificationException. Missä menimme pieleen? Ennen iteraation päättämistä yritimme poistaa joitakin elementtejä. Se aiheuttaa poikkeuksen.
Miten voin välttää sen?
Tässä tapauksessa on pari lähestymistapaa, jotka voivat auttaa. Ensinnäkin, hyödyntää Java 8:n hyvyys - Stream.
List adults = users.stream()
.filter(User::isAdult)
.toList();
Käyttämällä Predikaatti suodattimen avulla olemme tehneet edellisen ehdon käänteisen - nyt määrittelemme mukaan otettavat elementit. Tällaisen lähestymistavan etuna on, että poiston jälkeen on helppo ketjuttaa muita funktioita, esim. kartta. Mutta herran tähden, älkää yrittäkö tehdä jotain alla olevan kaltaista:
Se voi päätyä myös ConcurrentModificationException koska muutat virran lähdettä. Se voi myös aiheuttaa lisää poikkeuksia, joita ei ole helppo korjata.
Ratkaista ConcurrentModificationException yhden säikeen skenaariossa. voit myös siirtyä käyttämään suoraan Iteraattori ja sen remove() metodilla, tai voit yksinkertaisesti olla poistamatta elementtejä iteraation aikana. Suosittelen kuitenkin käyttämään Virrat - on vuosi 2022.
2. Salasanojen tallentaminen merkkijonoina
Koska olen yhä enemmän tekemisissä kyberturvallisuuden kanssa, en olisi rehellinen itselleni, jos en mainitsisi ainakin yhtä asiaa. Java virhe joka voi johtaa tietoturvaongelmaan. Käyttäjiltä saatujen salasanojen tallentaminen merkkijono esine on juuri se, mitä sinun pitäisi pelätä.
Ongelmana (tai ehkä etuna) on merkkijono on, että se on muuttumaton. Tietoverkkomaailmassa se luo mahdollisen uhan, koska kerran luodun arvon tyhjentäminen ei ole mahdollista. merkkijono esine. Hyökkääjä, joka pääsee tietokoneen muistiin, voi löytää sieltä pelkkiä salasanoja.
Toiseksi, merkkijonot Java ovat JVM:n sisäistämiä ja ne tallennetaan PermGen-avaruuteen tai heap-avaruuteen. Kun luot merkkijono objekti, se tallennetaan välimuistiin, ja se poistetaan vasta, kun roskienkerääjä alkaa tehdä työtään. Et voi olla varma siitä, milloin salasanasi poistetaan String-poolista, koska Garbage Collector toimii epädeterministisesti.
Miten välttää sitä?
Suositeltava lähestymistapa on käyttää char[] tai, vielä parempi, kirjasto, joka tukee salasanojen tallentamista muodossa char[], esim.Password4j. . char[] array on muuttuva ja sitä voidaan muuttaa sen alustamisen jälkeen. Kun olet käsitellyt salasanan, voit vain poistaa sarjan char[] kirjoittamalla siihen satunnaisia merkkejä. Jos hyökkääjät pääsevät käsiksi tietokoneen muistiin, he näkevät vain satunnaisia arvoja, joilla ei ole mitään tekemistä käyttäjien salasanojen kanssa.
3. Poikkeusten (epä)käsittely
Aloittelevat ja edistyneemmät ohjelmoijat eivät osaa käsitellä poikkeuksia oikein. Heidän suurin syntinsä tässä asiassa on vain jättää ne huomiotta. SE EI OLE KOSKAAN HYVÄ LÄHESTYMISTAPA.
Valitettavasti emme voi antaa sinulle ratkaisua, joka sopii jokaiseen ongelmaan. Poikkeuss-skenaario, johon törmäät. Sinun on ajateltava jokaista tapausta erikseen. Voimme kuitenkin antaa sinulle neuvoja, miten päästä alkuun tässä asiassa.
Miten voin välttää sen?
Ei huomioida Poikkeuss ei ole koskaan hyvä käytäntö. Poikkeuss-merkinnät ovat mukana jostain syystä, joten niitä ei kannata jättää huomiotta.
try {...} catch(Exception e) { log(e); } on harvoin oikea lähestymistapa Poikkeus käsittely.
Heitto Poikkeus, näyttää virhevalintaikkunan käyttäjälle tai ainakin lisätä kattavan viestin lokiin.
Jos jätit poikkeukset käsittelemättä (mitä ei pitäisi tehdä), selitä se ainakin kommentissa.
4. Nollan käyttäminen
Valitettavasti on melko yleistä, että Java-funktio palauttaa joissakin tapauksissa takaisin null. Ongelmana on, että tällainen funktio pakottaa asiakkaansa suorittamaan tuloksen nollatarkastuksen. Ilman sitä NullPointerException heitetään.
Toinen asia on kulkee null arvo. Miksi edes ajattelit sitä? Tällaisessa tapauksessa funktion on suoritettava nollatarkistus. Kun käytät kolmannen osapuolen kirjastoja, et voi muuttaa funktioiden sisäosia. Mitä sitten?
Vielä tärkeämpää on se, että muut kehittäjät, jotka lukevat koodisi ja näkevät, että annat eteenpäin null on luultavasti hämmentynyt siitä, miksi olet valinnut näin oudon tavan toteuttaa ominaisuutesi.
Miten voin välttää sen?
Älä palauta null arvo! Koskaan! Jos funktiosi palauttaa jonkinlaisen Kokoelma, voit vain palauttaa tyhjän Kokoelma. Jos käsittelet yksittäisiä objekteja, voit käyttää null-objektin suunnittelumallia. Koska Java 8, se toteutetaan seuraavasti Valinnainen. Muuten vähiten suositeltava lähestymistapa on nostaa esiin Poikkeus.
5. Raskas merkkijonojen ketjutus
Toivottavasti et tee sitä virhettä, sillä se on suosituin (tai ehkä toiseksi suosituin FizzBuzzin jälkeen) haastattelukysymys. Kuten sinun pitäisi jo tietää, a merkkijono objekti on muuttumaton Java - kun se on kerran luotu, sitä ei voi muuttaa. Joten ketjuttaminen merkkijono literaalit tarkoittavat paljon tarpeetonta muistin varaamista. Yhdistäminen merkkijono objekteja joka kerta vaatii väliaikaisen StringBuilder objektin ja muuttaa sen takaisin merkkijonoksi. Siksi tämä ratkaisu ei todellakaan sovellu, jos haluamme yhdistää suuren määrän merkkejä.
Miten voin välttää sen?
Ratkaise tämä ongelma käyttämällä StringBuilder. Se luo muuttuvan objektin, jota voidaan helposti manipuloida. Tietenkin voit aina käyttää StringBuffer jos projekti käytetään samanaikaisessa yhteydessä.
6. Olemassa olevien ratkaisujen käyttämättä jättäminen
Ohjelmistoja kehitettäessä on välttämätöntä, mutta se ei riitä, että opit tuntemaan sen kielen perusteet, jolla kirjoitat. Joku muu on jo ratkaissut monet algoritmiset ongelmat, joihin törmäät uutta ominaisuutta toteuttaessasi. Liian monta kertaa olen nähnyt jonkun toteuttavan tietoturva-algoritmin tyhjästä. Tällainen lähestymistapa on virhealtis. Yksi henkilö ei voi testata perusteellisesti näin monimutkaista ratkaisua. Kollektiivinen tietämys joukkue joka koostuu keskitasoisista ohjelmoijista, on lähes aina parempi kuin yhden ihmelapsen suuruus. Java-kehittäjä. Sinun ei tarvitse keksiä pyörää uudelleen - sinun on vain mukautettava olemassa oleva ratkaisu tarpeisiisi.
Miten voin välttää sen?
Yritä etsiä kirjastoja, jotka käsittelevät ongelmaa, jonka parissa työskentelet. Yritä löytää samanlaisia ratkaisuja. Monet verkossa saatavilla olevista kirjastoista ovat ilmaisia, ja kokeneet kehittäjät ja koko Java-yhteisö ovat hioneet ja testanneet niitä. Älä pelkää hyödyntää niitä.
7. Testien kirjoittamiseen ei löydy riittävästi aikaa
On houkuttelevaa uskoa, että koodimme toimii aina täydellisesti. Testien kirjoittamatta jättäminen koodille on pahin synti. Java ohjelmistokehittäjät. Monet meistä suosivat yksikkötestien sijaan manuaalisia ja tutkivia testejä, mikä on hullua. Miksi tuhlaat aikaa testien kirjoittamiseen, kun voit keskittyä tarjoamaan maailman parasta koodia projektillesi, jossa EI TODELLAKAAN ole virheitä?<joke>. Kävi ilmi, että todellisuus on raaka, emmekä voi tarjota laadukasta koodia ilman testien kirjoittamista.
Miten voin välttää sen?
Sinun pitäisi aina valmistella testejä koodillesi. Tiedän, että TDD-lähestymistapa ei ole kovin helppo ylläpitää, mutta sinun pitäisi ainakin laatia testit, jotka kattavat kaikki olosuhteet, joissa koodisi voidaan suorittaa. Tähän sisältyy myös poikkeustilanteiden testaaminen. Yksikkötestit ovat välttämättömiä. Sinun on laadittava niitä projektisi jokaiselle ominaisuudelle, jos haluat varmistaa, että koodisi on helposti refaktoroitavissa ja laajennettavissa jatkokehityksessä.
Vielä yksi asia. Pidä testikoodisi korkeatasoinen - se on sen arvoista. Tämä on Bob-sedän neuvo, ja olen täysin samaa mieltä siitä.
Älä myöskään unohda muita testityyppejä. Integrointitestit on otettava huomioon jokaisessa projektissa.
8. Pääsymodifikaattorien unohtaminen
Yksityinen ja julkinen, eikö niin? Miten voimme unohtaa ne. Kävi ilmi, että niitä on enemmän. Kun aloitit oppimisen Java, olet varmasti oppinut suojattujen käyttöoikeuksien muokkaajista. Niistä voi olla hyötyä joissakin tapauksissa, joten niiden olemassaolosta kannattaa olla tietoinen.
Java-kehittäjät näyttävät usein unohtavan paketin laajuuden. Sen käyttöä on helppo unohtaa, koska se on implisiittinen eikä vaadi mitään pakettipakettia. Java avainsanat. Paketin laajuus on tärkeä. Sen avulla voit testata suojattua metodia. Suojatut kohteet ovat käytettävissä testiluokan polusta, kunhan paketti on sama.
Miten voin välttää sen?
Muista suojattu modifioija ja se, että paketin laajuuden avulla voit testata sitä.
9. Puhtaan JavaEE:n käyttö Springin sijaan
Seuraava askel oppimisen jälkeen Java SE:n on opittava, miten Java palvelimilla, miten tehdään yritystason sovellus.
Aloittelijat lankeavat usein JavaEE:n oppimisen ansaan, koska siitä on olemassa valtava määrä opetusohjelmia. Jopa 'Thinking in Java', joka on Java-ohjelmoijat' raamatussa mainitaan JavaEE eikä puhuta mitään muista vaihtoehdoista.
Miten voin välttää sen?
JavaEE on menneisyyden laulu. Nykyään Spring on ihan oikea juttu, ja Java EE on vain kiva olla. Jokainen nykyaikainen yritystason sovellus käyttää Springiä, joten sinun kannattaa ehdottomasti harkita opettelevasi se täällä.