On Wed, 18 Nov 2015 10:13:45 +0100
Stefan Hundhammer <shundhammer(a)suse.de> wrote:
On 18.11.2015 09:56, Josef Reidinger wrote:
And to be honest it can happen in any code in any
language ( just
depending how often it can happen ).
Any halfway decent parser will realize that in one case you do return
something from your function, and in another you don't. That's what
Preciselly speak you always return something. Just maybe default value
for return is not so common in other languages. I know that e.g. C++
can check it during compilation, but ruby is not compiled, so in the
end, you in both cases ends up with runtime error or error catched by
Better yet, if you have to DECLARE your stuff (functions, variables),
you are making a commitment (or a contract, however you want to name
this) what you are going to do with that thing and what you don't.
And the parser (no matter if it's an interpreter or a compiler) can
catch those problems.
This is discussion between static and dynamic languages and about
explicit types specification. I think there is enough discussion on
internet regarding this stuff and I worry I cannot add anything new
E.g. in ycp one nil can result in cascade of
I really wouldn't call YCP, of all things, a shining example of good
behaviour when it comes to this. Yet, even it had (after years of
painful debugging) static type checking that at least did some
minimal amount of plausibility checks.
What is ruby philosophy how to solve it? Tests.
Do not trust code
that is not tested. Of course some tools can detect some misusage,
but only good tests can prove that code really works.
Tests are good, but they have limits. In particular, when your number
of code paths is too high, the possible permutations just explode.
That's why achieving good test coverage is so difficult.
Thats more phylosophy discussion about egg or the egg problem. Ruby
phylosophy is that if something is not tested ( manually or automatic
), then you cannot believe in code. And with good code design almost
everything can be tested.
Ruby (and the tools in its ecosystem like Rubocop) try to make you
believe that you can easily handle this by dumbing down functions
enough so they become trivial. Well, that would be good - if only
there were a practical way to go through each code path at least once
(better yet, with some permutations of your data set / variables to
test fringe cases in the less frequently taken code paths, too).
well, trivial = single purpose. Actually what you mention already
exists for ruby - https://github.com/mbj/mutant
it tests if you do not
have fake test coverage ( martin played with it in past ). Regarding
automatic tool to go thrue all path, it is still not enough as
1) that tool need to know behavior, sometimes exception is correct
2) need to verify it do what is expected, just passing function without
exception is not enough
But as seen in this example, this is often not practical. If your
code depends on the status of things beyond your immediate control,
you'd have to mock all that. In this particular case, who would have
foreseen that a seemingly unrelated scenario like having a RAID on
the previous installation might lead to such a crash?
If it happen first time like in this case I usually capture target map
( as hand crafting target map is pain ) and then write at least
regression test, that I know that covering this case.
Sure, better test coverage might have caught this. But it would have
been even simpler (very much simpler!) to have the parser throw an
error if the code is inconsistent - like not returning a value in
this case if in the other case it does.
It is question if you are on side at least have some check or having
good tests that verify working solution. Again it is part of mandatory
types discussion topic.
And to cut the reply that immediately comes to mind short: If in some
pathological case I want the code to return 'nil', I can explicitly
make it return 'nil'.
On other hand there is many cases where nil is nature return code like
in each, find, etc. So for language authors it can mean to use specific
statement for other loops or be consistent, which can cause troubles.
IMHO there is no real excuse for the Ruby parser to behave this dumb.
They just became collateral damage of their own "anything goes"
I agree that faster failure during runtime will be better, but there
can be maybe code that use this code path.
To unsubscribe, e-mail: yast-devel+unsubscribe(a)opensuse.org
To contact the owner, e-mail: yast-devel+owner(a)opensuse.org