Vilka misstag bör man undvika när man programmerar i Java? I följande stycke besvarar vi denna fråga.
Java är ett populärt språk med en etablerad ställning i världen av Utveckling av programvara. Det är ett starkt och mångsidigt programmeringsspråk. Cirka 3 miljarder enheter världen över körs på Java och därför gjordes minst 3 miljarder misstag när man använde den. I den här artikeln fokuserar vi på hur man inte gör några fler.
1. Få undantag för samtidig modifiering
Det här är det absolut vanligaste misstaget jag har stött på. I början av min karriär gjorde jag det många gånger också. Detta misstag uppstår när du försöker modifiera samlingen medan du itererar genom den. Den ConcurrentModificationException kan också uppstå när du arbetar med flera trådar, men för tillfället fokuserar vi på ett basscenario.
Anta att du har en Samling av användare där vissa av dem är vuxna och andra inte. Din uppgift är att filtrera bort barnen.
för (användare : användare) {
if (!user.isAdult()) {
users.remove(användare);
}
}
Körning av den tidigare nämnda kod slutar med att få ConcurrentModificationException. Var gick vi fel? Innan vi avslutade vår iteration försökte vi ta bort några element. Det är det som utlöser undantaget.
Hur kan jag undvika det?
Det finns ett par tillvägagångssätt som kan hjälpa till i det fallet. Först och främst, dra nytta av Java 8:ans godhet - Ström.
List vuxna = användare.stream()
.filter(Användare::isAdult)
.toList();
Använda en Predikat filter har vi gjort det omvända av det tidigare villkoret - nu bestämmer vi vilka element som ska inkluderas. Fördelen med ett sådant tillvägagångssätt är att det är lätt att kedja andra funktioner efter borttagningen, t.ex. karta. Men för guds skull, försök inte att göra något liknande som nedan:
Den kan också hamna i ConcurrentModificationException eftersom du ändrar strömkällan. Det kan också ge dig några fler undantag som inte kommer att vara lätta att felsöka.
För att lösa ConcurrentModificationException i ett scenario med en enda tråd. Du kan också byta till att använda direkt Iterator och dess ta bort() metoden, eller så kan du helt enkelt inte ta bort element under iterationen. Min rekommendation är dock att använda Strömmar - det är 2022.
2. Lagra lösenord som strängar
Eftersom jag blir mer och mer involverad i cybersäkerhet skulle jag inte vara sann mot mig själv om jag inte nämnde minst en Java-misstag som kan leda till ett säkerhetsproblem. Att lagra lösenord som tas emot från användare i en Sträng objekt är precis något du borde vara rädd för.
Problemet (eller kanske fördelen) med Sträng är att det är oföränderligt. I en cybervärld utgör detta ett potentiellt hot eftersom det inte går att återställa värdet på en en gång skapad Sträng objekt. En angripare som får tillgång till din dators minne kan hitta lösenord i klartext där.
För det andra, strängar i Java internaliseras av JVM och lagras i PermGen-utrymmet eller i heap-utrymmet. När du skapar en Sträng objektet, cachas det och tas bort först när Garbage Collector börjar göra sitt jobb. Du kan inte vara säker på när ditt lösenord tas bort från String-poolen eftersom Garbage Collector arbetar på ett icke-deterministiskt sätt.
Hur undviker man det?
Det rekommenderade tillvägagångssättet är att använda char[] eller, ännu bättre, ett bibliotek som stöder lagring av lösenord som char[], t.ex.Lösenord4j. Den char[] array är föränderlig och kan ändras efter att den har initialiserats. När du har bearbetat ett lösenord kan du bara radera char[] lösenordsarray genom att skriva slumpmässiga tecken i den. Om angriparna får tillgång till din dators minne kommer de bara att se några slumpmässiga värden som inte har något att göra med användarnas lösenord.
3. (O)hantering av undantag
Nybörjare och även mer avancerade programmerare vet inte hur man hanterar undantag på rätt sätt. Deras största synd i den frågan är att bara ignorera dem. DET ÄR ALDRIG ETT BRA TILLVÄGAGÅNGSSÄTT.
Tyvärr kan vi inte ge dig en universallösning som passar in i varje Undantags-scenario som du stöter på. Du måste tänka på varje fall separat. Vi kan dock ge dig några råd om hur du kan komma igång med det ämnet.
Hur kan jag undvika det?
Ignorering Undantagär aldrig en bra metod. Undantags är inlagda av någon anledning, så du bör inte ignorera dem.
try {...} catch(Undantag e) { log(e); } är sällan den rätta metoden för att Undantag hantering.
Nedkastning Undantag, visa en feldialog för användaren eller åtminstone lägga till ett omfattande meddelande i loggen.
Om du lämnade dina undantag obehandlade (vilket du inte borde), förklara åtminstone dig själv i kommentaren.
4. Använda noll
Tyvärr är det ganska vanligt att hitta en Java-funktion som i vissa fall returnerar en noll. Problemet är att en sådan funktion tvingar sin klient att utföra en null-kontroll på resultatet. Utan detta kommer NullPointerException kastas.
Den andra saken är att skicka en noll ...värde. Varför tänkte du ens på det? I ett sådant fall måste funktionen utföra en null-kontroll. När du använder tredjepartsbibliotek kan du inte ändra funktionernas insida. Vad gör man då?
Ännu viktigare är att andra utvecklare som läser din kod och ser att du klarar noll kommer förmodligen att bli förvirrade över varför du väljer ett så bisarrt sätt att implementera din funktion.
Hur kan jag undvika det?
Returnera inte ett noll värde! Aldrig någonsin! Om din funktion returnerar någon typ av Samlingkan du bara returnera en tom Samling. Om du hanterar enstaka objekt kan du använda designmönstret null object. Sedan Java 8, är den implementerad som Valfritt. I övrigt är det minst rekommenderade tillvägagångssättet att väcka en Undantag.
5. Tung strängkonkatenering
Förhoppningsvis är det inte ett misstag du gör, eftersom det är den mest populära (eller kanske näst mest populära efter FizzBuzz) intervjufrågan. Som du borde veta vid det här laget är en Sträng objektet är oföränderligt i Java - När den väl har skapats kan den inte ändras. Så konkatenering av Sträng literaler innebär en hel del onödig minnesallokering. Konkatenering Sträng objekt varje gång kräver att man skapar en tillfällig StringBuilder objekt och ändra tillbaka det till en sträng. Därför är den här lösningen absolut inte lämplig om vi vill kombinera ett stort antal tecken.
Hur kan jag undvika det?
För att lösa det problemet använder du StringBuilder. Det skapar ett föränderligt objekt som lätt kan manipuleras. Naturligtvis kan du alltid använda StringBuffer om din projekt används i ett samtidigt sammanhang.
6. Att inte använda befintliga lösningar
När man utvecklar programvara är det ett måste att lära sig grunderna i det språk man skriver på, men det räcker inte. Många algoritmiska problem som du stöter på när du implementerar en ny funktion har redan lösts av någon annan. Alltför många gånger har jag sett någon implementera en säkerhetsalgoritm från grunden. Ett sådant tillvägagångssätt är felbenäget. En person kan inte testa en sådan komplex lösning grundligt. Den kollektiva kunskapen hos Team som består av medelavancerade programmerare är nästan alltid bättre än storheten hos ett underbarn Java-utvecklare. Du behöver inte uppfinna hjulet på nytt - du behöver bara anpassa den befintliga lösningen så att den passar dina behov.
Hur kan jag undvika det?
Försök att söka efter bibliotek som tar upp det problem du arbetar med. Försök att hitta liknande lösningar. Många av de bibliotek som finns tillgängliga på webben är gratis och har polerats och testats av erfarna utvecklare och hela Java-communityn. Var inte rädd för att använda dem.
7. Inte tillräckligt med tid för att skriva tester
Det är frestande att tro att vår kod alltid kommer att fungera perfekt. Att inte skriva tester för kod är den värsta synden av alla Java Programvaruutvecklare. Många av oss föredrar manuella och utforskande tester istället för enhetstester, vilket är helt galet. Varför slösa tid på att skriva tester när du kan fokusera på att tillhandahålla världens bästa kod för ditt projekt, som DEFINITIVT inte har några buggar? Det visar sig att verkligheten är brutal och att vi inte kan tillhandahålla högkvalitativ kod utan att skriva tester.
Hur kan jag undvika det?
Du bör alltid förbereda tester för din kod. Jag vet att TDD-metoden inte är så lätt att underhålla, men du bör åtminstone tillhandahålla tester som täcker alla förhållanden under vilka din kod kan köras. Detta inkluderar testning av exceptionella situationer. Enhetstesterna är nödvändiga. Du måste tillhandahålla dem för varje funktion i ditt projekt om du vill se till att din kod är lätt att refaktorisera och utöka i vidareutveckling.
En sak till. Håll en hög standard på din testkod - det kommer att vara värt det. Det är farbror Bobs råd och jag håller helt med om det.
Dessutom får du inte glömma bort andra typer av tester. Integrationstester är något du bör tänka på i alla dina projekt.
8. Att glömma bort accessmodifierare
Privat och offentligt, eller hur? Hur kan vi glömma bort dem. Det visar sig att det finns fler. När du först började lära dig Javahar du definitivt lärt dig om modifierare för skyddad åtkomst. De kan vara användbara i vissa fall, så det är värt att känna till deras existens.
Java-utvecklare verkar ofta glömma bort paketets omfattning. Det är lätt att inte komma ihåg att använda det eftersom det är implicit och inte kräver någon Java nyckelord. Paketets omfattning är viktig. Det gör att du kan testa en skyddad metod. Skyddade objekt är tillgängliga från testklassens sökväg, så länge som paketet är detsamma.
Hur kan jag undvika det?
Kom ihåg den skyddade modifieraren och att paketets omfattning gör att du kan testa den.
9. Använda ren JavaEE istället för Spring
Nästa steg efter inlärning Java SE ska lära sig hur man kör Java på servrar, hur man skapar en applikation på företagsnivå.
Nybörjare går ofta i fällan att lära sig JavaEE eftersom det finns ett stort antal handledningar om det. Till och med "Thinking in Java", den Java-programmerare' nämner JavaEE och säger ingenting om de andra alternativen.
Hur kan jag undvika det?
JavaEE är en sång från det förflutna. Numera är Spring en självklarhet och Java EE är bara trevligt att ha. Varje modern applikation på företagsnivå använder Spring, så du bör starkt överväga att lära dig den här.