[Java] Method die string terug geeft - Null of empty string?

Pagina: 1
Acties:

Onderwerpen

Vraag


Acties:
  • 0 Henk 'm!

  • Tanuki
  • Registratie: Januari 2005
  • Niet online
(jarig!)
Dit is meer een conceptuele vraag: Indien een method een string terug geeft, zou dan een default value null beter zijn dan een default value "empty string"?

We hebben hier op kantoor een discussie waarbij er eigenlijk 3 kampen zijn:
• Null als default value
• Empty string als default value
• Optional<String> als return value

Ik ben zelf van mening dat null betekent "onbekend" of "niet aanwezig" en dus zou moeten dienen als default return value.

Wat use-cases, waar naar mijn mening het volgende van toepassing is:
• Street-class: List<House> getHouses() - Zou een lege list moeten teruggeven als er geen huizen in die straat staan (en dus niet null en al zeker geen Optional<List<House>>)
• House-class: String getNumberSuffix() - Zou een suffix terug moeten geven, of anders null (niet van toepassing)
...

Een van de argumenten om een lege string terug te geven is volgens een aantal ontwikkelaars dat er minder kansen op fouten bestaan. Ik moet dan meteen denken aan de gevallen waar er niet een string-object wordt teruggegeven, maar een ander concreet object. Ik ga ook niet een Street object instantieren waarbij ik dan geen enkele field assign, om zo te bepalen dat dit 'null' betekent.

Ik heb al wat discussies gevonden op sites als Stackoverflow, maar het lijkt erop dat er geen eenduidig antwoord is, en Stackoverflow is blijkbaar ook niet de website waar een dergelijke discussie moet plaatsvinden:
https://stackoverflow.com...een-null-and-empty-string
https://stackoverflow.com...ull-and-empty-java-string

Ikzelf vind dit wel een leuke manier om empty string vs null te omschrijven:
Afbeeldingslocatie: https://i.stack.imgur.com/j9vg8.jpg
Maar dat geeft eigenlijk nog steeds niet een richtlijn om de return value van een method te bepalen in alle gevallen.

[ Voor 40% gewijzigd door Tanuki op 18-04-2018 15:57 ]

PV: Growatt MOD5000TL3-XH + 5720wp, WPB: Atlantic Explorer v4 270LC, L/L: MHI SCM 125ZM-S + SRK 50ZS-W + 2x SRK 25ZS-W + SRK 20ZS-W Modbus kWh meter nodig?

Alle reacties


Acties:
  • 0 Henk 'm!

  • Standeman
  • Registratie: November 2000
  • Laatst online: 18:04

Standeman

Prutser 1e klasse

Aangezien een lege string prima iets anders kan beteken dan null, zou ik voor null gaan als er inderdaad geen waarde bekend is.

Optional is natuurlijk ook mogelijk, maar ik vind de waarde van de hele Optional class sowieso minimaal. :p

The ships hung in the sky in much the same way that bricks don’t.


Acties:
  • +1 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Null als de waarde onbekend is, String.Empty als je wéét dat er geen value is (dus in je NumberSuffix voorbeeld: Null = geen idee of er een suffix is, String.Empty = Er is geen suffix).

Inderdaad zoals je pleerol foto :P

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

  • Tanuki
  • Registratie: Januari 2005
  • Niet online
(jarig!)
RobIII schreef op woensdag 18 april 2018 @ 16:02:
Null als de waarde onbekend is, String.Empty als je wéét dat er geen value is (dus in je NumberSuffix voorbeeld: Null = geen idee of er een suffix is, String.Empty = Er is geen suffix).

Inderdaad zoals je pleerol foto :P
Dus om een functie als getFullName() te maken zou ik ipv deze code:
code:
1
return firstName + (null == infix ? new String() : new String(" ") + infix) + lastName;

code als deze moeten maken:
code:
1
return firstName + (new String().equals(infix) ? new String() : new String(" ") + infix) + lastName;

en dan ook moeten beseffen dat ik dat op die manier zou moeten doen?

En ik zou dan eigenlijk beide gevallen moeten afvangen:
code:
1
return firstName + (null == infix || new String().equals(infix) ? new String() : new String(" ") + infix) + lastName;

(expres new String() gebruikt ipv "")

Ik zou liever eenduidig de garantie hebben dat null betekent "is er niet" en dat iets anders dan null betekent "er is een waarde". Of denk ik dan te kort door de bocht?

En als ik dit vergelijk met objecten klinkt het mij ook vreemd om geen nulls te gebruiken, maar empty strings - Je instatieert ook niet zomaar een object met alle fields niet ingevuld en geeft dat terug aan je domein-code.

PV: Growatt MOD5000TL3-XH + 5720wp, WPB: Atlantic Explorer v4 270LC, L/L: MHI SCM 125ZM-S + SRK 50ZS-W + 2x SRK 25ZS-W + SRK 20ZS-W Modbus kWh meter nodig?


Acties:
  • 0 Henk 'm!

  • T.G
  • Registratie: Maart 2015
  • Laatst online: 01-07 11:18

T.G

In Go, is de zero value van een String "". Ik zou zelf ook kiezen voor "", omdat je zo null pointer exceptions voorkomt.

Acties:
  • +3 Henk 'm!

  • Standeman
  • Registratie: November 2000
  • Laatst online: 18:04

Standeman

Prutser 1e klasse

T.G schreef op woensdag 18 april 2018 @ 16:20:
In Go, is de zero value van een String "". Ik zou zelf ook kiezen voor "", omdat je zo null pointer exceptions voorkomt.
Waarom zou je null pointers willen voorkomen? Die geven juist aan dat er ergens een f*ck-up is gemaakt door een developer. Door empty strings te gebruiken verberg je die f*ck-up alleen maar en creëer je problemen die amper te debuggen zijn.

The ships hung in the sky in much the same way that bricks don’t.


Acties:
  • +2 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Tanuki schreef op woensdag 18 april 2018 @ 16:13:
[...]

Dus om een functie als getFullName() te maken zou ik ipv deze code:
code:
1
return firstName + (null == infix ? new String() : new String(" ") + infix) + lastName;

code als deze moeten maken:
code:
1
return firstName + (new String().equals(infix) ? new String() : new String(" ") + infix) + lastName;

en dan ook moeten beseffen dat ik dat op die manier zou moeten doen?
Geen idee wat je zou "moeten" doen; dat is namelijk afhankelijk van wat de eisen aan getFullName() zijn ;) Misschien moet 'ie wel klappen als de infix null is? En, then again, misschien wil je 't inderdaad beschouwen als "dan maar geen infix, hoppa, firstname + spatie + lastname en klaaaaaar".

Ik zou zoiets of zoiets doen...maar ik heb dan ook de luxe om met een fatsoenlijke taal te mogen werken :+ (grapje :* )

Sowieso mis je in allebei je voorbeelden een spatie voor lastname :+
Tanuki schreef op woensdag 18 april 2018 @ 16:13:
Ik zou liever eenduidig de garantie hebben dat null betekent "is er niet"
"Is er niet" betekent dat je wéét dat er geen infix (of whatever) is. Dat is gewoon een lege string, ofwel "" (String.Empty noemen we dat in .Net :+). Daarentegen: null is: "Geen idee, zou er kunnen zijn, zou er geen kunnen zijn, we hebben 't nog nooit gevraagd aan die klant".
Tanuki schreef op woensdag 18 april 2018 @ 16:13:
en dat iets anders dan null betekent "er is een waarde".
Een lege string is toch een waarde?
Tanuki schreef op woensdag 18 april 2018 @ 16:13:
En als ik dit vergelijk met objecten klinkt het mij ook vreemd om geen nulls te gebruiken, maar empty strings - Je instatieert ook niet zomaar een object met alle fields niet ingevuld en geeft dat terug aan je domein-code.
:? Waar komt dat vandaan? Ook hier weer:

code:
1
myRepository.getCustomer(12345);


Ik wil een (customerNotFound)Exception als de klant met ID 12345 niet bestaat of een klant terughebben. Als je hier null gaat returnen moet ik vervolgens overal gaan checken of een-of-andere method niet toevallig null heeft gereturned.

En dan hier:

code:
1
myRepository.listAllCustomers();


Hier verwacht ik: altijd een List<Customer> (ik kies nu even voor list, had net zo goed een IEnumerable<Customer> of whatever kunnen zijn); die kan leeg zijn (als in: 0 elementen bevatten), best, maar ook hier wordt er geen null gereturned.

Er zijn maar (relatief) weinig plekken waar je null returned. Doe je dat wel dan heb je door de rest van je code o-ve-frikkin'-al null-checks staan of vliegen de nullpointerexceptions je om te oren (of werk je met een taal als PHP of javascript waar null gelijk is aan een lege string of aan een banaan of 42 of een lege array en je nooit weet wat null nou precies in dat ene geval doet doet :+ )

[ Voor 53% gewijzigd door RobIII op 18-04-2018 17:48 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • +2 Henk 'm!

  • Mugwump
  • Registratie: Mei 2017
  • Laatst online: 20:32
Standeman schreef op woensdag 18 april 2018 @ 15:54:
Aangezien een lege string prima iets anders kan beteken dan null, zou ik voor null gaan als er inderdaad geen waarde bekend is.

Optional is natuurlijk ook mogelijk, maar ik vind de waarde van de hele Optional class sowieso minimaal. :p
Ik zou Optional niet van 'minimale waarde' noemen. Integendeel, het is juist een zeer waardevolle toevoeging.
Met Optional kun je expliciet aangeven dat de returnvalue van een methode er mogelijk niet is. Een aantal talen (b.v. C# of Kotlin) kennen 'nullable types'. Dergelijke types maken je ervan bewust dat een return value (of variabele) mogelijk niet kan bestaan en dat je expliciet wat moet doen met die situatie. Java kent dergelijke taalconstructies niet.

Als er zoals in de OP een class House met methode String getNumberSuffix() is, dan moet je weer expliciet gaan beschrijven in de javadoc wat de methode teruggeeft indien het adres geen huisnummertoevoeging heeft. Geef je een optional (of zoals in veel andere talen een nullable type) terug, dan weet je dat je dat je rekening moet houden met die situatie.

Dat wordt een nog veel prangendere kwestie als je niet gewoon een applicatie bouwt die je zelf deployed en waarvan verder de code niet zwaar wordt hergebruikt, maar dergelijk onverwachte / ongedocumenteerde nulls in veel gebruikte frameworks / libraries die ook nog eens als transitive dependencies in weer allerhande andere frameworks / libraries zitten leveren echt totale chaos op.

Afgezien van daarvan wordt het toch echt wel eens hoog tijd voor een elvis operator in Java. :P

Dus in mijn ogen moet de TS Optional<String> getNumberSuffix() gebruiken.
Bij een methode die een collection of array teruggeeft volstaat doorgaans een lege lijst wel gewoon.

"The question of whether a computer can think is no more interesting than the question of whether a submarine can swim" - Edsger Dijkstra


Acties:
  • 0 Henk 'm!

  • incaz
  • Registratie: Augustus 2012
  • Laatst online: 15-11-2022
Dit lijkt me typisch iets waarbij het belangrijk is hoe het gebruikt wordt. Als het enige wat je met de null gaat doen is afvangen om er alsnog een lege string van te maken, dan zou ik die moeite niet doen en gewoon lekker empty string teruggeven. In mijn ervaring is dat ook bijna altijd voldoende, en ben je als je vanuit input of imports aan het werken bent bovendien al heel vaak aan het checken op lege strings. Geen nulls en alleen checken op length=0 is dan wel zo fijn. (Trim wel je input natuurlijk, maar dat wordt niet opgelost door wel of niet nulls)

Zeker bij de suffix zie ik zo de meerwaarde van nulls niet in, het voegt geen extra duidelijkheid of veiligheid toe, selectie op wel of geen suffix is vaak niet van belang. Null als waarde voor onbekend kan mogelijk zijn, maar je kunt ook beargumenteren dat een adres waarbij velden onbekend zijn geen adres is en dus eigenlijk uberhaupt niet geaccepteerd moet worden. Het is meestal niet iets wat je later nog in kunt vullen. Of je vult het hele adres in, dus postcode-huisnr-suffix (of straat huisnr suffix woonplaats) of niet.
(Dit kan verschillen bij het gebruik. Een context waarin je incomplete adressen zou kunnen hebben zijn meldingen bij bv politie of gemeente - dan kan het meerwaarde hebben om alleen een straat in te kunnen vullen, en dus ook aan te kunnen geven dat nr en suffix onbekend is. Maar als je alleen maar besteladressen voor je webshop bijhoudt... dan is volledig invullen of de hele input verwerpen redelijk valide.)

In het algemeen zou ik zeggen: hoe abstracter je functies zijn, hoe meer nut er is om nulls null te houden. Maar in het meeste gebruik is lege string veel praktischer, en voorkom je eerder irrelevante foutmeldingen dan dat er belangrijke fouten mee worden toegedekt.

Never explain with stupidity where malice is a better explanation


Acties:
  • +3 Henk 'm!

  • nicenemo
  • Registratie: Juli 2005
  • Laatst online: 29-04 22:44
Null wordt door de uitvinder Tony Hoare ook wel de Billion Dollar mistake genoemd.

https://www.infoq.com/pre...Dollar-Mistake-Tony-Hoare

Met Optional maak je duidelijk dat het resultaat er wel eens niet kan zijn en dwing je de consumerende partij er iets mee te doen. Met heel soms een null gaat het lang goed.
Je moet dan in de Javadoc aangeven dat je soms null teruggeeft.

Een functie die die optionals teruggeeft geeft mag nooit null terug geven. Helaas zijn optionals gewoon objecten in Java. Dit moet je dus met code reviews en tooling regelen.

Optional is nodig om Functional Style te kunnen programmeren sinds Java 8 met Lambda's en de Streams API in java.util.streams.*.

Optional of Maybe is in functionele talen heel gebruikelijk. Het is eigenlijk niet veel meer dan een lijst van met maximaal lengte 1.

Een uitbreiding heet Either<T,E> waarbij de tweede component vaak voor de modellering van een fout gebruikt wordt. Either bevat altijd 1 waarde. Deze is van type T of E. Dit is handig voor code waar een Exceptie niet zo handig is bijvoorbeeld in Lambda's, java.util.streams.* en concurrent met Futures uit java.util.concurrency.

Bij gebrek aan elvis zijn de statische functies in Java.util.Objects erg handig voor het printen van Strings die mogelijk null zijn.
Reactie op een van de comnents
String.Empty bestaat niet in Java, dat is een .NET ding.

[ Voor 3% gewijzigd door nicenemo op 18-04-2018 22:02 . Reden: Link naar blogpost over Hoare ]


Acties:
  • +1 Henk 'm!

  • nicenemo
  • Registratie: Juli 2005
  • Laatst online: 29-04 22:44
Mogelijk wil je helemaal geen strings gebruiken maar specifieke domein objecten in de core van je code zoals NLPostcode, NLtelefoonnummer, BSN etc. Zo kun je foute state niet eens uitdrukken in je code. Je wordt dan ook gedwongen dit bij binnenkomst in de UI of service API af te vangen.

Deze kun je modelleren als een soort optionals gecombineerd met een Predicate Uit java.util.functions.*. Je kunt hiervoor generic base classes voor schrijven.


NLPostcode en NLtelefoonnummer kunnen van een specialisatie gebruik maken die een RegEx als predicaat gebruikt. Bij BSN gebruik je een 11 proof als predicaat.

Meer info zie https://fsharpforfunandpr...l-states-unrepresentable/ taal is F# maar is voor principe niet van belang. Wel een leuke taal overigens

[ Voor 13% gewijzigd door nicenemo op 18-04-2018 22:06 . Reden: Link naar relevante blogpost toegevoegd ]


Acties:
  • 0 Henk 'm!

  • sig69
  • Registratie: Mei 2002
  • Laatst online: 21:42
RobIII schreef op woensdag 18 april 2018 @ 17:10:
[...]

code:
1
myRepository.getCustomer(12345);


Ik wil een (customerNotFound)Exception als de klant met ID 12345 niet bestaat of een klant terughebben. Als je hier null gaat returnen moet ik vervolgens overal gaan checken of een-of-andere method niet toevallig null heeft gereturned.
Dat ben ik niet met je eens. Het is volgens mij prima acceptabel om null terug te geven, er is immers niets gevonden. Ik doe liever een if null check dan een try catch etc. Daarnaast zijn exceptions gooien meestal een dure bezigheid, dus een if check op null is sowieso sneller dan een exception afvangen.
(mijn referentiekader is C#, zou in andere talen natuurlijk anders kunnen zijn).

Roomba E5 te koop


Acties:
  • +2 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
sig69 schreef op donderdag 19 april 2018 @ 01:44:
[...]

Dat ben ik niet met je eens. Het is volgens mij prima acceptabel om null terug te geven, er is immers niets gevonden. Ik doe liever een if null check dan een try catch etc. Daarnaast zijn exceptions gooien meestal een dure bezigheid, dus een if check op null is sowieso sneller dan een exception afvangen.
(mijn referentiekader is C#, zou in andere talen natuurlijk anders kunnen zijn).
De vraag is hier een beetje: als je verwacht dat 't id bestaat (omdat bijv. de klant in de UI is aangeklikt) dan mag je prima een exception gooien in een GetCustomer wanneer die klant niet gevonden wordt (want dat zal (haast) nooit voorkomen tenzij iemand ligt te klooien met de url bijv. als het om een webapplicatie gaat). Dan is een exception prima acceptabel; sterker nog: dan wil je ook expliciet(er) loggen dat er iets aan de hand is wat geen normale gang van zaken is (ofwel: iets exceptioneels aan de hand ;) )

Is het "id" afhankelijk van user-input (en dus gevoelig voor typefouten o.i.d.) dan zou ik eerder een FindCustomer(string customerCode) method verwachten die een null kan returnen (als het een 0<=N<=1 uitkomst dient te zijn, bij een N>=0 verwacht ik een (al dan niet lege) IEnumerable). Dus alleen in 't specifieke geval dat je "zoekt" (i.p.v. "zeker weet") én je verwacht een enkel resultaat of geen resultaat dan is een null een mogelijke optie IMHO. *

Kort:
C#:
1
2
3
4
5
public interface Example {
    Customer GetCustomer(int id);  // Returned customer / throwed als niets gevonden
    Customer FindCustomer(string customerCode); // Returned customer / null als niet gevonden
    IEnumerable<Customer> ListCustomers(string lastName); // Returned 0..N customers
}


Hou je dit aan dan hoef je ook geen try...catch om élke invocatie van GetCustomer te zetten; dan kun je prima de exceptions omhoog laten bubbelen en globaler loggen en afhandelen / "gecontroleerd neerstorten" :+ Heb je plekken waar de GetCustomer afhankelijk is van user-input dan kun je op die plekken altijd nog een try..catch erom heen zetten (of beter: maak een TryGetCustomer(...) in .Net convention stijl ;) ).

Een ander voordeel: Maak je een CustomerNotFoundException (die je afleidt van een NotFoundException) dan kun je in 't geval van een webpagina makkelijk(er) automatisch een 404 laten gooien bijvoorbeeld door in je globale exception handler te kijken of de exception een afgeleide is van een NotFoundException (net zoals je een ProductNotFoundException en een UserNotFoundException zou hebben bijv. die je daar ook van zou afleiden). Of, als je lui bent, maak een wat generiekere EntityNotFoundException waarmee je voorgenoemde Customer/User/Product exceptions allemaal onder hetzelfde ding schaart)

Dus:

C#:
1
2
3
4
5
public ActionResult Foo(int id) {
  // Als GetCustomer throwed laten we 't lekker over aan de globale error handler om er
  // een nette 404 pagina van te maken
  return View(myRepo.GetCustomer(id));
}

I.p.v:
C#:
1
2
3
4
5
6
7
8
public ActionResult Foo(int id) {
  // Als GetCustomer null returned als deze niets vindt moeten we lokaal logica gaan
  // implementeren om een NullPointerException te voorkomen en netjes een 404 te tonen
  var customer = myRepo.GetCustomer(id);
  if (customer == null)
    throw NotFound(); // Of: return NotFoundView() o.i.d.
  return View(customer);
}


Dit tikt natuurlijk flink aan; voor elke entiteit heb je typisch bovenstaand stukje code; waar mijn methode kan volstaan met 1 enkele, vrij simpele, exception handler moet jij op élke plek die logica gaan inbouwen (of een wrapper method schrijven die de null-check uitvoert en de NotFound of View returned; maar dat vereist ook wat werk en je mag 't ook nergens vergeten omheen te zetten en als je geen view wil hebben maar de customer zelf (omdat je die bijv. weer aan een andere method moet doorgeven) moet je alsnog die null-check gaan bouwen op die plek waar je de customer ophaalt).

Zie het zo; allebei de GetCustomer() methodes ("de jouwe" of "de mijne" ofwel, die de null returned of die een exception gooit) kunnen net zo goed nog 200 andere exceptions gooien (OutOfMemoryException, SqlConnectionException, YouMessedWithTheWrongServerException, ...), daar ga je toch ook geen try-catch voor om elke GetCustomer() invocatie omheen zetten?

Maar goed; crux is dus wel wat de pre- en postconditions zijn die van de method verwacht worden en dat is, IMHO, dus nogal een beetje afhankelijk van de context.

Een andere manier om 't te zien: Een Int.Parse("foo") doet ook boem i.p.v. dat 'ie null (of 0) returned. Een File.ReadAllText(@"c:\nonexsistingfile.txt") doet ook boem i.p.v. dat 't null returned. Er zijn vast wel wat voorbeelden te verzinnen waar wél een null wordt gereturned, maar ik weet er zo 1, 2, 3 even geen, maar het is al laat ;)



* Persoonlijk vind ik nog netter:
C#:
1
2
3
4
public interface Example {
    Customer GetCustomer(int id);  // Returned customer / throwed als niets gevonden
    IEnumerable<Customer> FindCustomers(<predicate>); // Returned 0..N customers
}

En als je dan een enkele Customer verwacht op een bepaald zoekcriterium doe je er maar een (Linq) .Single() op; of, in jou voorkeur, een .SingleOrDefault() o.i.d. Helemaal vrijheid blijheid :+

[ Voor 53% gewijzigd door RobIII op 19-04-2018 02:47 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

  • Hydra
  • Registratie: September 2000
  • Laatst online: 13:27
Het is in Java land in ieder geval niet gebruikelijk om lege strings te gebruiken om de afwezigheid van een waarde weer te geven. Da's nu precies waar 'null' voor is. Of je dan in methodes inderdaad nulls terug wil geven of Optionals (nieuw per Java 8, wordt vooral vaak in service classes gebruikt op plekken waar een waarde misschien afwezig kan zijn) is een beetje persoonlijke voorkeur, zelf neig ik in de meeste gevallen naar Optional. Alleen wordt dat weer zowel in data classes afgeraden (optionals zijn niet serializable) en in method parameters (want type erasure).

https://niels.nu


Acties:
  • +1 Henk 'm!

  • Mugwump
  • Registratie: Mei 2017
  • Laatst online: 20:32
Hydra schreef op donderdag 19 april 2018 @ 14:27:
Het is in Java land in ieder geval niet gebruikelijk om lege strings te gebruiken om de afwezigheid van een waarde weer te geven. Da's nu precies waar 'null' voor is. Of je dan in methodes inderdaad nulls terug wil geven of Optionals (nieuw per Java 8, wordt vooral vaak in service classes gebruikt op plekken waar een waarde misschien afwezig kan zijn) is een beetje persoonlijke voorkeur, zelf neig ik in de meeste gevallen naar Optional. Alleen wordt dat weer zowel in data classes afgeraden (optionals zijn niet serializable) en in method parameters (want type erasure).
Sowieso slaat het gebruik van optionals in method parameters niet echt ergens op. Daar heb je gewoon method overloading voor. Het zou wat makkelijker zijn als Java ook eens de mogelijkheid om een default value toe te kennen aan parameters zou toevoegen, maar Java is wat conservatief. :P

Voor velden zou ik ook überhaupt nooit gebruik van optionals maken. Maak het veld gewoon het datatype en als je dan een getter maakt, laat die optional teruggeven.
Ik ben sowieso steeds minder fan van platte data-objecten die je qua data volledig blootstelt aan de buitenwereld, de zogenaamde 'anemic domain models'. Zeker wanneer je objecten het met meerdere niveau's van nesting is dat gewoon wachten op nullpointers in allerhande gebruik. Ik heb bijvoorbeeld wel eens een situatie gehad waarbij dergelijke data netjes in Mongo werd opgeslagen en opgehaald met JSON serializatie, waarbij je soms wel vijf niveau's van nesting had waar werkelijk alles potentieel null kon zijn van lijsten tot aan elementen in lijsten tot aan velden op die elementen. Gelukkig kennen veel template engines zoals Freemarker en Thymeleaf in Java nog wel een elvis operator, maar als je vervolgens business logica in je back end op een dergelijke 'data class' wil toepassen, dan is het één grote ellende. Zeker in een beetje groot, ietwat chaotisch verlopen project heb je dan een codebase met op honderden plekken allerhande potentiële nullpointers.

"The question of whether a computer can think is no more interesting than the question of whether a submarine can swim" - Edsger Dijkstra


Acties:
  • 0 Henk 'm!

  • nicenemo
  • Registratie: Juli 2005
  • Laatst online: 29-04 22:44
Java equivalent voor SingleOrDefault uit de Streams api:
Streams.findFirst
https://docs.oracle.com/j...m/Stream.html#findFirst--

En deze heeft als resultaat.... een Optional. Waar .NET voor null kiest, wordt in Java voor Optional gekozen.

Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
nicenemo schreef op donderdag 19 april 2018 @ 18:52:
Java equivalent voor SingleOrDefault uit de Streams api:
Streams.findFirst
https://docs.oracle.com/j...m/Stream.html#findFirst--
SingleOrDefault throwed wanneer er niet precies 0 of 1 resultaten zijn (dus N=0 geeft null (of whatever de default is), N=1 geeft het (enige) item en N>1 geeft een exception). FirstOrDefault returned de eerste (of default als er niets is). Als ik jouw link volg is findFirst dus niet equivalent met SingleOrDefault ;)

[ Voor 13% gewijzigd door RobIII op 19-04-2018 18:59 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

  • Mugwump
  • Registratie: Mei 2017
  • Laatst online: 20:32
RobIII schreef op donderdag 19 april 2018 @ 18:55:
[...]

SingleOrDefault throwed wanneer er niet precies 0 of 1 resultaten zijn (dus N=0 geeft null (of whatever de default is), N=1 geeft het (enige) item en N>1 geeft een exception). FirstOrDefault returned de eerste (of default als er niets is). Als ik jouw link volg is findFirst dus niet equivalent met SingleOrDefault ;)
De type systems zijn sowieso niet helemaal lekker te vergelijken. Java kent bijvoorbeeld geen nullable types, expliciete Value Types, structs en nog een aantal andere zaken die C# wel kent. Java kent wel weer primitives zoals int en long, waarvan je dan ook nog eens weer Primitive Wrapper Classes als Integer en Long. Primitives kunnen nooit null zijn, in tegenstelling tot wrappers. Om de boel een beetje makkelijk te maken heb je in Java dan weer autoboxing dat automatische conversie van Wrapper naar Primitive doet en vice versa. Levert wel vaak voor veel developers weer onverwachte nullpointers op omdat dat unboxing een nullpointer kan geven. :P

"The question of whether a computer can think is no more interesting than the question of whether a submarine can swim" - Edsger Dijkstra


Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Mugwump schreef op donderdag 19 april 2018 @ 19:36:
[...]


De type systems zijn sowieso niet helemaal lekker te vergelijken. Java kent bijvoorbeeld geen nullable types, expliciete Value Types, structs en nog een aantal andere zaken die C# wel kent. Java kent wel weer primitives zoals int en long, waarvan je dan ook nog eens weer Primitive Wrapper Classes als Integer en Long. Primitives kunnen nooit null zijn, in tegenstelling tot wrappers. Om de boel een beetje makkelijk te maken heb je in Java dan weer autoboxing dat automatische conversie van Wrapper naar Primitive doet en vice versa. Levert wel vaak voor veel developers weer onverwachte nullpointers op omdat dat unboxing een nullpointer kan geven. :P
Allemaal heel leuk hoor (maar was/is me we bekend) maar hoe slaat dit op wat ik zei precies :? (Want je quote me)

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

  • Mugwump
  • Registratie: Mei 2017
  • Laatst online: 20:32
RobIII schreef op donderdag 19 april 2018 @ 19:53:
[...]

Allemaal hee leuk hoor (maar was/is me we bekend) maar hoe slaat dit op wat ik zei precies :? (Want je quote me)
Je hebt het over het teruggeven van 'default' in C#. Aangezien dat concept niet als zodanig bestaat in Java, kan je dus eigenlijk ook nooit een equivalent van de C# methode in Java hebben.

"The question of whether a computer can think is no more interesting than the question of whether a submarine can swim" - Edsger Dijkstra


Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Mugwump schreef op donderdag 19 april 2018 @ 19:55:
[...]


Je hebt het over het teruggeven van 'default' in C#. Aangezien dat concept niet als zodanig bestaat in Java, kan je dus eigenlijk ook nooit een equivalent van de C# methode in Java hebben.
Het ging mij over het verschil tussen first en single; default was bijzaak.

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

  • nicenemo
  • Registratie: Juli 2005
  • Laatst online: 29-04 22:44
Je hebt gelijk. SingleOfDefault knalt als er meer resultaten zijn.
Grootste probleem in Java is nog Type Erasure:( Ik ben begonnen met Java, toen 15 jaar .NET en nu weer terug bij de Duke Side of the force.

Om te kijken wat met Java 8+ kan een zeer experimentele lib Noaber opgezet https://github.com/nicenemo/jnoaber. Er bestaat ook een C# versie. Hier experimenteer ik met Lambda's Optionals Streams etc (en in .NET met Linq) .

Op dit moment ben ik bezig met een FP style switch functie te bouwen. Ma.w. een switch die ook cases met predicaten, type, regexes e.d. heeft.

In de Java versie er achter gekomen dat overloads aanroepen vanuit een Lambda in combinatie met Generics niet werkt.
Constraints op Generics zijn in Java veel beperkter dan in .NET

Partial application krijg ik niet werkend als ik overerving wil mee nemen.

In .NET zijn er dan weer subtiele verschillen tussen C# en VB.net in combinatie met Linq en foreach

Acties:
  • +1 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
nicenemo schreef op donderdag 19 april 2018 @ 23:52:
*een compleet irrelevant verhaal en linkjes naar (eigen) projecten enz.
Allemaal heel leuk enzo, echt, maar zullen we proberen een beeeeeetje ontopic te blijven?
offtopic:
Duke side of the force :? :? Mis ik een referentie?

Ook heb ik even gekeken naar de Noaber en JNoaber projecten; uit beide README's word ik geen klap wijzer wat ze nu zouden moeten doen / welk probleem ze oplossen en (steeksproefsgewijs) in de .Net versie kon ik geen enkele regel commentaar vinden en in de java versie niets dan nietszeggende boilerplate comments. Either way; als ik na 3 minuten niet zie wat 't is / doet haak ik af en ga ik op zoek naar iets anders. Just sayin' ;)

[ Voor 63% gewijzigd door RobIII op 20-04-2018 00:10 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

  • nicenemo
  • Registratie: Juli 2005
  • Laatst online: 29-04 22:44
Duke is de mascotte van Java

Beide libs hebben functioneel programmeren als topic.
De Java versie maakt nogal heftig gebruik van Optionals. Is verder idd oftopic. Was een reactie op jouw opmerkingen met Linq(Streams in Java). Neigt voor de lezer ook naar oftopic als je niet bekend bent met Optional.

Negeer als je verder geen interesse hebt

Om je vragen te beantwoorden:
- code is meer bedoeld om te kijken wat kan met Linq in .Net en nieuwe dingen in Java 8. Het heeft wat trekjes van een inner framework.

In de Readme's staat duidelijk experimentele code. Maar meer uitleg is wenselijk. Dit ga ik toevoegen. Eerste poging hieronder

- .NET versie implementeert o.a. Linq voor tupels en een aantal andere Linq helper functies. Ook heb ik gekeken naar een implementatie van Either.
- niet gedocumenteerd omdat ik ooit het plan had een groot deel met T4 te genereren. Code is soms nogal boilerplate omdat alleen aantal argumenten of het type verandert.

In de Java versie experimenteer ik met dingen uit functioneel programmeren zoals partial application, curry, geavanceerd pattern matching etc.

Daarnaast kijk ik naar het gebruik van varargs in zowel de C# als Java versie In JavaScript accepteren Math.min en Math.max meer dan 2 argumenten. Geïnspireerd op blogpost van John Resig.

In C# maak ik gebruik van extension methods en partial classes om het beheersbaar te houden
Java heeft geen extension methods en partial classes zoals C#. In plaats daarvan maak ik gebruik van default implementaties in interfaces om het beheersbaar te houden.(Cake pattern) Ik ben hier een paar keer van gedachten veranderd: default vs static methods en wel of niet alles in 1 class.

Op dit moment focus ik me op een correcte implementatie van fp style pattern matching. Hierbij voeg ik voorbeeld code toe in de vorm van unit tests en verbeter ik meteen de boilerplate docs. Hier komt uitgebreide documentatie bij:
- stap voor stap opbouw
- ontleden van switch statement
- naming, ik heb uiteindelijk voor (when/then gekozen)
- partial application gebruiken of niet.
- Waarom wel:
- caching
- geen combinatorische explosie van te testen code
- cases met predicaten, classes en RegEx.
- testcode met Fizzbuzz fruit en meer.
- ellende met Generics in java.
- is mijn class FunctionalPredicate overengineering
Ik kijk nu specifiek naar pattern matching en constraints op Generics in Java. Deze zijn veel beperkter dan in .NET

[ Voor 2% gewijzigd door nicenemo op 20-04-2018 07:24 . Reden: Typo ]


Acties:
  • +1 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Ok, ik gaf wellicht aanleiding tot bovenstaand in mijn [ot] stukje maar nu loopt het de spuigaten uit; ga aub verder in [Alg] Welke tools heb jij gemaakt? - deel IV als je graag wil showcasen. Nu ontopic aub.

[ Voor 18% gewijzigd door RobIII op 20-04-2018 09:52 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

Anoniem: 80910

je moet je af gaan vragen wat de "responsibility" is van de functie en het verwachtingspatroon daarbij verzinnen. bij de ene functie zal ie dan null retourneren en bij de andere functie '' (bijvoorbeeld achternaam moet altijd gevuld zijn, dus dan null pointer exception bijvoorbeeld. maar een tussenvoegsel is optioneel dus die kan dan best een lege string retourneren, beide goed...
Pagina: 1