If you felt compelled to expand a one liner like
a = F(G1(H1(b1), H2(b2)), G2(c1));
I wouldn't blame you. That's not only hard to read, it's hard to debug.
Why?
- It's dense
- Some debuggers will only highlight the whole thing at once
- It's free of descriptive names
If you expand it with intermediate results you get
var result_h1 = H1(b1);
var result_h2 = H2(b2);
var result_g1 = G1(result_h1, result_h2);
var result_g2 = G2(c1);
var a = F(result_g1, result_g2);
and it's still hard to read. Why? It solves two of the problems and introduces a fourth:
It's dense
Some debuggers will only highlight the whole thing at once
- It's free of descriptive names
- It's cluttered with non-descriptive names
If you expand it with names that add new, good, semantic meaning, even better! A good name helps me understand.
var temperature = H1(b1);
var humidity = H2(b2);
var precipitation = G1(temperature, humidity);
var dewPoint = G2(c1);
var forecast = F(precipitation, dewPoint);
Now at least this tells a story. It fixes the problems and is clearly better than anything else offered here but it requires you to come up with the names.
If you do it with meaningless names like result_this
and result_that
because you simply can't think of good names then I'd really prefer you spare us the meaningless name clutter and expand it using some good old whitespace:
int a =
F(
G1(
H1(b1),
H2(b2)
),
G2(c1)
)
;
It's just as readable, if not more so, than the one with the meaningless result names (not that these function names are that great).
It's dense
Some debuggers will only highlight the whole thing at once
- It's free of descriptive names
It's cluttered with non-descriptive names
When you can't think of good names, that's as good as it gets.
For some reason debuggers love new lines so you should find that debugging this isn't difficult:
If that's not enough, imagine G2()
was called in more than one place and then this happened:
Exception in thread "main" java.lang.NullPointerException
at composition.Example.G2(Example.java:34)
at composition.Example.main(Example.java:18)
I think it's nice that since each G2()
call would be on it's own line, this style takes you directly to the offending call in main.
So please don't use problems 1 and 2 as an excuse to stick us with problem 4. Use good names when you can think of them. Avoid meaningless names when you can't.
Lightness Races in Orbit's comment correctly points out that these functions are artificial and have dead poor names themselves. So here's an example of applying this style to some code from the wild:
var user = db.t_ST_User.Where(_user => string.Compare(domain,
_user.domainName.Trim(), StringComparison.OrdinalIgnoreCase) == 0)
.Where(_user => string.Compare(samAccountName, _user.samAccountName.Trim(),
StringComparison.OrdinalIgnoreCase) == 0).Where(_user => _user.deleted == false)
.FirstOrDefault();
I hate looking at that stream of noise, even when word wrapping isn't needed. Here's how it looks under this style:
var user = db
.t_ST_User
.Where(
_user => string.Compare(
domain,
_user.domainName.Trim(),
StringComparison.OrdinalIgnoreCase
) == 0
)
.Where(
_user => string.Compare(
samAccountName,
_user.samAccountName.Trim(),
StringComparison.OrdinalIgnoreCase
) == 0
)
.Where(_user => _user.deleted == false)
.FirstOrDefault()
;
As you can see, I've found this style works well with the functional code that's moving into the object oriented space. If you can come up with good names to do that in intermediate style then more power to you. Until then I'm using this. But in any case, please, find some way to avoid meaningless result names. They make my eyes hurt.
HX
andGX
invocations may change in the one-liner, as the order of evaluation of function arguments is unspecified. If you for some reason depend on the order of side effects (knowingly or unknowingly) in the invocations, this ”style refactoring” could end up effecting more than just readability/maintenance.result_g1
what you'd actually use or does this value actually represent something with a sensible name; e.g.percentageIncreasePerSecond
. That would actually be my test to decide between the two