|
But I cant believe how much dialog is created down below. I have done quite a bit of C#, and done fair amount of Scala now. I love Option type in Scala and love that it is also a Functor/Monad and I can rely on it having a bias towards success path (Some(x) in Scala).
Only thing missing for me in C# is pattern matching, then it would be of great use
This is nice Option lib for C# : GitHub - nlkl/Optional: A robust option type for C#
For me this is a good article, and I completely see where you were coming from.
I gave it a 5
|
|
|
|
|
Well-written article. I think optional is an OK way to handle nulls and I believe the disambiguation of an interface is valuable. Since most nulls come from a database the code can contain null references within the database access code. I like to return a Boolean and an out parameter for a nullable object to avoid explicit testing for null.
|
|
|
|
|
I don't like this way in handling nulls. It blows up the code and makes it more complicated. When i guess there would be a null in return then i have to check it in the first place or provide a save way in check that the returned value will not be null otherwise the run time SHOULD crash because we do not expect this value to be null and that is ok. Each method has its own purpose. Take the Linq extensions from C#, they have a FirstOrDefault and a First . We can expect that FirstOrDefault could return a null|default value so we have to be aware that this could happen, First ensures that the will always be a value or an exception will be thrown. Fmpov this is the right way in handling this. When we expect a method to be return null, we have to be aware of it. Otherwise we have to create a method that ensures that!
a findUser method should considered to be returning in invalid value so each developer has always to be aware of the output. A findUserOrDefault method not.
Null or not null this is the question, at least we have to be aware of the fact that every ref could be null so the usage of an extra type for this case is imo not necessary.
|
|
|
|
|
"When i guess there would be a null in return then i have to check it...otherwise the run time SHOULD crash".
Imagine a perfect world: you wouldn't need to guess, you would just know. Your runtime wouldn't crash, you would get a compile error before your code even gets there. Would you consider that as an improvement to the scenario you described?
fizz().foo() // won't compile, fizz() returns Optional
bazz().foo() // will compile, and will never crash on you: bazz doesn't return Optional
"It blows up the code and makes it more complicated."
Based on the assumption that most your values are not nullable, you only apply it to those selected few places (if that assumption is not true, it's really a lot of noise as you perceived it). It tends to reduce the amount of code actually in practice. You can try refactoring the last set of code examples in the article - do the identical thing using null references.
For a real world experience, you can take a look at one of these APIs:
http://google.github.io/guava/releases/snapshot/api/docs/com/google/common/collect/FluentIterable.html
https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html
Just a quick glance on method signatures will tell you what will surely return a value and what might not. Not only you won't need to guess or read the documentation / implementation for this information, the compiler will - in most cases at least - stop you if you try to use those Optional values directly.
|
|
|
|
|
Quote: When someone uses that method, things can go wrong in several ways
All three reasons sucked from the... um... finger. Null is the one best option to handle "not found" case.
|
|
|
|
|
Most developers fingers contain those problems actually. Check the opinion of Tony Hoare - the inventor of null reference - on the subject.
Stamping things as "the one best solution" makes life convenient but it's limiting. You can surely think of scenarios when you need to communicate nullability on your interface. You can do that in many ways, comments, annotations, etc. The solution with option type wrapping has the property of being (almost) compiler safe, and has some useful syntax especially for functional programming.
It's why it's so much used in things like google's guava or java8. It's not just "dummy" stuff.
|
|
|
|
|
mrcellux wrote: the inventor of null reference Disputed.
Missing the null-object pattern, missing the benefits of having a null, missing a lot; at the moment it is just an article of "if not null then".
mrcellux wrote: You can surely think of scenarios when you need to communicate nullability on your interface. Anything that is a reference can be null. No need to communicate the obvious, and stop mixing up business-requirements with coding-conventions. The "null" thingy isn't there to communicate a business need about optionality
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
|
|
|
|
|
C was an improvement over assembly language, due to abstractions (syntax) of program flow and storage. These abstractions better communicated the programs intent to the programmers involved. Structure could also be enforced to some degree. C++ improved this further by allowing for encapsulation. This forced programmers to use resources correctly. As a result, the number of bugs decreased.
Although I like the new C# conditional operator, I like ideas like "Optional" even more, because it represents an extension of abstraction. In code, you clearly mark the object as "Optional," showing and enforcing clearly that the value could be simply not present. Null is too general, because every reference could be null.
Currently, I use null to mean optional. Truly "?" is just a wrapper for "Nullable<>." But sometimes the type should never be null and so, my use is ambiguous. Nullable also only works for value types. What about reference types?
"Optional" could be the equivalent to "Nullable" for reference types.
Note: I have, up to this point, been using Resharper to fix my null reference issues. However, not everyone has Resharper. With "Optional" I could eliminate all those checks for null and simply perform a "Debug.Assert()" check on reference types which should never be null.
-- modified 27-Nov-15 9:59am.
|
|
|
|
|
Your compiler is not there to model business-needs.
MuThink wrote: But sometimes the type should never be null and so, my use is ambiguous. Nullable also only works for value types. What about reference types? What about them?
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
|
|
|
|
|
There is a reason why microsoft used the convention:
bool TryParse(string value, out result)
It quite clearly indicates to you whether it succeeded or not, and allows you to capture the value if it does. If the only point you are trying to make is that the interface doesn't explicitly tell you whether null is supported then why not use a syntax that does support it properly?
Your solution is inelegant, over bloated, creates additional unnecessary classes and is not in line with the standards of the language itself.
|
|
|
|
|
We're discussing generic API design in the context of absent values. Please don't misunderstand what I'm about to say, in specific parsing scenarios, this TryParse may be a good design choice.
To address absent values in general though, this specific implementation is not ideal, I would dare say inelegant - to use your word. The reasons why:
- it returns a bool, not the result you're interested in. you also lose the ability to chain method calls
- it forces you to handle the absent value immediately - or wrap and propagate your result together with that bool to allow you to do so later
- you need to create and pass in a mutable object to access your result (this is the biggest issue)
- it requires you to prefix your methods with try to express your intent
The option type btw doesn't need you to create unnecessary classes. A single class for your whole codebase, either included in your language api, a library, or in "worst case" implemented by yourself.
The reason why it's getting more popular is because it's very useful in functional programming. That try-like pattern - the pattern that you proposed - is also hugely useful, but with a different implementation: the either type. Either<Something, SomethingElse>. This is a very robust pattern, you can even use it for error handling, eg Either<Result, Exception>. The option type is actually a convenience - specialization of either type, you can think of it as Either<Something, Void>.
Edit: escaped < and > to make the comment readable
|
|
|
|
|
mrcellux wrote: it returns a bool, not the result you're interested in
You DO realize that ALL control is determined by booleans. Whether directly as a boolean result or by performing an expression that returns a boolean (ie does X == null). So for you to say that it is a reason why it is not elegant is because it cuts directly to the chase and returns the EXACT value you require to control whether a value is absent or not simply shows you fail to understand simple programming.
You have made an arbitrary (and poor) presumption that you MUST return the result you are interested in, which means you are convoluting your original design by stating that it must not only provide a means of controlling whether a value is present, but also return that value, thus you have created the problem you just happen to have a solution for.
That is very poor coding
mrcellux wrote: t forces you to handle the absent value immediately - or wrap and propagate your result together with that bool to allow you to do so later
You cannot have it both ways. You cannot completely contradict yourself in the same sentence by saying it is both bad that you are forced to deal with it immediately, and that you have to wrap it to deal with it later. Why would you even retrieve the value if you did not want to either deal with it immediately OR deal with it later?
Again you are making a very flawed design decision that absent values must support both immediate handling and later handling equally.
Again that is poor coding
mrcellux wrote: ou need to create and pass in a mutable object to access your result (this is the biggest issue)
Can you explain this better, it isn't clear what you mean and I have a feeling you are creating a problem in order to say that it is a problem. You are creating an instance of a class to capture the result (and that is good?) but if you actually store the result in a variable then that is bad?
That makes no sense
mrcellux wrote: it requires you to prefix your methods with try to express your intent
Are you serious??? You are claiming that it is bad to have the names of your methods actually provide you with information about the task it is performing? Weren't you the one going on about how interfaces need to explain what is expected? But now you are complaining that the text "try" is required to express intent???
Seriously... STOP programming. You clearly have no clue about the purpose of method names. You DO understand the need for verbs don't you?
I am sorry, but I stand by my original comment that this solution you have suggested is needlessly bloated, extremely inelegant, it creates problems that it then magically says it can solve, and the "reasons why" a simple solution are not good are all manufactured or just plain convoluted.
If you seriously think someone when coming up with a design says "Mmmm... I need to add 'try' to the front of this method, I know, i will write an entire new class and add an overhead, that is a much better solution that making my method name actually tell me what it is doing"
You have to be joking!
|
|
|
|
|
It seems you're very enthusiastic on providing career advices. Based on your statements you either don't know the following concepts or just ignore them.
- value of immutability
- issues with hungarian annotation (as method prefix)
- preference functions over procedures with out arguments
- generics (or that writing new classes thing is an intended strawman reasoning?)
"I suppose it is tempting, if the only tool you have is a hammer, to treat everything as if it were a nail."
Compare
findUser("foo").ifPresent(user -> mail(user, "bar");
to
Holder<User> userHolder = new Holder<>();
boolean userFound = tryFindUser("foo", userHolder);
if(userFound) {
mail(userHolder.get(), 'bar");
}
modified 25-Nov-15 4:50am.
|
|
|
|
|
mrcellux wrote: value of immutability
Only of value when writing code specifically to be used by external third party sources. If you are writing within your own application then mainly unnecessary... unless of course you dont trust your own code?
mrcellux wrote: issues with hungarian annotation
Are you serious? I was simply using an existing and well known example to highlight a *possible* use. By all means change it to be whatever notation you want. When one of your main 4 points is to complain that the naming of the method should be the reason why the mechanical behavior of the method itself is wrong, you know you clearly are grasping at straws.
mrcellux wrote: preference functions over procedures with out arguments
Highly arbitrary and very specific to the actual problem space being addressed. Perhaps if you were returning multiple complex objects with a single call, or if you were a heavy reflection user and were too lazy to spend the extra time in getting the syntax correct to call the functions, but there isn't anything which would be of significant value to warrant the creation of an entirely new class structure. I can absolutely guarantee you that performance-wise the instantiation of your class would have a higher overhead in both cycles and memory than the choice to use an "out" parameter.
mrcellux wrote: generics
How does generics change the preference of one over the other? It doesn't matter whether I am returning a generic class or passing a generic parameter, they are both equally the same.
mrcellux wrote: "I suppose it is tempting, if the only tool you have is a hammer, to treat everything as if it were a nail."
How interesting you should say that... because when presented with a nail, your choice of tool is a hydraulically powered, carbon nano-fibre, diamond tipped power hammer with a nuclear generator that will continue to strike the nail for the next 50,000 years.
mrcellux wrote: Compare
And here you prove my point perfectly.
You have purposely created an example with a verbose, unnecessary and overly complicated example by which to indicate that your code is better. Not only did you purposely ignore the structure of the example given (and I am overlooking the fact you wrote syntactically bad code, you may want to add a bracket before the semi-colon there and add an "out"), but you have no problem with the creation of additional code but only in the example you are trying to disprove. There is that strawman nuclear hammer again
What is worse, the example you gave completely contradicts all the reasons you previously stated as being the whole point of using your original solution. You dont have any choice in your example, you purposely didn't instantiate the return variable so you could make your code look smaller, but by doing so you have FORCED your own code to deal with the absence of the entity straight away. What's more, I no longer have access to the result as it is now gone.
So nice once... you purposely set up two examples in an attempt to try and make your solution look good, then make sure the examples are vastly different just to make a point.
Very. Poor. Coding
But to correct your mistakes and give a fairly equivalent example
Holder<User> userHolder = findUser("foo");
userHolder.ifPresent(user ->> mail(user, "bar"));
My example (when removing all of your unnecessary bumpf)
Holder<User> userHolder = null;
if ( tryFindUser("foo", out userHolder) )
{
mail(userHolder, "bar");
}
Now the second you need to do something more complex when the value exists, your example falls down as your use of LINQ becomes unweildly with more than a single method call being done, while my control structure becomes necessary.
So the irony here is that YOUR solution very much looks like you have a hammer, and every solution is solved when you make a single method call when you have a value (ie your nail).
Well done
|
|
|
|
|
Hehe. If you consider your code example superior/simpler then we don't have much to talk about. Let's agree to disagree.
That code spaghetti with mutable values, temporal null assignment, out argument presented as the silver bullet recommended way.. God save us from the coding horror of single, declarative statements, and blasphemous paradigms.
Ps: you forgot to grab the user from the holder when you mail. Also you can have multiple statements in that lambda, there is no such limitation you suggest.
modified 26-Nov-15 13:08pm.
|
|
|
|
|
Who ever said my example was superior? And who ever said it was a silver bullet?
In fact I made it very clear I was simply correcting YOUR example which you purposely made to appear worse in order to try and make your own example better (while failing some of the original design considerations YOU actually considered to be of value such as not having to deal with the result immediately).
I know you can have multiple statements in a lambda, but surely even you know that doing so is a last minute cludge for several reasons, the least of which is the scope in which it runs.
Its funny... I thought I made it clear that you use the right tool for the right job, yet TWICE now you have tried to claim that I am pushing some kind of "one solutions fits all", first with the abhorrent hammer analogy, and now by making up your own story about me thinking a bit of corrected code to bring the two examples more on equal footing (and remove your bias) was a silver bullet.
Now if you were talking about the use of event arguments, your solution is basically EXACTLY what is already in place to cover such a paradigm, because the need to send serialized arguments fits the bill exactly. Similarly if you were dealing with a background worker, which takes a single "object" as both parameters and results, I would say your solution is also the best method for the task at hand... but only because both of these things are 40 foot tall nails where you have no choice BUT to align yourself within the mechanism provided, hence your nuclear powered jack hammer works well.
Problem is, YOU are the one presenting your solution as if it fits everything, which I originally pointed out for simple tasks it was horrendously over engineered. Instead of going "Oh I agree, you wouldn't use this for something that simple" you doubled down and tried to exaggerate your solution as being a better fit for everything.
Projection thy name is mrcellux
|
|
|
|
|
Mate, the functional code with the option monad is much better for the problem than the alternative you propose.
There is an article comparing the same things:
The Option Pattern
Something like bool tryParse(something, output) might be a smashing idea for high-scale streaming of the results. Otherwise it's just cumbersome. Try to code in Haskell a bit, it will shape your C# too in good ways.
|
|
|
|
|
Firstly I wasn't suggesting that my solution was the most optimal, I was pointing out the over-engineering of the suggested solution for something as simple as just obtaining a value.
Secondly, when a pattern has to write something like this:
"The worst is that clients may accidentally refer to value when TryGetValue returns false."
It just shows how much they are grasping at straws. People will always write bad code, and they will always make accidents, claiming that the potential for bad code writing as being the reason why using that code isn't good is just pure ignorant.
"Oh don't use the if statement, you might get your equals and not equals mixed up, so the fact you could 'accidentally' compare with the wrong operator means that the if structure is a bad choice"
Its the same thing.
The OPs tried to point out that hungarian notation of the method name was one of the 4 reasons why I was wrong. Are you serious? Its a method name, call it whatever you want, that doesn't change the behavior of the function, and it doesn't mean the function is bad because you named it a certain way.
Like I said... grasping at straws.
At the end of the day, I need to get something, and I need to know if I succeeded or not. Depending on what it is I got, and how detailed the result is for determining if I got it determines WHICH is the better method to use. If all I am getting is an integer value out of a string, then why wouldn't I just use TryParse? If I am attempting to retrieve a patient and there are several known reasons why I could fail, each of which I may want to code separately for then I might return an enumeration, if I need to return several complex structures with a combined return state that may contain several exceptions or errors, then I would possibly use the provided solution in this post... The point is that you use what is most appropriate based on the needs at the time.
THAT was the point I was making. No silver bullets, no one solution fits all, and of course there are other solutions that work better in other situations.
|
|
|
|
|
Tell me the exact problems you see in my code example? Where is it overengineered, where is the bloat, why is it inelegant, why should the developer of that code quit programming, why is it a joke? Your statements. Concretes please, just the code snippet. I used the silvet bullet term because you apparently get angry when you see an alternative different to your usual stuff.
The problem i see with your example a bit more distilled: neither the Holder nor the bool have semantic meaning of their own, they can only be used together. Since the method can only return a single value, you introduce the out parameter as a workaround for that. Since you need both those to be useful, you won't be able to pass it to a field of an object, even passing it to a method is more troublesome. This is why its difficult to delay handling. You have no such problems if you simply utilize the type system to group these two. Very natural thing to do so, and serves an important purpose.
It enables then comply some good principles like side effect free functions, and immutability. Sure, you can continue to violate those 2 principles (arbitrary as you said) but you lose a lot in the process.
Those principles enable you powerful stuff like:
new List<string>({"stan", "pan"})
.Select(name => findUser(name))
.Where(user => user.isPresent()))
.ForEach(user => mail(user, "bar"));
And this is just scratching the surface. Statistically one needs about half the code with such coding style and is less error prone (the research result i read on this was based on java7 - scala comparison)
|
|
|
|
|
1. "Null check is not performed (hasn't been considered or forgotten)"
Which you then immediately follow with "if(user.isPresent())", which by your own admission could not be performed because it wasn't considered or forgotten.
2. "Time is invested in making sure that implementation never returns a null reference.. Then hope for the best that won't change in the future"
Given that you are the creator of the method, and returning a null is valid, why would you have to invest time in making sure it never returns null? Why would you have to "hope for the best" it doesn't change in the future? How is that any different from someone "hoping for the best" that you dont completely change your structure for Optional<> in the future or change the method calls on it?
3. "Null check is done speculatively, even if it's not needed"
But its ok to use LinQ to perform .Select and .Where "even if its not needed"?
So from your original 3 reasons as to why your solution is better than existing solutions, you have either done the very thing you are saying is wrong with existing solutions, or you have simply replaced one "the developer may write bad code" with a different "the developer may write bad code".
I dont know how many times I have to keep saying this. ALL I did with YOUR example was to try and remove YOUR bias, by removing the superfluous code that you added on purpose to try and make your example look better.
mrcellux wrote: This is why its difficult to delay handling
He says while providing an example that FORCES you to handle it immediately, with absolutely no provision to delay the handling.
Well done!
The only reason I "get angry" as you put it is the sheer hypocrisy and contradiction where you seem to set up these fictitious reasons why something is bad and then violate them yourself in the very next sentence. If "delaying handling" is something you decide is valuable, then why are all your examples completely ignoring the ability to do this? Why are you making a point of showing verbose examples as being bad when the only way to delay handling is to do the very thing you say is bad?
And as I also keep saying, your "powerful stuff" is completely and utterly bloated overkill if all I want to do is parse a simple value. You keep harping on about immutability and claiming I am "violating" it, yet I explained to you that immutability serves a purpose for a reason. If I were to use Entity framework I CANNOT make my data models immutable, it requires them to be changeable in order to load the classes. Does that automatically mean it is "violating the principle" and is therefore bad?
YOU have decided that immutability is a show stopper in ALL circumstances, but look at your very own example. The only think "immutable" about it is that I cannot change the "isPresent" from being true to false (which nobody would ever want to do) and I cannot change the "user" that it relates to (which again I nobody would ever want to do). So immutability is a completely moot point in your example. The only way in which a lack of immutability would be a problem here is if people are purposely writing malicious code.
Are you always so paranoid about your own developers?
"Statistically", you only need about half the code when you write exactly what you want in exactly the way you want for exactly the purpose you want it. So by all means, write an article stating that here is a solution for one very specific problem, and I would totally agree with you (as I said before, event args and background worker parameters/responses is a good example)... but claim that this is something that should be used "anywhere that can return a null" and I will have to disagree because you violate your own premises with very poor convoluted and arbitrary "problems" you manufacture yourself and then solve with your own solution.
|
|
|
|
|
I asked you to pick apart that one line of code, and show me why is it "bad coding".
You jump now to the article and the new example because you can't do so? About the claims:
1) without ifpresent/get you get compile error. Important difference.
2) you being the author is not given. We don't code alone in a cave, we have to communicate through are apis (even with implementations)
3) the linq code is not needed sure. It just makes things safer, shorter, more declarative. You can do this in assembly if you don't consider that important. I think it's our goal as developers to do the most with the least effort.
I didn't say this should be used everywhere. I show a problem, how it solves it and also show the drawbacks (conclusion section). A pattern is chosen or not based on advantage / drawback ratio.
But all that aside, can you do me a favor of talking about a very single thing?
Please return to the original one line of code:
findUser("foo").ifPresent(user -> mail(user, "bar");
You said things like "you have no problem with the creation of additional code", "Very. Poor. Coding". Support your claim of bad code. Shoot. Or is it not bad?
|
|
|
|
|
mrcellux wrote: You jump now to the article and the new example because you can't do so?
Who was the one making the point that being able to delay handling was necessary? So I pointed you to your article which stated this. So "picking apart that one line of code" included the fact that based on YOUR words of what was important, you are not allowing for delayed processing.
That was my issue with your purposefully bias representation of the examples. You went out of your way to make the example supporting your own view as succinct, and then purposely wrote the other example verbosely and grossly bloated just to make a point.
Either delayed processing IS important, or it is not, and if you are going to give examples to illustrate that, then BOTH examples should illustrate that.
I also believe that I did point out how your example is limited in your use of linq. Clearly you have never debugged through a ForEach statement before, or you would understand this, and clearly you have never bothered looking at an exception that is thrown by code inside a ForEach loop either. Your example forces the processing of all items without any capability for handling individual failures.
mrcellux wrote: 1) without ifpresent/get you get compile error. Important difference.
Are you being purposely dense? seriously... Do you honestly think I am talking about removing code which makes it not compile and putting that forward as a valid option? Seriously mate, you come up with some completely insane rebuttals some times. First you argued that Hungarian notation is one of the main reasons that the mechanical behavior of a solution was wrong, NOW you are using inability to compile by making the stupid presumption that what I meant was to just remove code and have it fail.
Is that really your #1 response? A compile error. That is your hands down show stopper of a response?
mrcellux wrote: 2) you being the author is not given. We don't code alone in a cave, we have to communicate through are apis (even with implementations)
And yet another completely useless comment. What on earth does this mean? If you are trying to say that our code needs to explain what it does, I dont see how I wasn't explaining that. Heck, your whole original argument was that null wasn't explicitly indicated in the syntax of the method, which is why I gave you an existing example that does, and I could come up with dozens of others which still don't need your bloated and overweight poor "generic" solution.
mrcellux wrote: 3) the linq code is not needed sure. It just makes things safer, shorter, more declarative
No, you used it specifically to try and make your example look better, which is why you went out of your way to add extra lines of code in the alternate example. Do you really have to go that far out of your way to try and make your solution look good? Shouldn't it just stand on its own two feet?
Seriously, all you needed to do in the beginning was say "sure, if all you need is just a single value then my solution is complete overkill. I stand corrected, my solution isn't for all situations, it is more geared towards those places where you dont have a choice and where you have a need to return more complex data", and I would have been happy. But as I said before, you just doubled down and acted like your solution does everything.
I even handed you a fricken bone and told you that things like event args or background worker request/response classes your solution would be perfect, because in those cases you are FORCED to use only a single object to convey all the information you require... but oh no... dont ever take a step back and correct yourself. Instead, just soldier on, push forward and quote stupid things like "it wont compile if I remove code"
mrcellux wrote: I didn't say this should be used everywhere
Really? I re-read the article looking for ANYWHERE you actually mentioned where this solution should be used and I couldn't find any. What i did find however were lots of "commonly used", "many languages", "many contexts", "an alternative", "with consistent use".... So I am sorry, but failing to explicitly say something doesn't mean you didn't more than imply it with how common and generic you are claiming it is. Even when given the opportunity to clarify it when I pointed it out, instead of going "oh you are right, it shouldn't be used in most cases" you just doubled down again. So even now that you are making a point of NOT saying it should be used everywhere.... you still dont say that it shouldn't be used everywhere.
mrcellux wrote: and also show the drawbacks (conclusion section).
It is interesting you should use the word "drawback". It is only mentioned ONCE in the entire article, and that is to describe the problem you are solving.
But here is your disadvantages:
"Disadvantages? In most cases there aren't, but as to everything there are exceptions. The Optional is a heap object, this needs to be considered in extreme cases. There may be specific scenarios where such practice doesn't deliver real value or is impractical"
Wow... "in MOST cases"... but that sounds like the vast majority of cases SHOULD use this. "Extreme Cases", so just wanting an integer is an extreme case? Wanting a simple object is an extreme case?
Honestly, if you are going to write articles, you need to NOT pat yourself on the back so much and slant everything towards your own solution being some holy grail.
mrcellux wrote: Shoot. Or is it not bad?
I have already been over this a dozen times, and I have even explained it further above, which I have done so many times previously. But what the heck, let me go even deeper into pulling this to pieces.
ifPresent
What an awesome little piece of code. You DO know what the code inside this method is don't you? You do understand the internal compiler directive which performs the is null check and then conditionally executes the next line of code when it exists. So you DO actually realize that anyone can write their own extension function that takes in an expression and performs EXACTLY the same as this. So sorry, you dont get to take credit for other people's coding.
LinQ
You are aware of the overhead of using Linq aren't you? The memory requirements of setting up a functional expression? You are setting up an additional overhead of having to create additional classes for no other reason than to support the Linq interface to make one line of code look pretty. You would achieve this with far less memory and far fewer cycles by simply performing your own null check and then only execute if it exists. Sure it is a few more lines, but doing something PURELY for the code to look good is as I say VERY.POOR.CODING. When it is more important for you to make that line pretty than to think about how the code itself will run and how it will function is bad.
Exception Handling
Said it above, but will repeat it here in case you missed it like all the other times I have spelt out problems. There is no means of handling errors from within Linq statements, you ave not given any indication of where the problem is within the stack trace, and you cannot manage the exception. I noticed that you purposely reduced your example now to leave out the ForEach, which would have caused an even greater problem with handling exceptions. That is VERY.POOR.CODING.
But here is your chance... despite all of this, and you doubling down. Here is your opportunity to explicitly state when this should and shouldn't be used, perhaps even changing the article to reflect this instead of making it sound like there are very few "extreme" cases where it shouldn't be used.
Or are you so protective of your little piece of code that you care more about how it looks than it being correct?
|
|
|
|
|
Cool, this article from 2007 is about the exact same thing as this strangely pointless comment thread here.
|
|
|
|
|
Yes, this is old stuff. You're wasting your time with your comments. That enigma bloke is not interested in discussing consequences of patterns, just wants to be right. You can see that from mile away when someone takes the piss on fundamental design principles in the effort.
|
|
|
|
|
If I just want to be right, then why would I be giving him examples of where his solution would be of use? Why would I be pointing out his lack of scoping it correctly?
I have said it before, if he said this was to only be used in certain instances, rather than make it sound like it is a magic bullet that solves everything and that only 'extreme cases' are outside of it (which is just lip service), then I would not have an issue.
If he didn't purposely make bias examples that are not even functionally equivalent to make a point, and then break his own stated rules of "delayed processing" then I wouldn't have a problem.
I am not taking the piss on fundamental design principles, I am taking the piss out of someone who quotes them poorly, then solves the very problem he creates in the first place.
Show me one design principle I am pissing on?
|
|
|
|
|