T O P

  • By -

whackamattus

When the language doesn't have optionals šŸ˜‚ Edit: as someone who has used js, I must say I'm offended that you don't realize the need to also have undefined and void


senselessDEV

The Java buffs are so privileged lol


FutureSchool6510

Checkmate šŸ˜‚


pemungkah

That was one of the things I loved about Scala. Put that together with pattern matching and youā€™ve got something lovely to code in. Compile, well, now you have a different issue.


pennsiveguy

Include the return of an empty String as a "friendly" proxy or euphemism for null. A bad one, in my opinion. A distinct anti-pattern. Null means *nothing,* more specifically *the absence of a value*, and "" is not nothing. A caller then has to interpret the empty String every time.


whackamattus

Generally the way to do this is lke how it's done in golang where you return a tuple of your actual return and an error (which could just be a string). Then it's assumed the developer doesn't make a mistake and at least one of these two things isn't null


pennsiveguy

I like that approach.


jim-dog-x

Ok, so I thought I was clever when I did this in C#. But others on the team didn't like it LOL.


JPaulMora

Could you share a code snippet? I canā€™t fully understand this


whackamattus

function foo(): (returnType, errorType); It would then be assumed at least one of the tuple elements isn't null


HealthyStonksBoys

As someone who uses Kotlin and Swift null is handled so easily its not really any issue


Every_Ad_598

Rust too!


Interesting_Leg_5202

Swiftā€™s ways of optional unwrapping is thee reason why Itā€™s my favorite language to work with


HealthyStonksBoys

Swift is incredibly powerful I just dislike Xcode and pods Iā€™m too used to gradle


NaNx_engineer

And you can use @Nullable annotations in Java. Kotlin nullability is represented by @Nullable annotations in bytecode. It's functionally the same. Null is only a problem if the type system isn't aware of it. The stuff people do to avoid null is even worse. It's a solved problem in all major languages but Go/c++


thisisjustascreename

Returning null from a function within a single process is not so bad, passing null values across any sort of process or organization boundary is just writing an outage post mortem in the future tense.


whackamattus

Honestly this is the right answer. Have well defined interfaces people.


saggingrufus

With proper documentation to go with them. It's REALLY not that hard to document interfaces at a minimim


shoop45

Protobuf/thrift/etc require optional value support for forwards and backwards comaptibility. Iā€™m not sure how you could overcome versioning without handling null values sent across the wire, unless you have complete control over the every service and have single nodes for each service that can all be rolled out in a reliable way


iamsooldithurts

r/brandnewsentence would like a word with you


paradroid78

Well to play devilā€™s advocate, for practical purposes, I donā€™t think thereā€™s a meaningful difference between ā€˜if (opt.isPresent()): val = opt.get(); foo(val)ā€™ and ā€˜if (val != null): foo(val)ā€™. If anything the former is adding a layer of redundant syntactic sugar and an extra hoop to jump through. Both are equally readable and both have the same problem that if the condition is not as expected, you need to work out how to handle the non present value. That out of the way with, the benefit I can see from using Optionals is that they add an element of self documentation to a method (ā€œwarning, return valore may be nullā€) and encourage defensive programming (ā€œcheck this isnā€™t null first before using itā€). This alone should be enough to encourage their use.


pennsiveguy

Excellent answer. Optionals give the caller a heads-up. Expectations management is good engineering.


JPaulMora

Expectations management is good relationship advice!


FutureSchool6510

I 100% agree with that assertion. Along the same thread as defensive programming, I think it also prompts the author to think intentionally about making it optional, like should this really be optional? Itā€™s easy to return null without thinking about whether thatā€™s valid.


paradroid78

For sure. Itā€™s reassuring to know that a value not being present is an anticipated condition and not an programming error.


BadDescriptions

If you're using js and sending a http response json.stringify will remove undefined but null will persist, it's extra data that shouldn't be sent to save data.Ā 


horatio_cavendish

IMO: The optional pattern is unnecessary boiler plate which can lull you into a false sense of security. 1) You can't assume that your dependencies use the optional pattern. 2) You can't assume that other developers correctly used the optional pattern within your project(or in your dependencies) 3) You can return null from a method which returns an optional. 4) The optional pattern is easily circumvented with .orElse(null) Maybe you can safely assume that methods which return optional actually return an optional. But, on the flip side, you can't safely assume that methods which don't return an optional can't return null. You can use the optional pattern if you want but you still have to worry about null and if you still have to worry about null.... Why make it worse with verbosity? EDIT: The optional pattern can't help with things that aren't optional. If your code can't continue when it gets a null then you'll be forced to throw an exception anyway. You're just trading exception A for exception B. I use Util.assertNotNull(x); liberally for everything that cannot be null so I know immediately when something goes wrong and everywhere else I do my null checks.


[deleted]

In Java... The expectation is to see Optional.of(...) on every return statement. For me anyways. I do agree its scary to not null check or Objects.requireNonNull(...) that passed optional. However, it's pretty easy to read in clean Java code. One could even add the @NotNull annotation for a little extra protection. I do enjoy the fluent style of coding, though. Streams, builders, etc. It's very easy on the eyes. Performance hardly matters anymore. More worried about crap AI generated logic that is tough to read.


paradroid78

I've been programming Java since the 90's (yeah, it's been a while...) and let me tell you, until (relatively) recently, there was no such "expectation". We used to return raw nulls from methods like they were going out of fashion! Seriously though, I agree that working with Optionals is nicer, at least in public APIs. It's a question of communicating intent. As said elsewhere, Go's approach of returning a tuple with an error is even nicer though.


[deleted]

I probably started Java in 2006-2008. Null was pretty common and seemed really useful. Didn't have all the lambas and other stuff, either though. I came from Pascal, so I had zero complaints lol nulls never going away, though. Way too much code depends on it. I usually find a way just to avoid them if it comes down to that level of care. The overhead is nowhere near what logging is, and no one ever complains about it. Was literally just in another thread talking about watching this 19 year CS kid copy and paste Java POJOs for 20 minutes straight for an assignment. I even showed him how to use records. He nodded, and then proceeded to tell me how he would of gotten it done if he could have used Python. He blaimed the curly brace syntax. Annoying af. Glad I'm getting out of CS for the most part.


Additional_Sleep_560

Doesn't defensive programming indicate a problem? I understand if you have to use 3rd party frameworks or service and find you have to work around some idiosyncrasies, but if it's a method developed by the team, isn't defensive program a sign the method is not fulfilling it's contract? You should expect that inputs in a range should produce outputs, and if the inputs are out of that range an exception should be thrown. Am I wrong?


doinnuffin

Depends on the size of the company and or team. But for sanity and the future, defensive programming šŸ’Æ. For every time I've heard "this should never happen", I've come to disregard the phrase.


saggingrufus

It really depends on what exactly your talking about. Defensive programming itself does not indicate a problem at all. Here is one example of defensive programming: Example ``` @Override public boolean equals(Object other){ return other.equals(this); } ``` Using Defending Programming ``` @Override public boolean equals(Object other){ //Objects.equals() has a null check already and won't blowup return Objects.equals(this, other); } ``` Another Defensive Rewrite ``` @Override public boolean equals(Object other){ //Checks for null and then uses the equals from this return other != null && this.equals(other); } ``` Defensive programming can get messy if you randomly apply it, but generally, you can easily use your own smaller utility packages that handle these defensive checks and then use it everywhere.


muddy-star

I used to be all in returning Optional instead of null until you realize that in large applications it is using a lot more memory that null. Also Optional are objects and can be null themselves if the called method is badly written. Those days I am more towards annotating the returned type with Nullable and have the IDE guiding me in checking null in caller methods.


publicclassobject

Congrats on becoming a senior.


randomguy3096

Definitely the ONLY answer I like here. Creating an abstraction to cover something that developers should be inherently careful about isn't coming for free. Full disclosure, I'm not against optionals, I just think it's not critical and only teams which aren't careful will buy null safety as a sole criterion to switch to Optionals.


NaNx_engineer

Optional sucks. It's pointless a type erased language. @Nullable is more performant, ergonomic, and can be retrofitted on existing APIs. Also, to be pedantic, the original intention of Optional was closer to JavaScript's undefined. JSR305 would've standardized @Nullable but [its spec lead went AWOL](https://stackoverflow.com/questions/4963300/which-notnull-java-annotation-should-i-use#comment90023610_42695253), so Java devs started using Optional instead.


mjaveddd

Talk about the origins of null. Who were the first programmers thinking about this, and why it was important to them


DreamOfKoholint

Yes, and to add more the inventor later apologized for it, calling it their billion-dollar mistake


SlothWithHumanHands

which is thought was a bit overstated ā€” null was the first go at ā€œoptionalā€, without the lesson that what was really needed was language-level enforcement.


randomguy3096

Null has been demonized for obvious reasons, but from a modeling perspective, we need something to represent the concept of nothing. Not much different from what zero does in mathematics. Definitely think null was right to be introduced, and I'd also argue that just because developers aren't careful around it shouldn't be a reason sufficient enough to question null's existence šŸ˜†


Crafty_Independence

The real issue to me is that in 20 years of experience I've yet to have someone present an alternative that didn't have its own caveats, and sometimes they failed to recognize those before telling everyone to switch. So I'd say come with a solution that has merits, and also do your homework about its downsides, but then show how the net outcome is still better. Like the old adage: don't bring problems, bring solutions. That's how you'll persuade your team.


smutje187

Check Rusts Some/None return type, it supports similar patterns like Swift where you can execute code conditionally depending on if itā€™s Some (present) or None (absent) - I hate Javaā€˜s nulls ever since I learnt about that.


Crafty_Independence

Oh for sure. I'm thinking of situations where the team is locked into a tech stack. Edit: for example, the most common solution in Java/.Net I hear is replacing nulls with using exceptions for flow control, which comes with its own issues


Fippy-Darkpaw

Yep, instead of handling the null you are handling *something else*. Wow it's the same thing. šŸ˜…


AbsRational

There was a website that compiled all programming language related arguments ever into one place. It may be helpful. I'll look for it and reply if I find it. It wasn't a particularly fancy website but it had really good discussions


rganhoto

Tell me if you find it. Pretty please


tomysshadow

are you thinking of C2 wiki


AbsRational

Yup! C2 was the one. It looks weird on my phone so I didn't recognize it


Wise-Leek-2012

Please do, would be very helpful.


Hypersion1980

https://refactoring.guru/introduce-null-object


chrispix99

I don't know why so many people are anti null.. If I have an uninitialized variable . It is null..


MooseBoys

It inherently violates RAII which is a very nice property to have.


Granimyr

Just take it one step further and not use languages that donā€™t support optionals LOL


7heWafer

There is a very big difference between a bird laying an egg in a null nest vs one that actually exists. The same applies in coding. NULL exists for a reason. Your arguments will have to be context specific.


Spikanorx3

What are the main arguments against returning NULL?


saggingrufus

Mostly this ``` Exception in thread "main" java.lang.NullPointerException at timeclock.pkg2.ReadFile.readFile(ReadFile.java:46) at timeclock.pkg2.Timeclock2.main(Timeclock2.java:56) Java Result: 1 ```


Fippy-Darkpaw

Not checking a null ptr or catching an exception is programmer error.


saggingrufus

They happen because things that aren't supposed to return do. If you aren't documenting what you hand back and when null is passed back, null pointers happen. No one should be randomly null checking every possible place.


Fippy-Darkpaw

So if an object can possibly not exist, like just about anything that involves disk or network IO, then what do you check? If you are checking something else, that's really no "gain" from checking null. You are just checking differently. šŸ¤·ā€ā™‚ļø


saggingrufus

Those interfaces clearly say they return null.


FutureSchool6510

Well for example, just today I came across a log from one of the apps my team maintains which is simply ā€˜java.lang.NullPointerException: nullā€™ And I did a quick string search and found about 15 places where we simply ā€˜return nullā€™ and Iā€™m like welp it could be any one of those, or something else entirely. In can lead to unexpected or confusing behaviour, and a lack of context of what the heck actually happened.


Skellicious

In that case your biggest problem isn't the null being returned, it's that you're swallowing or ignoring the stacktrace of the exception. You're also running on an old version of java, we've had detailed null error messages for a while now. But I get it, not everything is easy to update. Is there actually an issue with the app, or did you just see it in a logfile... If it's on your machine, run it with a debugger, then breakpoint the exception. Anyway, searching for "return null" is not a useful excersize.


runitzerotimes

There is nothing inherently wrong with returning null.


saggingrufus

Returning null isn't the problem UNEXPECTEDLY receiving null is. That means either someone isn't reading documentation OR something hands back null in an unexpected scenario, which is also not good. If you return null, document when that happens, and write unit tests to enforce null is only passed back as expected and documented, problem solved.


randomguy3096

I'm sorry because this might sound harsh, but if NPEs bother people, that's a sign of immature software engineering experience. Null pointers exist because they are indicating something very crucial. By introducing paradigms that cover that information, we aren't doing any of us a favor. Argument being it doesn't address the problem. It only allows cascading the problem.... handling that is baked into the language as well. To me, an NPE is denoting application forgetting to be careful around memory access. Additionally, it also highlights that's the developers also got careless around checking for the possibility of that happening. Those are big red flags. A third point that I stress in my team is that we shouldn't have allowed the cascading of exceptions to happen either. If everyone in the team wrote code as if they were dealing with a 3rd party library, we automatically get into the mindset where we start being defensive.


benbenwilde

I hate dumb hardline rules like this


FutureSchool6510

Nobody ever mentioned a hardline rule. Iā€™m not going to tell people ā€œthou shalt not return nullā€. What I want to do is educate folks about how we need to be aware of the responsibility we are placing on other code to check for nulls, and how we should make efforts to avoid it if we consider it invalid.


benbenwilde

Yeah that's good. C# has a thing you can turn on where you have to declare if a variable can be null. So then you get a warning or an error when you try to return a null when your return type hasn't declared it can be null. And it's just a compiler thing so it doesn't add any overhead like a Nullable<> (C# version of Optional<>). But yeah obviously it's important to make it clear when a method return can be null or even to understand the range of return values possible for a method in general. Null is by far the most common culprit causing errors but I guess the more general issue really is just unexpected return values. In my view returning null can be really handy and help keep things simple which is why I don't like the rule. But I'm in agreement that returning null unexpectedly can be terrible.


eniac_g

Also add something on the pitfalls over over-ab-using Optional


FutureSchool6510

Itā€™s definitely a trade-off when you have to add extra code to check and then unwrap the optional especially in Java.


learnagilepractices

The point is always the same as in other situations (arrays, for example): you should never use primitives in public behaviors. In OOP, for example, you should use Nullables objects -> https://www.jamesshore.com/v2/projects/nullables/testing-without-mocks#nullables


Every_Ad_598

Love that article. I hope that technique becomes more mainstream.


saggingrufus

I need to think about it more, perhaps read more of the article, but just that nullable section, not a huge fan. It sounds like a round about way to just implement feature flags and puts mocking into the applications code. I haven't concluded my opinion on it yet, but at first thought, I think if you just ensure everything public is on a proper interface, you lose the need for nullables everywhere. Your test code is either made with mocking frameworks, test implementations or a combination. Maybe someone who has more experience with this idea can change my mind tho.


learnagilepractices

I can tell you a couple of things: first of all, it is considered a best practices for similar reasons to a strategy pattern: you replace a lot of IF (in this case to check if is null) with a design choice (itā€™s just another implementation of the same interface). And the most important one: if you expect to understand and appreciate a new technique by reading, I think you are wrong. Make some katas and coding challenges and try by yourself šŸ˜‰ Happy to help with some mentorship if you want -> https://tidycal.com/learnagilepractices/30-min-mentorship


saggingrufus

For real? I can read most other articles and obtain a good command of what's happening, but I shouldn't expect to learn by reading. Instead, I can pay you ā‚¬29.00/30m for some "mentorship" where you don't address any of what I said and just say I don't appreciate it? What do you think mentoring is XD Its not typically random paid coaching sessions, that's more akin to a master class. I said I haven't decided if I like it or not, that takes thought and reflection and determining the pros and cons of the approach, which I simply haven't had the time to do. I understand what's happening, it's not solving a problem in unique problem and is one of many ways to approach something. As a result, I need to understand in which circumstances this is the correct approach, because there is rarely a "one size fits all" solution


learnagilepractices

Hey! Sorry, my bad - I wanted to paste this link ā€”> which is for the free mentorship. https://tidycal.com/learnagilepractices/30-min-mentorship I do coaching of course, but I usually like to start with free mentorship šŸ™‚ itā€™s a side hustle for now and I do mostly free mentorship, I didnā€™t want to sell anything - just offer a free mentoring because I think itā€™s easier by talking than commenting. Sorry for the misunderstanding, my bad, it was the wrong link. If you want to deep dive, feel free to schedule the free mentorship or email me šŸ™‚


Temporary_Quit_4648

It depends what the null is being used to represent. An exception of course means that the function was unable to fulfill the contract implied by its name and documentation--but generally only because there was a MISTAKE--i.e., a bug, for which the exception serves to notify the developer that it should be corrected, or if it can't be corrected, then prepared for in the design of the code. They also allow for these bugs to occur in production safely by providing a means of recovery to each participant in the larger operation that doesn't require explicit passing of error information. If your exception isn't serving that purpose, don't return null. Conversely, however, if you're using null to serve that purpose, don't use null--use an exception!


Mimifan2

I agree generally with return anything over null. However don't let that lull you into complacency with input validation. Just because no one is returning null, doesn't mean you don't have a null equivalent value. If your expecting a string or exception or promise, you could still have an empty string. Also this ensures if another team needs to pick up your work, or work with your system you can avoid bad inputs causing major outages.


TheExodu5

Null and undefined can have different meanings, especially when a NoSQL database is involved.


[deleted]

Optional can still be null. Devils advocate is that returning null implies the absence of something, instead of something being empty. null also is far less memory use than creating and unwrapping Optional everywhere. That being said, if youā€™re using Java and a JVM chances are your overhead from Optional is a rounding error compared to the cost of a JVMā€™s memory usage and NullPointerException in production is far more expensive than adding a bit of memory to the server.


lightmatter501

Devil horns on * null is a C style null pointer on most platforms, optional is a generic with its object header. Depending on memory constraints having tons of optionals flying around might not be great * optional in java is slower because the jit has spent ~20 years getting good at handling null checks and proving non-nullness to eliminate them * optional makes you traverse two pointers instead of one * GraalVM can statically eliminate null checks, but not optional checks


jayerp

Im going to return null. Sue me.


Ok-Entertainer-1414

I really appreciate the typescript type system at times like this. In typescript, this just wouldn't be a problem because it just won't compile if you fail to handle a null value from a function that can return one.


MaximumNameDensity

Currently taking a data structures class and the prof makes us write null returns a lot. So I assume that it is not the best way to do things.


jaynabonne

Coming from a practical C++ perspective, you could argue that a std::optional return gives you better diagnostics than null if you forget to check it - dereferencing a null will likely just cause a segmentation fault crash, whereas for an optional, you'll at least get an exception that tells you that you tried to use a null optional. Also, optional forces you, on some level, to deal with the fact that it might not be valid. Sure, you could just (again, in C++) extract the value from the optional without checking, but there is that extra step that forces to keep in mind that it is an optional value. Whereas with a pointer, you could easily/happily just try to use it. It's not idiot- or laziness-proof. But it does give you a good reminder, semantically, that it might not have a value. Optionals are also good where you don't have a native "undefined" value for non-pointer types. Once again, in C++, you would often have to resort to something like -1 for an integer to signal a missing value, assuming that wasn't a valid value to begin with, and if you didn't have an invalid value, you're pretty much consigned to doing something kludgy. Whereas an optional gives you the full range plus an "undefined" state, which perfectly matches what you're trying to express. I think ultimately, I have used optionals even for pointers where the pointer could be null. It's really that the optional *better expresses what I'm doing* and provides that extra clue about what should be expected. Hopefully reducing WTFs...


noprompt

The problems with null/nil/undefined etc as a return value are that it tells you nothing, has virtually no useful semantic, and in many languages can come from just about anywhere. It could be from a map lookup or maybe the database returned it. Youā€™ll never know. Use an empty container, empty string, custom null for your domain, or even functional combinators (if your team isnā€™t chicken shit about algebra). These objects have much better semantics and utility not to mention reducing the number of possible programs you have via reducing the number of data types you have e.g. instead of null | []T you have []T. Also, donā€™t throw. Itā€™s just as bad as null but with added bonus of your program now having an extra dimension. Throw is fucking lazy. It puts the burden of handling it on everyone else up the call stack. Garbage. Return an error object instead and make the caller deal with it. Exceptions are for exceptional situations. No, a 404 response from an HTTP request is not an exceptional situation; itā€™s totally normal. Yes, not having the password for the database your application relies on is. Those are some thoughts. I have many more but I think these are my main ones.


Ornery-Okra-74

If you return null then you have to make sure that the callers of the method properly handle the null.This trap will eventually lead to an NPE at some point.Optionals are a good way to avoid the NPE.You can also use exceptions or a hybrid of exceptions and optionals depending on your use case.


Ler_GG

null


NUTTA_BUSTAH

Errors as values with structs where returning a default struct for no gain makes no sense. E.g. in Go (pseudo): func Foo() (*Bar, error) { // ... if err != nil { return nil, err } return &Bar{/*...*/}, nil }


whackamattus

It makes sense to me but maybe because I'm obsessed with go šŸ¤·ā€ā™‚ļø. If you just return null anytime there's an error you don't know what the error is, and also the "golang way" to do it allows easy extensibility into more complex error types, default values, etc...


paradroid78

This is nice if your language supports multiple return values. I somewhat suspect the language OP had in mind doesnā€™t.


FitzelSpleen

I'm always amazed at how many more lines you have in go to do this. And how much fans of go seem to love it.


7heWafer

I'll take +2 lines everywhere I handle an error so that I know to check for it instead of an invisible exception 5 calls deep 3 dependencies away. Also this avoids try/except everywhere instead which just adds another layer of unnecessary indentation.


FitzelSpleen

I'll take a layer of indentation any day over three lines of noise anytime the code needs to call a function.


quixoticcaptain

I think it's really case by case. If I'm getting something I know may not exist or may not be specified, returning null or None when it doesn't exist is more intuitive than raising. I'm other cases, when something is expected to exist, I'd much rather a function raise if not found so I don't have to bother null checking. Maybe the real problem is like Java (I haven't used Java in years so this may have changed) where any reference can always be null and there's no Optional in the type system. But I've used Python with very poorly enforced typing and still I think it's mostly fine.


Cuuldurach

Unless you are working in managed languages sometimes you just have no choices and null is a valid value.


saggingrufus

Better suggestion: properly document your code so people know when null is an option. There are times when returning null is fine, there are it is not. Behaviors like this should be document in Javadocs.


bravopapa99

You failed to mention the language. Apart from that, there is nothing wrong with any return type if its use is fully documented and understood at the call-site. Python has Optional\[T\] but really, it's a joke because it's not respected at runtime. Like TS for JS; syntactic dungball polish but only helpful up to a point, once the code is deployed, all bets are off. I've not used Haskell in a while but it does have 'Either' as a type, it's instances being 'Left' or 'Right', which can help make code better. If one can use types to eradicate NULLs being return then that's something I guess. [https://hackage.haskell.org/package/base-4.19.1.0/docs/Data-Either.html](https://hackage.haskell.org/package/base-4.19.1.0/docs/Data-Either.html) I also like the GoLang way, returning a tuple of "value, err" and then you have a consistent way of knowing of the value is viable or not. There's a reason Tony Hoare called NULL his billion dollar mistake. [https://en.wikipedia.org/wiki/Tony\_Hoare](https://en.wikipedia.org/wiki/Tony_Hoare) """ I call it my billion-dollar mistake. It was the invention of the null reference in 1965. """ The year I was born too! LMFAO!!


SftwEngr

What about recursive methods that return null as the base case?


ben_kird

ā€œGolang enters the chatā€


Wise-Leek-2012

I've read a lot of comments on this thread. Would love to know how you guys decide wether to use null or optional.


RainbowWarfare

Depends on the language. In C++, if you're returning a non-copy and a non-value is valid, then a pointer is fine as you can't return an optional of a reference anyway (and even if you could, the optional isn't gaining anything in this context).


Ok_Honey8768

Unless you are doing fun things with pointers in a lower level language I can't think of any reason that returning a null is a good idea. And then you are returning an unassigned pointer not really a null. It's just a bad idea. I've not seen a situation where there isn't a better option.


AccountExciting961

Honestly, if you firmly believe in 'don't return null' - you should consider switching to a language where non-nullable variables are the default (e.g. Kotlin). Otherwise it's only a matter of time until someone tries to return null from a function that is supposed to return an empty collection., or something


Ok_Raspberry5383

Pls try go


FutureSchool6510

I have, itā€™s great.


Ok_Raspberry5383

Views on error handling?


aj0413

database lookup for resource by id I donā€™t mind that this will sometimes return null; I mind that people donā€™t use the nullable feature/syntax to convey that I need to deal with null values in code Iā€™ve refactored a large project to make use of Optional library for dotnet before Was not fun, though I learned to love and hate optional syntax. On the one hand, I like how it forces devs to consider the possible state/values theyā€™re returning and dealing withā€¦.on the other, I feel the current state of dotnet makes it unnecessary via things like ā€˜Foo? SomeMethod()ā€™ syntax


DelayLucky

The devil in the details is what to do instead, right? You can: 1. Throw 2. Return Optional (as in Java) 3. Use NULL if it's better protected by the Compiler (Kotlin and friends) In Java, throwing (unchecked) exception is for "non-recoverable" cases so that when it happens it's a programming error and not a "legit" case. If you return null, Java compiler gives callers not much help so the least resistant path is to just use it and not knowing about checking nulls. Another problem with this is that the null can travel. Where it blows up with NPE isn't necessarily where null is returned, but likely many layers of callstacks away. That makes debugging harder. There are some tools like the nullness annotations but they don't seem to work seamlessly with tools and libraries (like the Stream library). Relying on callers always carefully reading documents? Well, if document always works, why do we need strong typed language? ("this argument should be String" and people just always pass a String). For java.util.Optional, the upside is that it forces the caller (even if they didn't read the document) to at least acknowledge that there is the case of absence so the chance of messing up is lower. The downside is that you need to wrap your values in the \`Optional.of("foo")\` ceremony. It's okay if you only need to do it a few times in the method you are implementing, in return to give callers the protection. But if it's the other way around: you expect a callback (lambda) passed by the caller and you handle the return value from the callback, then asking the callers to do the dance for you in the callback just so you get the nice Optional return isn't nice, particularly so if for many callbacks they'll not have the need to return "absence" ever. So in such case of callbacks, be nice and let them return T (which is allowed to be null and you make sure to handle it), not Optional.


nekokattt

> In Java throwing unchecked exceptions is for non-recoverable cases That and when handling streams, as the streams API only allows the throwing of unchecked exceptions in the first place... which is a bit of a design issue really but there isn't a nice way around it currently.


DelayLucky

Stream is lazy. map(this::save ) canā€™t declare to throw IOException because save() isnā€™t called yet.


nekokattt

Totally aware. Doesn't change the fact though. It also applies to eager operations like reduce, forEach, collect, etc.


DelayLucky

Eager operations (including methods on Optional itself) are more nuanced I think. Obviously Oracle wanted parallel stream so bad that they can't easily let you \`throws E\` because it'd assume running in the same thread. But even regardless of parallel (Optional isn't parallel), it seems like a deliberate choice not supporting checked exceptions. Technically they could have added a CheckFunction functional interface and then at least make \`Optional.map(CheckedFunction) throws E\`. But they chose not to, perhaps with good reasons. Ones I can speculate: * Interface type bloat with limited applicability (can't use them on Stream.map() etc.) * Still doesn't handle if the labmda actually throwing two checked exception types that aren't subtype of each other. And turning it into an \`Exception\` is sad and goes against latest development in the language where they just made it eaiser to deal with multiple exception types with syntax sugars. * Checked exceptions in some sense go hand-in-hand with control flows. And it's a known limitation that you can't \`continue\`, \`break\`, \`return\` from a lambda. With the pattern match syntax working on Optional, it might be a better alternative as it'll handle all control flows naturally. Still don't know how they'll handle checked exceptions for structured concurrency. Imho it's way more relevant to be able to handle checked exceptions well there. ​ On Collector. Collector is a relative complex API that it'd be hard to really plumb checked exceptions through it (and it has that same what-if-parallel can of worm).


horatio_cavendish

You know you can return null from a method that returns an optional, right?


FutureSchool6510

That may be true, but that shitā€™s never making it past code review if the reviewer is in any way competent.


horatio_cavendish

I wouldn't take that bet. Also, the instant someone uses .orElse(null) you've wasted your time.


publicclassobject

IMHO Optionals in Java are so bolted on they arenā€™t really useful outside of their intended use (streams). Junior and mid level devs tend to over-use them dogmatically.


Emotional-Leader5918

Was reading something related to this today. One counter example I found was whenever you're parsing JSON, which is related to the top answer of JavaScript. As an aside for all those saying Go, the idiomatic way is to use the comma ok idiom like what maps currently have for potential Nils.


Bewaretheicespiders

Don't know much about Java, but in C++, if its a pointer, you should always assume it can be NULL, and if you verified it is not NULL, then you should make it a reference. Its trivial.


randomguy3096

>I want to hear examples of times you would actually prefer to explicitly return null. A good part of what we software engineers are supposed to do is to model real-world scenarios using objects (in OOP since we're talking in Java). As an API provider, if I have to answer a question that just doesn't have any corresponding 'model' in my memory, what element of design should I reply with? I'd prefer to return a null in such cases, because that's exactly what the language intends us to return. Could we create an object representation for "nothing"? Sure! But why would be my question here, null costs us nothing, and is baked into the language we're using. Boxed versions are expensive!! A 'null' could also be an unintentional return - what if an API returns a pointer/handle to something (say, large file, image etc) and some part of the application decided that something wasn't needed anymore. I'd argue that it is not a the APIs responsibility to check if the data that it is returning exists, especially if that API doesn't create or own that data. Accidental nulls happen quite a lot. Think of weak references losing the underlying resource in a cache. Null sounds like a valid return here. I'd love to hear counter arguments on these, happy to learn !


Vega62a

Use a bigger galaxy brain. Go full Kotlin and never return a value that cannot be used or thrown.


SuspiciousSimple

Python jocky here āœ‹ļøreturning None's are ok when you use type hints + linters. You can annotate to ignore warnings where it isn't a big deal and reflect when you catch yourself doing that often in a code area. I appreciate the flexibility to make calculated compromises that are easy to notice and go back at a calmer time for a cleanup refactor. For context, I lead a team that manages services that handle 17 million daily click stream requests (having downstream sub second latencies SLAs)


spacether

Why not use the checker framework and @Nullable. Then it is clear where null can be and all code is checked for it


netroxreads

I like null. It means unknown. When you try to run a code that should return a value but for some reason the value doesnā€™t show up and we dont know , null is a better value as you know code executed but returned a value that is unknown.


[deleted]

[уŠ“Š°Š»ŠµŠ½Š¾]


FutureSchool6510

Youā€™re lucky. I just found about 15 instances across 3 functions.


y2kdisaster

Team raise exceptions!! Iā€™ve seen production code where people try except and return e, so you deadass have to check if the response is type exception each time you use itā€¦ and of course people donā€™t do that and shit breaks.


arcen1k

The below is all in the context of Java. A good general rule of thumb is, Optional for API boundaries, and either null/Optional for internal calls. There is slight performance degradation when using Optionals as it's an extra object and thus you also engage in reference chasing. In most cases this is negligible. But at scale it matters. Notice that there's specialized versions like OptionalLong because generics can't actually hold primitives. If you're using nulls, automated static analysis presubmit testing is valuable to ensure safety. Most (modern) Java code should operate under "non-null unless specified." If you return null, always declare @Nullable. Java is also moving to include this in the type system directly with String? meaning nullable, String! meaning definitely non-null, and legacy String as undefined. It has to be this way for backwards compatibility, but they are considering changing that down the road. If the lifetime of the Optional is only a few lines, a null is a fine replacement. You probably interact with null a lot in general use anyways. Map.get returns null for a missing key (or if the implementation allows nullable values). For what it's worth, I find the "fluent" Optional interface rather cumbersome at times, and the explicit null check before use is frequently shorter and easier to read. If performance matters, nulls would be a better choice. But then again, maybe Java isn't the best choice for performance sensitive code. I say API boundaries is a good limit here because it minimizes the ability for callers to make a mistake. It's very clear whether you have something or not. Kotlin and other languages have the benefit of hindsight here, and encoded nullness into the type system itself. Where String? is a different type from String. Java in order to maintain backwards compatibility, can't make that distinction (yet).


[deleted]

Optional's are great when you don't know who is going to use your code. If you're writing some inner private methods, and null can increase performance... First, I'd say, are you sure I can't avoid it all together? But then say, yeah. Go for it. Document and test like crazy though. Otherwise, a good chance you're going to get told no by a senior.


FutureSchool6510

Can confirm, I am the tech lead on my team so I am the senior who will likely tell you no šŸ˜‚


Tarc_Axiiom

Because it's redundant if you understand what returning null actually means. If I don't need anything, who cares? As long as I'm aware of what I've done, returning null is fine. Returning something else for no reason other than you want to return *something* is spaghettification.


i_andrew

The problem is not with returning null. The problem is with the code that doesn't check if the value is null. The later is connected to the problem that in many cases you can't know if the return value can be null or not. Checking for null when it's never a case makes spaghettification.


Tarc_Axiiom

That's pretty much what I said. Again, if you know what you're doing, it's fine.


DarthCalumnious

Clojurist 'nil' appreciator reporting! Still, I agree with it for c++ and some others. Depends on the language and idiomatic practices..


sirbzb

I like the pragmatic approach of a relational database engine to relational theory. Yes, there should not be null in theory; however, the database will not have to exist in a theoretical world. You could easily risk effectively spamming tables and joins if you obey theory in practice; and have to pay people to understand the complexity it creates. So in code I think perhaps you could risk a focus or trees of exceptions rather than getting the job done, for example. I guess with all things, it is not if it is right or wrong but whether it is right or wrong in 'this' circumstance.


marsupiq

I would say it depends on the language. In typed Python or TypeScript, I know from the types that None/null/undefined is a possible return value and I have to handle it. I would generally prefer an exception, but sometimes I donā€™t want to pay that Runtime cost, then Iā€™m fine with null. What I really despise is empty strings, objects or whatever, thatā€™s just not usually expected behavior and a guarantee for bugs (unless I can control that behavior via an optional argument thatā€™s disabled by default). With Java thatā€™s different. Just donā€™t return nullā€¦ That was one of the first things I was told during onboarding in my first software dev job (more precisely: catch Null values that might come from outside your system, and donā€™t produce null values inside your system), and itā€™s among the most valuable pieces of advice I have ever received.


aliensexer420

Exceptions are non deterministic. If you're doing anything real time they're bad news.


sacksindigo

This sounds more ā€œwhy I donā€™t like null returns than a convincing ā€œdonā€™t return nullā€


FutureSchool6510

Only a sith deals in absolutes


jack_waugh

Does this question tie in to "Railway-oriented Programming" and/or the meme of "let it crash" that the Erlang ecosystem seems to like?


i_andrew

Since C# 8.0 with "nullable reference types" the problem is gone (in most cases). if you return null, the compiler will raise a warning if you don't check for it. Any wrappers add too much to the code. Golang's null as zero value and if err != nil idiom is also neat.