9 fouten die je moet vermijden bij het programmeren in Java
Rafal Sawicki
Java Ontwikkelaar
Welke fouten moet je vermijden bij het programmeren in Java? In het volgende stuk beantwoorden we deze vraag.
Java is een populaire taal met een gevestigde positie in de wereld van softwareontwikkeling. Het is een sterke en veelzijdige programmeertaal. Ongeveer 3 miljard apparaten wereldwijd draaien op Java en daarom zijn er minstens 3 miljard fouten gemaakt bij het gebruik ervan. Laten we ons in dit artikel richten op hoe je er niet nog meer maakt.
1. Een gelijktijdige wijzigingsuitzondering krijgen
Dit is verreweg de meest voorkomende fout die ik ben tegengekomen. In het begin van mijn carrière heb ik deze fout ook vaak gemaakt. Deze fout treedt op wanneer je de collectie probeert aan te passen terwijl je er doorheen itereert. De ConcurrentModificationException kan ook ontstaan als je met meerdere threads werkt, maar laten we ons nu richten op een basisscenario.
Stel dat je een Collectie van gebruikers waarvan sommige volwassenen zijn en andere niet. Het is jouw taak om de kinderen eruit te filteren.
for (Gebruiker : gebruikers) {
als (!user.isAdult()) {
users.remove(gebruiker);
}
}
Het uitvoeren van de eerder genoemde code eindigt in het krijgen van ConcurrentModificationException. Waar ging het mis? Voordat we onze iteratie voltooiden, probeerden we enkele elementen te verwijderen. Dat is wat de uitzondering veroorzaakt.
Hoe kan ik het vermijden?
Er zijn een paar manieren die in dat geval kunnen helpen. Eerst en vooral kun je profiteren van Java 8's goedheid - Stroom.
Een Predicaat filter hebben we het omgekeerde gedaan van de vorige voorwaarde - nu bepalen we elementen om op te nemen. Het voordeel van een dergelijke aanpak is dat het eenvoudig is om andere functies te koppelen na het verwijderen, bijv. kaart. Maar in hemelsnaam, probeer alsjeblieft niet zoiets als hieronder te doen:
Het kan ook terechtkomen in de ConcurrentModificationException omdat je de bron van de stream wijzigt. Het kan ook meer uitzonderingen opleveren die niet eenvoudig te debuggen zijn.
Oplossen ConcurrentModificationException in een single-thread scenario. Je kunt ook overschakelen op het direct gebruiken van Iterator en zijn verwijderen() methode, of je zou gewoon geen elementen kunnen verwijderen tijdens de iteratie. Mijn aanbeveling is echter om Stromen - het is 2022.
2. Wachtwoorden opslaan als strings
Nu ik steeds meer betrokken raak bij cybersec, zou ik niet trouw zijn aan mezelf als ik niet ten minste één ding zou noemen Java fout dat kan leiden tot een beveiligingsprobleem. Het opslaan van wachtwoorden van gebruikers in een String object is precies iets waar je bang voor moet zijn.
Het probleem (of misschien voordeel) van String is dat het onveranderlijk is. In de cyberseced wereld creëert dit een potentiële bedreiging omdat je de waarde van een eenmaal gecreëerde String object. De aanvaller die toegang krijgt tot het geheugen van je computer kan daar wachtwoorden in platte tekst vinden.
Ten tweede, strings in Java worden geïnterneerd door de JVM en opgeslagen in de PermGen-ruimte of in de heap-ruimte. Wanneer je een String object, wordt het in de cache geplaatst en wordt het pas verwijderd als de Garbage Collector zijn werk gaat doen. U kunt er niet zeker van zijn wanneer uw wachtwoord wordt verwijderd uit de String-pool, omdat de Garbage Collector op een niet-deterministische manier werkt.
Hoe vermijd je het?
De aanbevolen aanpak is om char[] of, nog beter, de bibliotheek die het opslaan van wachtwoorden ondersteunt als char[]bijv.Wachtwoord4j. De char[] array is muteerbaar en kan worden gewijzigd nadat het is geïnitialiseerd. Na het verwerken van een wachtwoord kunt u de char[] wachtwoord array door er willekeurige tekens in te schrijven. In het geval dat de aanvallers toegang krijgen tot het geheugen van je computer, zullen ze alleen een aantal willekeurige waarden zien die niets te maken hebben met de wachtwoorden van gebruikers.
3. (On)afhandeling van uitzonderingen
Nieuwelingen en ook meer gevorderde programmeurs weten niet hoe ze correct met uitzonderingen moeten omgaan. Hun grootste zonde op dat gebied is ze gewoon negeren. DAT IS NOOIT EEN GOEDE AANPAK.
Helaas kunnen we je geen kant-en-klare oplossing bieden die in elke situatie past. Uitzonderings' scenario dat je tegenkomt. Je moet over elk geval apart nadenken. We kunnen je echter wel wat advies geven over hoe je hiermee aan de slag kunt gaan.
Hoe kan ik het vermijden?
negeren Uitzonderings is nooit een goede gewoonte. Uitzonderings worden er om de een of andere reden ingegooid, dus je moet ze niet negeren.
try {...} catch(Exception e) { log(e); } is zelden de juiste benadering van Uitzondering behandeling.
Rethrow Uitzonderingeen foutdialoogvenster tonen aan de gebruiker of op zijn minst een uitgebreid bericht toevoegen aan het logboek.
Als je je uitzonderingen onbehandeld hebt gelaten (wat je niet zou moeten doen), leg jezelf dan op zijn minst uit in het commentaar.
4. Nul gebruiken
Helaas komt het vaak voor dat een Java-functie in sommige gevallen een nul. Het probleem is dat zo'n functie zijn client dwingt om een null-controle op het resultaat uit te voeren. Zonder deze controle zal de NullPointerException wordt gegooid.
Het andere is het passeren van een nul waarde. Waarom heb je daar zelfs maar aan gedacht? In zo'n geval moet de functie een null-check uitvoeren. Wanneer je bibliotheken van derden gebruikt, kun je de binnenkant van de functies niet wijzigen. Wat dan?
Nog belangrijker is dat andere ontwikkelaars die je code lezen en zien dat je de nul zullen waarschijnlijk niet begrijpen waarom je zo'n bizarre manier hebt gekozen om je functie te implementeren.
Hoe kan ik het vermijden?
Stuur geen nul waarde! Ooit! Als je functie een soort Collectiekun je gewoon een lege Collectie. Als je te maken hebt met enkelvoudige objecten, kun je gebruik maken van het null object design pattern. Aangezien Java 8 wordt geïmplementeerd als Optioneel. Anders dan dat, is de minst aanbevolen aanpak het verhogen van een Uitzondering.
5. Zware String-aaneenschakeling
Hopelijk maak je deze fout niet, want het is de populairste (of misschien wel de op één na populairste na FizzBuzz) interviewvraag. Zoals je inmiddels zou moeten weten, is een String object is onveranderlijk in Java - Eenmaal aangemaakt, kan het niet worden gewijzigd. Dus aaneenschakeling van String betekent veel onnodige geheugentoewijzing. Aaneenschakelen van String objecten telkens een tijdelijke StringBuilder object en het terugveranderen naar een tekenreeks. Daarom is deze oplossing absoluut niet geschikt als we een groot aantal tekens willen combineren.
Hoe kan ik het vermijden?
Om dat probleem op te lossen, gebruik je StringBuilder. Het creëert een veranderlijk object dat gemakkelijk kan worden gemanipuleerd. Natuurlijk kun je altijd StringBuffer als uw project wordt gebruikt in een gelijktijdige context.
6. Bestaande oplossingen niet gebruiken
Bij het ontwikkelen van software is kennis van de basis van de taal waarin je schrijft een must, maar niet genoeg. Veel algoritmische problemen die je tegenkomt tijdens het implementeren van een nieuwe functie zijn al door iemand anders opgelost. Te vaak heb ik iemand een beveiligingsalgoritme vanaf nul zien implementeren. Zo'n aanpak is foutgevoelig. Eén persoon kan zo'n complexe oplossing niet grondig testen. De collectieve kennis van de team die bestaat uit gemiddeld gevorderde programmeurs is bijna altijd beter dan de grootsheid van één wonderkind. Java-ontwikkelaar. Je hoeft het wiel niet opnieuw uit te vinden - je hoeft alleen de bestaande oplossing aan te passen aan jouw behoeften.
Hoe kan ik het vermijden?
Probeer te zoeken naar bibliotheken die het probleem waar je aan werkt aanpakken. Probeer vergelijkbare oplossingen te vinden. Veel van de bibliotheken die beschikbaar zijn op het web zijn gratis en zijn gepolijst en getest door ervaren ontwikkelaars en de hele Java-gemeenschap. Wees niet bang om ze te gebruiken.
7. Niet genoeg tijd vinden voor het schrijven van tests
Het is verleidelijk om te geloven dat onze code altijd perfect zal werken. Het niet schrijven van tests voor code is de ergste zonde van Java softwareontwikkelaars. Velen van ons geven de voorkeur aan handmatige en verkennende tests in plaats van unit tests, en dat is bonkers. Waarom tijd verspillen aan het schrijven van tests als je je kunt richten op het leveren van 's werelds beste code voor je project, die DEFINITIEEL geen bugs heeft?<joke>. Het blijkt dat de realiteit wreed is en we geen code van hoge kwaliteit kunnen leveren zonder tests te schrijven.
Hoe kan ik het vermijden?
Je moet altijd tests voorbereiden voor je code. Ik weet dat de TDD-aanpak niet zo gemakkelijk te onderhouden is, maar je zou op zijn minst tests moeten maken die alle omstandigheden dekken waarin je code kan worden uitgevoerd. Dit is inclusief het testen van uitzonderlijke situaties. De unit tests zijn noodzakelijk. Je moet ze voor elke functie van je project maken als je er zeker van wilt zijn dat je code gemakkelijk te refactoren en uit te breiden is bij verdere ontwikkeling.
Nog één ding. Zorg voor een hoge standaard van je testcode - het zal de moeite waard zijn. Dat is het advies van oom Bob en ik ben het er helemaal mee eens.
Vergeet ook andere soorten tests niet. Integratietests zijn iets wat je in elk project moet overwegen.
8. Toegangsmodifiers vergeten
Privé en openbaar, toch? Hoe kunnen we die vergeten? Het blijkt dat er meer zijn. Toen je voor het eerst Javaheb je zeker geleerd over beschermde toegangsmodifiers. Ze kunnen in sommige gevallen nuttig zijn, dus het is de moeite waard om van hun bestaan op de hoogte te zijn.
Java-ontwikkelaars lijken vaak de package scope te vergeten. Het is gemakkelijk om het niet te onthouden omdat het impliciet is en geen Java trefwoorden. De package scope is belangrijk. Hiermee kun je een beschermde methode testen. Beschermde items zijn toegankelijk vanaf het pad van de testklasse, zolang het pakket hetzelfde is.
Hoe kan ik het vermijden?
Denk aan de protected modifier en dat je deze met de package scope kunt testen.
9. Gebruik van pure JavaEE in plaats van Spring
De volgende stap na het leren Java SE is om te leren hoe je Java op servers, hoe je een applicatie op bedrijfsniveau maakt.
Nieuwelingen trappen vaak in de val om JavaEE te leren omdat er een enorm aantal tutorials over bestaan. Zelfs 'Denken in Java', de Java programmeurs' bijbel, noemt JavaEE en zegt niets over de andere opties.
Hoe kan ik het vermijden?
JavaEE is een liedje uit het verleden. Tegenwoordig is Spring een go-to ding en is Java EE gewoon leuk om te hebben. Elke moderne bedrijfsapplicatie maakt gebruik van Spring, dus je moet zeker overwegen om het volgende te leren hier.