Blond udvikler: "Jeg forstår ikke den her kode"

Jeg har noget kode, der fejler med en exception, og jeg forstår ærlig talt ikke hvorfor, hvilket generer min faglige stolthed. Men måske er der nogle brunetter derude, som kan hjælpe?

Jeg får en NullPointerException i følgende stykke Java-kode:

Boolean result = allowCancel ?   
 DialogUtil.showYesNoCancelDialog(ownerComponent, message, title) :  
 DialogUtil.showYesOrNoDialog(ownerComponent, message, title);

når allowCancel = true og DialogUtil.showYesNoCancelDialog(...) returnerer null for at indikere, at brugeren trykkede Cancel. Det burde da ikke give en exception, når resultatet skal assignes til en Boolean (med stort B)?!

Hvis jeg i stedet skriver koden om til følgende:

Boolean result;            
if (allowCancel) {               *
*   result = DialogUtil.showYesNoCancelDialog(ownerComponent,  *
*                                                                 message, title);           *
* }           *
* else {               *
*  result = DialogUtil.showYesOrNoDialog(ownerComponent, *
*                                                          message, title);           *
* }

så får jeg ikke nogen exception... Men hvad er forskellen?

Kommentarer (65)
sortSortér kommentarer
  • Ældste først
  • Nyeste først
  • Bedste først
Kasper Henriksen

Læs Java Language Specifications afsnit om Conditional Operator 1, hvor der bl.a. står:

If one of the second and third operands is of type boolean and the type of the other is of type Boolean, then the type of the conditional expression is boolean.

Så mit gæt er, at showYesOrNoDialog() returnerer boolean, mens showYesNoCancelDialog() returnerer Boolean, og det er en fejl.

Kode, der bruger Boolean til at signalere mellem 3 mulige værdier, er hul i hovedet, hvilket fyrene bag Java Puzzlers da også kommenterer på i deres fremragende præsentation af et par problemer 2.

  • 0
  • 0
Andrew Rump

Som Kasper Henriksen skriver, så er det fordi showYesOrNoDialog() kan returnere to tilstande: True = Yes og False = No mens showYesNoCancelDialog() kan returnere tre tilstande: True = Yes, False = No, Null = Cancel - dvs. det er ikke en boolean i gængs forstand.

  • 0
  • 0
Nikolaj Brinch Jørgensen

Det er fordi Java sproget er en fejl der ikke burde være påstået .
Det var en fejl i første omgang at vi fik primitiverne som ikke var objekter. Men vi fik så objekt wrappers. Så lavede vi alle mulige utility libraries (som vi skrev igen og igen og igen ... og igen), til konvertering mellem dem, og reflection var ligeledes besværliggjort.
Men synes så man skulle lave et fiks i Java 5 med autoboxing, som netop kun løser konverteringen, men samtidigt fjerner det typecheck der ville være i Java 4.
Java er en super platofrm med en glimrende VM, men sproget, det er efterhånden ikke værd at beskæftige sig meget med.
Scala, Groovy, JRuby, Jaskell m.fl. giver meget smukkere programmer.

  • 0
  • 0
Jesper Udby

Scala, Groovy, JRuby, Jaskell m.fl. giver meget smukkere programmer.

Sikke noget bavl.

Mod elendige udviklere kæmper selv guderne forgæves, og ovenstående viser eksempel på rigtig dårlig stil, som intet programmeringssprog kan beskytte i mod.

At JAVA så i det konkrete tilfælde håndterer det skidt, er en anden historie.

En boolean datatype kan udtrykke om et givent udsagn er true eller false. En Boolean kan så også repræsentere at man ikke har taget stilling endnu.

På en dialog med Ja og Nej knapper kan man efterfølgende spørge: "blev der svaret Ja ?" og derved få en boolean. Man kan også spørge: "blev der svaret nej ?"...
Og at "null" så skulle svare til "annullér" er slemt. Hvad hvis det var en "OK / Annullér" dialog ? Er mulighederne der så "true / null" ?

Nej, på en dialog bør man kunne få at vide hvilket svar der blev givet; det kan være en String, int, enum eller lign. Sgudda ikke en boolean/Boolean!

Anne-Sofie: du må tilbage til dem der har designet DialogUtil API'et og bede dem om at tage sig gevaldigt sammen.

  • 0
  • 0
Jonas Høgh

At der ikke burde have være brugt Boolean her, ændrer ikke på at Javas wrappere rundt om primitive typer er et grimt hack. Til sammenligning er det meget pænere håndteret i C# med value types.

At C# så har arvet Javas dårligdom med at alle reference types kan være null, er en anden sag.

  • 0
  • 0
Michael Mortensen

At C# så har arvet Javas dårligdom med at alle reference types kan være null, er en anden sag.

Hvad mener du her?

Hvis en reference type ikke er initialiseret, eller den ikke skal bruges mere, så er det vel kun naturligt at den er null?

Kan du uddybe den påstået "dårligdom"?

På forhånd tak .. :-)

  • 0
  • 0
Jesper Udby

C#, Java, osv...

Brugen af diverse sprog ændrer ikke ved det faktum at den oprindelige løsning stinker...

Personligt holder jeg af at kode JAVA, hader PHP, synes SQL er fedt, især når det går op i en højere enhed, udholder JavaScript og koder PIC-assembler i fritiden...

  • 0
  • 0
Jonas Høgh

For example, in the type system we do not have separation between value and reference types and nullability of types. This may sound a little wonky or a little technical, but in C# reference types can be null, such as strings, but value types cannot be null. It sure would be nice to have had non-nullable reference types, so you could declare that ‘this string can never be null, and I want you compiler to check that I can never hit a null pointer here’.

50% of the bugs that people run into today, coding with C# in our platform, and the same is true of Java for that matter, are probably null reference exceptions. If we had had a stronger type system that would allow you to say that ‘this parameter may never be null, and you compiler please check that at every call, by doing static analysis of the code’. Then we could have stamped out classes of bugs.

Kilde: http://www.computerworld.com.au/article/261958/a-z_programming_languages...

  • 0
  • 0
Nikolaj Brinch Jørgensen

Sikke noget bavl.

Se her: http://rubyhoedown2007.confreaks.com/session09.html

Men det er nok forgæves... At skabe noget der er smukt forudsætter naturligvis det rigtige værktøj. Java sproget er ikke et værktøj hvormed man kan skabe specielt smukke løsninger.
Specielt på områderne proportion og clarity stinker Java, da man stort set altid er nødt til at blande det man egentlig prøver at beskrive der skal udføres med alt muligt boilerplate kode, der egentlig er fuldstændigt unødvendigt.

Java er forældet som sprog, og Sun har holdt udviklingen tilbage. Det er synd for det kunne være gået så godt. Til gengæld er platformen super stærk, og trives bedre end nogen sinde før. Tilmed er der nu en masse nye sprog til rådighed her.

C# er Microsoft derimod ikke så bange for at udvikle videre på.

  • 0
  • 0
Martin Glob

En rigtig WTF.. Nu er jeg ikke Java udvikler, men i første omgang burde compileren have fanget risikoen for at man kunne komme til at assigne en Boolean til en boolean - en warning ville være pænt i det mindste. Exception typen giver heller ikke en hint om hvad der er galt. At showYesNoCancelDialog() burde have returneret noget pænere kan jeg kun være enig i.

Men datatyper der kan antage en primitiv værdi eller null synes jeg nu er yderst fornuftige - forudsat at det er implementeret på en fornuftig måde og ikke umiddelbart kan blandes med den grundliggende primitive type.

C#'s nullables er et glimrende eksempel på hvordan det kan gøres elegant.

Det kræver lidt omtanke.. Men det forventes vel også af udviklere....

  • 0
  • 0
Michael Mortensen

Tak for citatet :-)

Jeg mener stadig reference typer bør være null. I fht. value types, så kan du sætte disse til nullable, men som en anden skriver, med omtanke.

Det jeg læser du efterspørger er vel en kontrakt på metode/egenskab niveau, så eks. en retur værdi ALDRIG kan være null - altså, du forventer ALTID at få en værdi du kan benytte videre?

Læs evt. denne lidt ældre artikel omkring de nye Code Contracts som er at finde fra .Net 4; http://bit.ly/9ESrWI. Der er også et par gode artikler i MSDN Magazine som også kan findes online.

At udviklere generelt (jeg selv inklusive) fra tid til anden får en NullReferenceException er jeg faktisk svært glad for - det betyder at der er nogle tilstande i applikationen jeg ikke har taget højde for, som så igen gør mig bedre til mit hverv.

  • 0
  • 0
Jesper Udby

;
; log2: calcuate r0 = approx 16*log2(r1:r0). wi, r1 destroyed
;
log2:
movlw 16
movwf wi
log2_loop:
bcf STATUS,C
rlf r0,f
rlf r1,f ; C affected
decfsz wi,f ; Z affected
btfsc STATUS,C
goto log2_done
goto log2_loop
log2_done:
movlw 0xf0
andwf r1,w
iorwf wi,w
movwf r0
swapf r0,f
return

  • 0
  • 0
Nikolaj Brinch Jørgensen

Men datatyper der kan antage en primitiv værdi eller null synes jeg nu er yderst fornuftige - forudsat at det er implementeret på en fornuftig måde og ikke umiddelbart kan blandes med den grundliggende primitive type.

Hvorfor da det? De primitive typer kan fuldstændigt fjernes fra sproget uden problemer, sammen med faren for at lave den type fejl.

  • 0
  • 0
Michael Rasmussen

De primitive typer kan fuldstændigt fjernes fra sproget uden problemer

Du skriver ikke ofte kode, der skal håndtere beregningstunge algoritmer, vil jeg antage, for i så fald ville du have erfaret, at det er forbundet med en væsentlig forringelse i performance at erstatte alle primitive typer med deres ditto Object wrapper.

Et andet aspekt: Hvordan ville du linke til f.eks. C-biblioteker uden sproget havde primitive datatyper?

  • 0
  • 0
Martin Glob

@Nikolaj

Man har tit brug for at have et felt (db/kode what ever) der enten har en værdi - eller ikke. Tag f.eks. noget som Dødsdato. Er der en værdi er personen død - og er feltet null er personen ikke død. Bevares, det kan implementeres på mange måder, men nullable typen er perfekt til et sådan formål.

I C# vil det være en Nullable<DateTime> doedsdato;

Og i C# må du ikke assigne en Nullable<DateTime> til en alm. DateTime. C# hjælper dig her, men du kan stadig dumme dig hvis du ikke checker for null værdier først.

  • 0
  • 0
Jesper Udby

Smuk kode er:

Når man kan skrive det hele i få linier; helst én, kommentarer er overflødige, koden er jo selvdokumenterende. Ligesom regular expressions og Perl. Mums!

Når koden er let at vedligeholde. Duh??

Når koden er skrevet i System/390 assembler og der bruges så få MIPS som overhovedet muligt.

Når koden kan skrives i et gratis værktøj og kan afvikles "gratis" på næsten en hvilken som helst platform. Fx. BASIC? Perl?? Rexx???

Når koden er lyserød i din favorit-editor (bruger du også VIm?).

SQL, det er lækkert, kun overgået af XSLT; især når databasen er MySQL.

Når koden er skrevet i xxx#. En Microsoft variant af xxx. Til gengæld kan man kalde WinYyy API direkte og lave indlejret assembler og alt muligt lækkert i det kommende M$WTF-API... Og, kære venner, vi er jo alligevel altid på en Windows platform.

Når man kan få forretningsfolk til at udtrykke deres inderste våde drømme i et sprog naturligt for dem. Mmmmm!! (Mercedes, Bonus, Matrix-organisation, Vertikaler, Outsourcing, BRIC, CRM, ERP, SOA, TCS/CSC/IBM/Accenture... SOA!!!).

Gåvææææækk! Der findes det her nye smarte xxx sprog! Man kan faktisk modellere hele universet og lidt til i én variabel og man behøver slet ikke typer eller åndssvage fejl. Fortolkeren gennemskuer selv når programmøren er under middel og retter fejl "on-the-fly". søg efter "adaptive programming just-in-time-fixer"... Det performer for lækkert, især med mange tråde og databaser. Min datter i børnehaven kan kode i dette sprog! DET bliver det næste store efter ML, især fordi man matematisk kan bevise det virker, ALTID!!

Neeeej nej nej, Misforstået!!! Det skal bare være SOA og BPEL og ESB og "global enterprise model" (så kan vi rumme hele verden, nemlig, og slå vores konkurrenter - Hurra!) og en masse Indere/Kinesere/Srilankanere/... - DET er smukt! Ikke noget konkret kode, men en masse projektledere og specifikationer og møder og modeller (ikke dem med store kasser) og CMMI og ITIL og PRINCE og planer og ting og kæmpe-budgetter.

  • 0
  • 0
Jesper Udby

; >>>> ALL interrupts goes here <<<<
INT org 4
; Save W and STATUS
movwf W_TEMP ; Store W in W_TMEP
swapf STATUS,w ; Store (and swap) STATUS in W
movwf S_TEMP ; Store W (swapped STATUS) in S_TEMP
; Switch to bank #0
movlw 0x1f
andwf STATUS,f
;
; FIGURE OUT WHAT INTERRUPT WE ARE TALKING ABOUT
;
btfss PIR1,TMR1IF
goto spu_int
...etc...

  • 0
  • 0
Nikolaj Brinch Jørgensen

Du skriver ikke ofte kode, der skal håndtere beregningstunge algoritmer, vil jeg antage, for i så fald ville du have erfaret, at det er forbundet med en væsentlig forringelse i performance at erstatte alle primitive typer med deres ditto Object wrapper.

Øhh, hvordan tror du Smalltalk klarer den? Altså fordi et tal er repræsenteret ved et objekt (som er en abstraktion) i din kode, kan den jo sagtens mappes direkte til et BYTE, WORDS, DWORD, QWORD osv. det er der ingen problemer (eller performance flaskehalse) i, det er jo derfor vi har en compiler.
Så hvis du igne læser det jeg skriver, så handler det ikke om at have Object wrappers i Java, blot at fjerne primitive type, således at tal også er objekter: 5.plus(5)

Et andet aspekt: Hvordan ville du linke til f.eks. C-biblioteker uden sproget havde primitive datatyper?

Nøjagtigt som idag, vha. JNI. Det ændrer intet.

  • 0
  • 0
Nikolaj Brinch Jørgensen

Man har tit brug for at have et felt (db/kode what ever) der enten har en værdi - eller ikke. Tag f.eks. noget som Dødsdato. Er der en værdi er personen død - og er feltet null er personen ikke død. Bevares, det kan implementeres på mange måder.

Enig, jeg tror heller ikke jeg sagde at det var en dårlig idé. Der er et begreb som hedder missing value (f.eks. implementeret i SAS), her kan en værdi være missing (null) på 32 forskellige måder (og du kan som udvikler selv styre det).

Den dårige idé er at lave unødvendige ting i et programmeringssprog, som gør at folk kan lave fejl. Når det havde været muligt at udelade det fra sproget til at begynde med.

  • 0
  • 0
Nikolaj Brinch Jørgensen

Når man kan skrive det hele i få linier; helst én, kommentarer er overflødige, koden er jo selvdokumenterende. Ligesom regular expressions og Perl. Mums!

Når koden er let at vedligeholde. Duh??

Når koden er skrevet i System/390 assembler og der bruges så få MIPS som overhovedet muligt.

Når koden kan skrives i et gratis værktøj og kan afvikles "gratis" på næsten en hvilken som helst platform. Fx. BASIC? Perl?? Rexx???

Når koden er lyserød i din favorit-editor (bruger du også VIm?).

SQL, det er lækkert, kun overgået af XSLT; især når databasen er MySQL.

Har du stadig ikke set Marcel Molina?

Når koden er skrevet i xxx#. En Microsoft variant af xxx. Til gengæld kan man kalde WinYyy API direkte og lave indlejret assembler og alt muligt lækkert i det kommende M$WTF-API... Og, kære venner, vi er jo alligevel altid på en Windows platform.

Nej plastic knækker.

Når man kan få forretningsfolk til at udtrykke deres inderste våde drømme i et sprog naturligt for dem. Mmmmm!! (Mercedes, Bonus, Matrix-organisation, Vertikaler, Outsourcing, BRIC, CRM, ERP, SOA, TCS/CSC/IBM/Accenture... SOA!!!).

Gåvææææækk! Der findes det her nye smarte xxx sprog! Man kan faktisk modellere hele universet og lidt til i én variabel og man behøver slet ikke typer eller åndssvage fejl. Fortolkeren gennemskuer selv når programmøren er under middel og retter fejl "on-the-fly". søg efter "adaptive programming just-in-time-fixer"... Det performer for lækkert, især med mange tråde og databaser. Min datter i børnehaven kan kode i dette sprog! DET bliver det næste store efter ML, især fordi man matematisk kan bevise det virker, ALTID!!

Neeeej nej nej, Misforstået!!! Det skal bare være SOA og BPEL og ESB og "global enterprise model" (så kan vi rumme hele verden, nemlig, og slå vores konkurrenter - Hurra!) og en masse Indere/Kinesere/Srilankanere/... - DET er smukt! Ikke noget konkret kode, men en masse projektledere og specifikationer og møder og modeller (ikke dem med store kasser) og CMMI og ITIL og PRINCE og planer og ting og kæmpe-budgetter.

Den der meget tunge sten du bor under, hvor ligger den?

  • 0
  • 0
Jesper Udby

Nej, desværre, jeg har ikke set/mødt Molina.

Jeg hører til de der irriterende typer der ikke kan lade være med at blande sig i lokalpolitik og bestyrelserne i børnenes daginstitutioner og den slags - forsøge at undgå at en økonomisk trængt kommune "smadrer" vores børns fritidstilbud med nedskæringer - så min fritid er begrænset til at drille lidt på nettet :-)

Og i min hverdag som selvstændig I/T-konsulent er metoder, sprog, frameworks (for satan da) og værktøjer som regel dikteret af kunden, som ofte er et par generationer bagud :-)

  • 0
  • 0
Baldur Norddahl

Man har tit brug for at have et felt (db/kode what ever) der enten har en værdi - eller ikke. Tag f.eks. noget som Dødsdato. Er der en værdi er personen død - og er feltet null er personen ikke død. Bevares, det kan implementeres på mange måder, men nullable typen er perfekt til et sådan formål.

Mange tror at NULL i SQL betyder "ingen værdi". Men det betyder "ukendt værdi". Hvilket betyder at NULL!=NULL. Det er derfor problematisk når folk vælger at bruge NULL i betydningen "ikke død endnu". Det betyder kun "vi ved ikke hvornår denne person eventuelt er død".

I computersprog bestemmer man sådanset selv hvad null betyder. Men det er slet ikke nødvendigt og giver mulighed for fejl. Dødsdato kunne f.eks. være en abstrakt type med to nedarvninger: død og levende. Modsat brugen af null, medfører denne metode at oversætterens typecheck hjælper med at verificere programmets korrekthed.

Mange sprog gør det meget nemt. For eksempel SML:

datatype deaddate = ALIVE | DIED of date

  • 0
  • 0
Nikolaj Brinch Jørgensen

Jeg hører til de der irriterende typer der ikke kan lade være med at blande sig i lokalpolitik og bestyrelserne i børnenes daginstitutioner og den slags - forsøge at undgå at en økonomisk trængt kommune "smadrer" vores børns fritidstilbud med nedskæringer - så min fritid er begrænset til at drille lidt på nettet :-)

Ja den båd sejler jeg også i (Carl Nielsens vuggestue Kbh. Ø).

Og i min hverdag som selvstændig I/T-konsulent er metoder, sprog, frameworks (for satan da) og værktøjer som regel dikteret af kunden, som ofte er et par generationer bagud :-)

Ditto! Men derfor kan man jo godt hjælpe dem fremad, så de kan spare nogle penge og få et kompetenceløft.

  • 0
  • 0
Torben Mogensen Blogger

Jeg mener stadig reference typer bør være null.

Hvorfor egentlig? Der er masser af eksempler, hvor man gerne vil have referencer, men hvor en nulreference ikke giver mening. At man bliver påtvunget denne værdi, selv når den er meningsløs, har ingen fordele, men seriøse ulemper:

  • Det er en kilde til fejl.
  • Det gør dine programmer mindre læselige, da en læser ikke kan se, om du har tænkt dig at bruge nulreferencer til noget.
  • Det hindrer optimering, da oversætteren bliver nødt til at tage højde for muligheden af nulreferencer.

Det er ikke meget anderledes end, hvis sproget insisterede på, at 42 er en mulig værdi i alle typer.

  • 0
  • 0
Nikolaj Brinch Jørgensen

Hvorfor egentlig? Der er masser af eksempler, hvor man gerne vil have referencer, men hvor en nulreference ikke giver mening. At man bliver påtvunget denne værdi, selv når den er meningsløs, har ingen fordele, men seriøse ulemper:

  • Det er en kilde til fejl.
  • Det gør dine programmer mindre læselige, da en læser ikke kan se, om du har tænkt dig at bruge nulreferencer til noget.
  • Det hindrer optimering, da oversætteren bliver nødt til at tage højde for muligheden af nulreferencer.

Det er ikke meget anderledes end, hvis sproget insisterede på, at 42 er en mulig værdi i alle typer.

Nemlig! Godt sagt Torben!

  • 0
  • 0
Michael Mortensen

Hvorfor egentlig? Der er masser af eksempler, hvor man gerne vil have referencer, men hvor en nulreference ikke giver mening. At man bliver påtvunget denne værdi, selv når den er meningsløs, har ingen fordele, men seriøse ulemper:

  • Det er en kilde til fejl.
  • Det gør dine programmer mindre læselige, da en læser ikke kan se, om du har tænkt dig at bruge nulreferencer til noget.
  • Det hindrer optimering, da oversætteren bliver nødt til at tage højde for muligheden af nulreferencer.

Hvis du eks. bestræber dig på, at følge de fornuftige retningslinier som findes i Framework Design Guidelines (http://bit.ly/9rAJxH), så er det min opfattelse, at dit punkt 2 udebliver.

Jeg er enig i, at det er en kilde til fejl, men der er jeg af en lidt anden opfattelse end dig; idet jeg tidl. har skrevet det hjælper mig til at højne kvaliteten af applikationen (tjekke for nulls, smide en ArgumentNulLException etc). Kort opsummeret trot jeg fejlniveauet vil være uændret i fht. din indvending mod NULL - det vil bare være andre fejl, som måske er svære at finde?

Omkring optimering, så er vi nede på et niveau hvor jeg har tillid til .NET IL, og den pris der er associerede med et NULL tjek er antagelsesvis forsvindende lille?

Din lille provokation omkring værdien 42 (hvis vi ser bort fra Hitchhikers guide to the galaxy) mener jeg ikke kan sammenlignes med NULL, idet det så rent faktisk kan være en reelt værdi.

NULL fortæller mig, at typen (sandsynligvis) ikke er initialiseret endnu, og at jeg skal lave nogle tiltag for at gøre dette, samt kan give fordele i fht. lazy load m.m..

Hvis vi ikke havde NULL, så er min påstand, at vi ville få applikationer med ekstra stort hukommelsesforbrug samt værdier der måske, eller måske ikke, er gyldige.

  • 0
  • 0
Nikolaj Brinch Jørgensen

NULL fortæller mig, at typen (sandsynligvis) ikke er initialiseret endnu, og at jeg skal lave nogle tiltag for at gøre dette, samt kan give fordele i fht. lazy load m.m..

Som er en ekstra stor kilde til fejl.

Hvis vi ikke havde NULL, så er min påstand, at vi ville få applikationer med ekstra stort hukommelsesforbrug samt værdier der måske, eller måske ikke, er gyldige.

Det er min påstand så at vi ikke ville, og jeg kan godt tænke mig at se den påstand underbygget? Hvilke værdier er det vi gerne vil have skal være null, således at vi ikke bruger for meget hukommelse? Har vi ikke netop oprettet referencen fordi den skal have en værdi?
Og ikke fordi den ikke skal have en værdi

  • 0
  • 0
Michael Mortensen

NULL fortæller mig, at typen (sandsynligvis) ikke er initialiseret endnu, og at jeg skal lave nogle tiltag for at gøre dette, samt kan give fordele i fht. lazy load m.m..
Som er en ekstra stor kilde til fejl.

Hvis vi ikke havde NULL, så er min påstand, at vi ville få applikationer med ekstra stort hukommelsesforbrug samt værdier der måske, eller måske ikke, er gyldige.
Det er min påstand så at vi ikke ville, og jeg kan godt tænke mig at se den påstand underbygget? Hvilke værdier er det vi gerne vil have skal være null, således at vi ikke bruger for meget hukommelse? Har vi ikke netop oprettet referencen fordi den skal have en værdi?
Og ikke fordi den ikke skal have en værdi

Ehm, hvis vi tager udgangspunkt i original artiklen, så kan vi hurtig blive enige om, at Java koden nærmere sig det tåbelige.

I fht. eks. .NET (som er mit område), så har jeg svært ved at forstå dine påstande, muligvis fordi jeg ikke oplever det påstået.

I fht. managed code og GC, så vil objekter med en valid reference optage plads indtil det frigøres. Hvis jeg først benytter pladsen når jeg skal bruge den, så bruger jeg ikke unødigt hukommelse.

Det der mangler i denne diskussion er nok noget kontekst i fht. vores hver især oplevelser :-)

Lad os sige vi har en User, denne har muligvis en property navngivet Statistic. Dette kunne være en reference til UserStatistic, med x-antal metoder, properties m.m..

Der er vel som sådan ingen grund til at loade denne statistik unødigt, hvis jeg kun ønsker en liste over alle brugere i et system fra 2000-01-01 til og med 2010-01-01?

Uden at gå for meget i løsningsmode, så kunne ovenstående være et eksempel på en, set med mine øjne, fornuftig brug af null reference?

  • 0
  • 0
Michael Mortensen

Jeg vil mene, at en reference til f.eks. typen Unassigned er mere på sin plads.

Kan du uddybe denne?

Med Unassigned, mener du så du har en reference type navngivet Unassigned? Så hvis jeg ønsker at returnere UserStatistic, så kan denne både være Unassigned samt UserStatistic?

Eller?

  • 0
  • 0
Nikolaj Brinch Jørgensen

Jeg mener at getUserStatistic kan returnere UserStatistic eller f.eks. Unassigned (se evt. Scala: None, Some osv.).

Jeg ønsker lige at tilføkje lidt mere spot til Java: Det er et usandsynligt verbose sprog - f.eks. udnerstøtter det ikke properties, som (C#, Groovy osv.) Så man skal skrive explicitte getters/setters!!! Som så skal refaktoreres når man vil omdøbe dem. Det er super håbløst og spild af tid.

Programmering skal være at udtrykke hvad man gerne vil have udført - præcist.
Man skal ikke udtrykke hverken mere (Java) eller mindre (Perl - writeonly language) end at det fremgår tydeligt, hvad det er koden gør.
At skulle skrive alt mulig boiletrplate og plumbing er spild af tid, og har ingen værdi overhovedet, hverken for programmør eller kunde - tværtimod, så har den kæmpestor negativ værdi.

  • 0
  • 0
Baldur Norddahl

Uden at gå for meget i løsningsmode, så kunne ovenstående være et eksempel på en, set med mine øjne, fornuftig brug af null reference?

Det er en klassisk "option" type. Option er en abstrakt klasse med to nedarvninger: Some og None. Some indeholder en reference til din faktiske datatype.

Feltet "Statistic" kan herefter indeholde for eksempel Some(2000-01-02) eller den kan indeholde None.

Option kommer ofte med smarte funktioner som beskytter mod null-pointer fejltyper. For eksempel er der ofte en metode i stil med getOrElse(defaultValue) som returnere den indre værdi hvis der er tale om en Some og defaultValue hvis der er tale om en None.

  • 0
  • 0
Michael Mortensen

Jeg mener at getUserStatistic kan returnere UserStatistic eller f.eks. Unassigned (se evt. Scala: None, Some osv.).

Jeg ønsker lige at tilføkje lidt mere spot til Java: Det er et usandsynligt verbose sprog - f.eks. udnerstøtter det ikke properties, som (C#, Groovy osv.) Så man skal skrive explicitte getters/setters!!! Som så skal refaktoreres når man vil omdøbe dem. Det er super håbløst og spild af tid.

Programmering skal være at udtrykke hvad man gerne vil have udført - præcist.
Man skal ikke udtrykke hverken mere (Java) eller mindre (Perl - writeonly language) end at det fremgår tydeligt, hvad det er koden gør.
At skulle skrive alt mulig boiletrplate og plumbing er spild af tid, og har ingen værdi overhovedet, hverken for programmør eller kunde - tværtimod, så har den kæmpestor negativ værdi.

Jamen så er vi helt enige, og så må jeg præcisere, at mine udtalelser basere sig fra de trygge .NET rammer, og her står jeg umiddelbart ved mine udsagn. Det er så muligt, at vi ikke her kan nå til enighed, men det behøves sådan set heller ikke.

I det angivet eksempel, der kunne du som programmør mod min User forvente en UserStatistic instance, hvis du valgte denne property. Her ville jeg forpligte mig til at give dig det du forventet - og IKKE en NULL reference. Under hjelmen ville jeg dog forholde mig til, at hvis den private variabel, _userStatistic, var null, så ville jeg initialisere den, og returnere det du forventer.

Såfremt der ikke var en fejl i min kode ;-)

  • 0
  • 0
Michael Mortensen

Det er en klassisk "option" type. Option er en abstrakt klasse med to nedarvninger: Some og None. Some indeholder en reference til din faktiske datatype.

Feltet "Statistic" kan herefter indeholde for eksempel Some(2000-01-02) eller den kan indeholde None.

Option kommer ofte med smarte funktioner som beskytter mod null-pointer fejltyper. For eksempel er der ofte en metode i stil med getOrElse(defaultValue) som returnere den indre værdi hvis der er tale om en Some og defaultValue hvis der er tale om en None.

Se det giver rigtig god mening, og det kunne sagtens være en pattern man kunne vælge at indføre i eks. sine .NET projekter. Umiddelbart i fht. .NET, så er jeg dog ikke sikker på jeg ville benytte denne pattern med henblik på min tidl. reference til Framework Design Guidelines.

Min tilgang til kodning er, at det skal være nemt og intuitivt at benytte for mine med-programmøre.

Fandt dog din foklaring nem og forståelig, og såfremt nogle har interesse i eks. Scala, så er her en beskrivelse af "The Option Pattern": http://bit.ly/ce1WrW.

  • 0
  • 0
Jonas Høgh

Det der var min pointe for snart mange indlæg siden var netop, at det i .Net fx ofte er bedre at bruge Null Object : http://en.wikipedia.org/wiki/Null_Object_pattern, dvs et tomt objekt der "ingenting" gør når man udfører operationer på det, i stedet for null, som bare springer i luften.

I og med at .Net kræver, at en reference type kan være null, kan du ved brug af Null Object stadig ikke gardere dig imod, at en bruger af din klasse vælger at sende en reference til "almindeligt" null videre, og dermed skabe problemer.

  • 0
  • 0
Michael Mortensen

Det der var min pointe for snart mange indlæg siden var netop, at det i .Net fx ofte er bedre at bruge Null Object : http://en.wikipedia.org/wiki/Null_O..., dvs et tomt objekt der "ingenting" gør når man udfører operationer på det, i stedet for null, som bare springer i luften.

I og med at .Net kræver, at en reference type kan være null, kan du ved brug af Null Object stadig ikke gardere dig imod, at en bruger af din klasse vælger at sende en reference til "almindeligt" null videre, og dermed skabe problemer.

Denne "Null Object Pattern" er interessant og kunne godt overvejes ind i forb. med Unit testing. Dog fastholder jeg min nevøsitet i fht. det der også understreges ved punktet Critics: "This pattern should be used carefully as it can make errors/bugs appear as normal program execution.".

Og dette understreger meget præcist min modstand for det fremhævet i denne diskussion.

  • 0
  • 0
Torben Mogensen Blogger

Det der var min pointe for snart mange indlæg siden var netop, at det i .Net fx ofte er bedre at bruge Null Object, dvs et tomt objekt der "ingenting" gør når man udfører operationer på det, i stedet for null, som bare springer i luften.

Interessant koncept. Man kunne lave en Null Object type, der er en subtype af alle typer, modsat Object, der er en supertype af alle typer.

Dog skal man tage højde for klasser, der er erklæret final, da de ikke kan have subtyper. Men at sige, at final klasser ikke kan have Null Objects, er måske egentligt også det rigtige, semantisk set. Så kan man udelukke Null Object fra en type ved at erklære den final.

  • 0
  • 0
Baldur Norddahl

Interessant koncept. Man kunne lave en Null Object type, der er en subtype af alle typer, modsat Object, der er en supertype af alle typer.

Scala har en Null type som er en subtype af alle referencetyper og en Nothing type som er en subtype af Null samt alle ikke-referencetyper (tal).

Det bliver blandt andet brug i definitionen af Option typen. Således er None[Nothing] en fællestype for alle mulige konkrete Option typer.

var x: Option[Int] = None[Nothing] (*)

fordi None[Nothing] er en subtype af Option[Int].

Java mangler denne Nothing type, og derfor kan man ikke have en fælles None for alle Option typer i java.

(*) praktisk skal man kun skrive None da None extender Option[Nothing].

  • 0
  • 0
Jonas Høgh

Well, ideen med Null Object er hverken test stubs eller en global subtype, men et konkret forretningsmæssigt behov for at indføre et specialtilfælde, hvor noget er tomt. I stedet for at lave magisk opførsel med if-sætninger og null, redelegeres implementationen til null-objektet.

Et eksempel kunne være et hotel-reservations-system, hvor vi ikke altid kender kundens navn, da reservationen kan være lagt gennem et rejsebureau, der endnu ikke har oplyst navnet. Her kunne vi lade kunde-null-objektets properties for navn, adresse, osv. returnere "Ukendt" i stedet for at bøvle med det i alle de klasser, der skal præsentere kundeobjekter.

Men det er naturligvis ikke ufarligt, hvis man ikke bruger det med omtanke. Det er trods alt bedre at udvikleren finder en NullReferenceException i fejlloggen, end at miste en masse penge fordi fakturaer aldrig er nået frem, da de er blevet postet med "ukendt ukendt ukendt" på kuverten :-)

  • 0
  • 0
Jesper Udby

Nu kan akademiske diskussioner om hvorvidt reference-typer kan indeholde null eller andre spændende "ikke-værdier" (42 er sjovt) være ganske interessant - uanset hvad bør man vel få en hård fejl når man forsøger at dereferere dem?
Men skal vi ikke prøve at holde os til at Den Blonde har udstillet en ganske relevant problemstilling i JAVA?

Jeg synes spørgsmålet er interessant og svaret også - en "gammel rotte" lærte da noget nyt dér.

Det ændrer dog ikke ved det faktum at udviklerne af DialogUtil tilsyneladende har valgt en uheldig implementation af showYesNo[Cancel]Dialog() metoderne.

Jeg er enig i at JAVA's autoboxing feature her viser sit grimmeste ansigt, men det er dog stadig implementationen der stinker. Mod elendige udviklere kæmper guderne stadig forgæves...

Man kan kritisere JAVA for meget og jeg vil da i den anledning anbefale én af 3 løsninger:

1) lade være med at kode JAVA.
2) forsøge at ændre sproget...
3) lære sproget at kende og vide hvor dets muligheder og begrænsninger er (Bruce Tate er vistnok med os endnu, trods alt).

Hvis man arbejder som konsulent med JAVA som et af sine primære fokusområder vil jeg anbefale at man holder sig til 3) med 2) som noget man kan overveje hvis man arbejder i en stor (nok) organisation ;-)

  • 0
  • 0
Jesper Udby

Et eksempel kunne være et hotel-reservations-system, hvor vi ikke altid kender kundens navn, da reservationen kan være lagt gennem et rejsebureau, der endnu ikke har oplyst navnet. Her kunne vi lade kunde-null-objektets properties for navn, adresse, osv. returnere "Ukendt" i stedet for at bøvle med det i alle de klasser, der skal præsentere kundeobjekter.

NPE's i loggen tyder på dårligt arbejde, manglende Unit-tests eller begge dele.

Ovenstående løsning vil jeg gerne advare imod. Tænk hvis man pludselig havde 1000 kunder med "ukendt ukendt, ukendt ukendt, Ukendt" fordi en service i systemet pludselig ikke svarer fornuftigt længere...

  • 0
  • 0
Nikolaj Brinch Jørgensen

Kære Jesper,

Man kan kritisere JAVA for meget og jeg vil da i den anledning anbefale én af 3 løsninger:

1) lade være med at kode JAVA.
2) forsøge at ændre sproget...
3) lære sproget at kende og vide hvor dets muligheder og begrænsninger er (Bruce Tate er vistnok med os endnu, trods alt).

Hvis man arbejder som konsulent med JAVA som et af sine primære fokusområder vil jeg anbefale at man holder sig til 3) med 2) som noget man kan overveje hvis man arbejder i en stor (nok) organisation ;-)

Nu arbejder jeg også som konsulent med Java og mine anbefalinger er bestemt ikke lig dine. Min pointe er at Groovy altså også er Java, det er i mine øjne vældig meget mere fremtidsorienteret at vælge at kode videre i f.eks. Groovy.
Sproget (om er under JCP) er da netop den forbedring af Java som mange efterspørg.
At blive ved med at kode i sproget Java er jeg bestemt ikke enig i er en god ting.

Husk 7 gode vaner - og slib saven! :-)

PS: Bruce er da Ruby guy nu!

  • 0
  • 0
Nikolaj Brinch Jørgensen

Scala er bestemt også en mulighed.

Her anvendes bla. Option, Some, None i stedet for null

  • mange andre smarte ting.

Helt enig (sidder faktisk og koder Scala lige nu), men der er væsentlig forskel, i og med at Groovy er Java (+ en hel masse smartness - og desværre performance penalty pga. dynamisiteten og den afledte dispatching der finder sted - hvor der ikke endnu er JVM support for).
Hvor Scala ikke er det (så kan vi roligt blive enige om at Scala er lækkert - men det er underordnet).
Desuden er Scala ikke dynamisk, men har super god performance - i forhold til Groovy. Dog forbedres det hele tiden.

  • 0
  • 0
Jens Madsen

En boolean datatype kan udtrykke om et givent udsagn er true eller false. En Boolean kan så også repræsentere at man ikke har taget stilling endnu.

Er det ikke et dårligt valg, at bruge samme ord - og kun forskel på stort/småt? Umiddelbart virker det som et hurtigt valg, hvis man ikke lige kan finde på hvad man skal kalde det. Så bruges samme ord, og det gøres så med småt. Det virker ikke som velovervejet. Det må være muligt, at finde noget mere sigende, der illustrerer forskellen i de to booleans.

På mig virker det lidt "C" agtigt.

  • 0
  • 0
Jonas Høgh

NPE's i loggen tyder på dårligt arbejde, manglende Unit-tests eller begge dele.

Øh, ja - har jeg sagt andet?

Ovenstående løsning vil jeg gerne advare imod. Tænk hvis man pludselig havde 1000 kunder med "ukendt ukendt, ukendt ukendt, Ukendt" fordi en service i systemet pludselig ikke svarer fornuftigt længere...

Jeg skrev jo netop at man ikke skal bruge Null Object hvis der er fare for at det fejler "stille" uden man opdager det.

Men nu var målet ikke at gå ind i de finere detaljer i hvordan det implementeres, blot at give et eksempel på hvornår det kunne være rart at kunne erklære en type ikke-nullable i .Net eller Java.

  • 0
  • 0
Torben Mogensen Blogger

Er det ikke et dårligt valg at bruge samme ord - og kun forskel på stort/småt? [...] Det må være muligt at finde noget mere sigende, der illustrerer forskellen i de to booleans.

Jo, det havde været bedre med "NullableBool" eller "boolean?" (som indikerer, at det måske er en boolean og måske null).

Men et større problem er, at ?: operatoren vælger at returnere en boolean, hvis den ene gren er boolean og den anden Boolean. Det ville da være mere naturligt enten at give en typefejl eller at udvide til den type, der kan indeholde alle de mulige resultater, i stedet for at lave en exception, hvis den ene gren returnerer null.

  • 0
  • 0
NA NA

Jeg ønsker lige at tilføkje lidt mere spot til Java: Det er et usandsynligt verbose sprog - f.eks. udnerstøtter det ikke properties, som (C#, Groovy osv.) Så man skal skrive explicitte getters/setters!!!

Du er klar over at basal viden om objektorienteret design siger at getters og setters bør undgås så meget som muligt ?

Se her http://www.javaworld.com/javaworld/jw-09-2003/jw-0905-toolbox.html
"A fundamental precept of OO systems is that an object should not expose any of its implementation details. This way, you can change the implementation without changing the code that uses the object. It follows then that in OO systems you should avoid getter and setter functions since they mostly provide access to implementation details."

Hvad skal man med syntaktisk sukker for noget man bør undgå ?

Jeg har set en del C# kode i min tid og det meste af det ringeste af slagsen er præget af kode der gør sådan her:

compute_something(SomeObject object)
{
int a = object.anthorObject.LetMeJustGetThis.OkThisOneHasWhatINeed.There.valueB + object.anotherObject.LetMeSeeHere.OhHereIsSomething.YesSir.valueC;
}

  • 0
  • 0
Jesper Udby

Øh, ja - har jeg sagt andet?

Du skal læse indenad... Hvis dit system er designet til at kunne håndtere at kunden til en reservation ikke er kendt, så bør den situation i sagens natur aldrig give anledning til NPE's i loggen...

NPE's i loggen (som bør overvåges) betyder at noget er galt. Det er bedre at man opdager det tidligt, fremfor når breve/mails kommer retur fra "ukendt adresse".

Jeg forstår ikke helt denne frygt for "null referencer". I C/C++ og lign. kan det være alvorligt at dereferere en "syg" pointer/reference (også hvis den ikke nødvendigvis er null; fx. 42 :-D).

I Java får man en NPE. Det er jo så fordi der er fejl i koden. Fejl bør opdages så tidligt som muligt, helst af kompileren, men ellers ASAP på runtime.
Forkerte og dårlige implementationer bliver sguda ikke bedre af at man ikke kan få en NPE når man forsøger at tilgå "noget forkert".

NPE's (og enhver anden Exception for den sags skyld) i loggen på et system der virker "efter hensigten" er tegn på at man ikke er færdig med sin implementation...

  • 0
  • 0
Jonas Høgh

NPE's i loggen (som bør overvåges) betyder at noget er galt. Det er bedre at man opdager det tidligt, fremfor når breve/mails kommer retur fra "ukendt adresse".

Det er jo netop det jeg skriver...

Forkerte og dårlige implementationer bliver sguda ikke bedre af at man ikke kan få en NPE når man forsøger at tilgå "noget forkert".

Jeg siger ikke at andre fejl er mindre alvorlige end NPE. Jeg siger at den korrekte implementation kan være nemmere at realisere hvis man bruger et pattern som Null Object (med omtanke), og at den korrekte kode bliver væsentligt mere læsbar og nemmere at vedligeholde, da den indeholder mindre "if (foo != null)" boilerplate.

  • 0
  • 0
Torben Mogensen Blogger

Jeg forstår ikke helt denne frygt for "null referencer". I C/C++ og lign. kan det være alvorligt at dereferere en "syg" pointer/reference (også hvis den ikke nødvendigvis er null; fx. 42 :-D).

I Java og de fleste moderne objektorienterede sprog, er der ikke pointeraritmetik og andet rod, så de eneste "syge" pointere er nulreferencer. Men du har ret i, at [i]alle[/i] syge referencer bør undgås.

Det er ret svært i sprog som C og C++, men i Java-lignende sprog (hvor nulreferencer er de eneste syge referencer) er det ikke så svært: Gør i typen forskel på, om der er nulreferencer eller ej, og tving et nulcheck før dereference af referencer, der ifølge typen kan være nul. Ditto når en reference med nulmulighed kopieres ind i en variabel, hvis type ikke tillader nulreferencer. Biblioteksfunktioner osv. bør laves, så de ikke tillader nulreferencer i argumenter, med mindre dette faktisk giver mening, og deres returtyper bør også så vidt muligt være nulfri.

Sprog som SML klarer sig fint uden nulreferencer overhovedet: Alle variable (inklusive referencevariable) bliver initialiseret ved erklæring, og alle tildelinger er typesikre, så alle referencer vil pege på en lovlig værdi. Som Baldur sagde, bruger man i stedet en option type, hvis man vil have en værdi, der muligvis er udefineret.

  • 0
  • 0
Log ind eller Opret konto for at kommentere