|
When I look at some code, I wonder which paragraphs of the law may apply and what the author should be sentenced to.
Before someone screams at me for not being on topic enough: I don't have much of a choice right now.
SUM_Loop: SEX R2
LDN R7 ; get a byte from the ROM
STXD ; push it onto the stack
IRX
GLO R8 ; get the low byte of the current sum
ADD ; add both bytes
PLO R8 ; update R8.0
GHI R8 ; get the high byte of the current sum
ADCI 00H ; add 00H with carry
PHI R8 ; update R8.1
GHI R7 ; are we done?
SDI HI(ROMEnd)
BNZ SUM_Continue
GLO R7
SDI HI(ROMEnd)
BZ SUM_Result
I have lived with several Zen masters - all of them were cats.
His last invention was an evil Lasagna. It didn't kill anyone, and it actually tasted pretty good.
|
|
|
|
|
Some set of unwritten rules in my head - taking into account any possibility of expansion down the line (keep it verbose) or none (one-liners). For example:
The target of a php AJAX call will check for values:
$value = (isset($_REQUEST['value']))?$_REQUEST['value']:some_default; as there's no where to go with this.
On the other hand, an if/else block leaves easy room for expansion - unless, of course, it's amenable to a switch(). And so on.
Ravings en masse^ |
---|
"The difference between genius and stupidity is that genius has its limits." - Albert Einstein | "If you are searching for perfection in others, then you seek disappointment. If you are seek perfection in yourself, then you will find failure." - Balboos HaGadol Mar 2010 |
|
|
|
|
|
I also like each chained call on a new line:
List
.WhenNotEmpty()?
.ForEach(s => s.Prepare(out var r)?
.Manipulate(r));
This code, however raises red flags when if I were to review it:
list.WhenNotEmpty()?.ForEach(s => s.Prepare(out var r)?.Manipulate(r));
Seeing an "out" var inside a ForEach, then doing something with the value smells of side-effects. I know this is a contrived example, but if I saw this, I would take some time to investigate and possibly suggest a way of encapsulating it in a method and ensure no side effects can leak out, or encapsulate the state changes in a return object so it is obvious.
|
|
|
|
|
Yeah, I knew that bit would trigger a few shudders and cringes going in. Not something I would actually do, just felt a little impish when building the example...
|
|
|
|
|
Sentences. I use Linq, extension methods, and fluent style, meaning methods often return this rather than a value, which can be accessed through a getter property if necessary.
And tuples! I love tuples! Again, a useful, common to other languages not just C#, that the juniors have never seen.
The result looks a lot more like F# with its continuation and partial closure syntax.
Sadly, even though the code "reads" easily enough, it boggles the mind of the junior devs.
And the really sad thing is, the junior devs don't even know about the null continuation operator, so the first question I get is, WTF is ?.
As per my previous post, there's dumbing down, and then there's just lobotomy dumb. The null continuation operator is such a nice shorthand vs. cluttering code with if-else statements. So you'll see a lot of my code that looks like GetXmlElement(Constants.MyElement)?.Value ?? Constants.MyElementDefaultValue); but again, the junior devs are totally flustered by the ?. ?? notation.
Oh well, they need to learn. This notation (or equivalent) is common enough in other languages nowadays, so LEARN, GFD!!!!
[edit]And worse, the juniors have never been mentored to NOT code literal strings, so their code is littered with literals. And of course, when something needs changing, you have to search the entire code base for all references.
[edit]
For example, I find this totally readable:
new List<Control>()
{
tbCashDrawerOnes,
tbCashDrawerTwos,
tbCashDrawerFives,
tbCashDrawerTens,
tbCashDrawerTwenties,
tbCashDrawerFifties,
tbCashDrawerHundreds
}.ForEach(ctrl => ctrl.TextChanged += (_, __) => ignoreCashDrawerTextBoxEvents.Else(() => UpdateCashDrawer()));
But it is esoteric, I suppose.
modified 31-May-18 15:02pm.
|
|
|
|
|
Technically:
list.WhenNotEmpty()?.ForEach(s => s.Prepare(out var r)?.Manipulate(r));
Would work as well as:
list.ForEach(s => s.Prepare(out var r)?.Manipulate(r));
Given that an empty list is, well, empty. But again, to rant more about junior devs vs. experienced devs, IMO (as an experienced dev) a list should never be null. It should be empty or have content. But I see so many "if null" checks because nobody initializes their collections in the constructor, for example. And since the juniors are stuck in the dark ages because they don't get training, even:
list?.ForEach(s => s.Prepare(out var r)?.Manipulate(r));
is unknown to them, though I'd still squawk at them for having a null list.
Then again, I've also seen the null continuation operator abused in ways that tell me the programmer really had no right to be writing code: Code Review - What You Can Learn From a Single Line of Code
|
|
|
|
|
|
Richard Deeming wrote: There's one feature of C# 8 you'll like, then!
Quite so. Still, I wonder where they're going with this -- nullable value types are great, and so it makes sense that the complement, non-nullable reference types, should exist, it certainly provides symmetry.
But oh boy, there are going to be thousands of warnings in the code base I work with at work when (if ever) they opt-in for this. But it'll probably be a few years before they get their build systems onto the C# 8, which by then they still will probably be several versions behind, as they are now.
|
|
|
|
|
Interesting comment. I was returning the null to abuse the nullco and short circuit the chain, even though the (actual) list itself isn't null, just empty. But you make a good point about things that shouldn't be null. Returning a null when empty does (though only shortly until the nullco) create a null list. Not using the nullco immediately after would turn a null list loose.
|
|
|
|
|
|
Paragraphs, then collapse all the functions I'm not actively messing around with.
|
|
|
|
|
If you use VS, you can change the formatting parameters depending on who you show the code to: Before showing your code to a code homeopath, you check every single option in the New Lines and Spacing sections and uncheck the Wrapping options. Then go to the closing brace of the file, delete and retype it, and the code is ready for presentation. When you go back to the coding, you set the switches back to your preferences, delete and retype the closing brace.
If you are fond of end-of-line comments, they won't be nicely lined up at column 70 when you show your code in diluted mode. That is usually a minor problem with the homeopaths; the never look beyond column 30 of the source file anyway. Besides, the majority of them are totally unfamiliar with the very concept of end-of-line comments; they put all comments into the huge commment block over every function.
This works fine with C#; I never tried with other languages.
In the old days before we had automatic formatting, and code discussions were based on hardcopy printouts, a nice trick was to print all source code double spaced. I have had homeopaths commenting point to a few specific blank lines telling that I could drop the blank to emphasize that they really go together - never noticing that the entire file had "blank lines" between every printed line - or three or five blank lines.
|
|
|
|
|
In your example:
list.WhenNotEmpty()?.ForEach(s => s.Prepare(out var r)?.Manipulate(r));
The WhenNotEmpty()?. isn't really needed, is it?
|
|
|
|
|
No, not really in this case. Something like .When(predicate) that might have been better. Or following it with something where it did matter.
|
|
|
|
|
I was saying that you can use an empty collection with foreach, which will basically do nothing. You shouldn't need anything there.
|
|
|
|
|
Right. That's what I meant by "following it with something that did matter".
|
|
|
|
|
Ah good, learnt something new first thing in the morning, now the rest for the day.
the this class extensions parameter looks interesting. Might see if can use a bit of it.
thanks
|
|
|
|
|
|
|
The one problem I have with the everything-on-one-line approach style of programming (which I also do a lot) is that it's impossible to debug.
You don't get intermediate values and you don't get to set breakpoints at specific functions.
The readability aspect is not that big of a deal, I can read it just fine (usually).
However, since you write code only once and read and debug it a gazillion times I prefer to write my code so I can step through it.
Sometimes I put it back together for readability afterwards.
For example:
var filtered = myList.Where(...);
var ordered = filtered.OrderBy(...);
var result = ordered.ToList();
return result;
return myList
.Where(...)
.OrderBy(...)
.ToList();
|
|
|
|
|
All that depends on the debugger. E.g. in Visual Studio, if you write your code as
string Foo(int x) {
if (x == 1) return "one";
else return "not one";
} and you only want to break when "one" is returned, mark the statement return "one"; with the mouse and hit F9. It will not break for the "if" tests, but only if the true branch is taken.
|
|
|
|
|
Yeah, but I believe that's a new feature since VS2017
Just like you can now debug in-line lambda's.
It wasn't always like that (and still sometimes isn't).
|
|
|
|
|
This I can parse and validate, at a glance, without trying:
string Foo(int x)
{
if(x == 1)
{
return "one";
}
else
{
return "not one";
}
}
}
This requires me to actually read the words on screen and consciously think about them:
string Foo(this int x) => (x == 1) ? "one" : "not one";
It's not "more clear" on a macro level. It's "more clear" to you personally.
If you were one of my juniors, I'd reprimand you for using an esoteric personal style at work.
If you were a senior colleague, I'd just skip all formalities and just stab you with a kitchen knife.
|
|
|
|
|
Do you really have parsing problems with
string Foo(int x) {
if (x == 1) return "one";
else return "not one";
} This style gives me a third as many source "code lines" to relate to. I can easily overview the entire function. In a larger function, a less whitespaced layout makes it much easier to spot the start/end of loops and condition blocks etc.
|
|
|
|
|
I can parse it line by line at a normal reading speed. Takes about 3-4 seconds the first time I see it.
The initial style I can parse and verify without having to read a single word. Takes me about 250 milliseconds.
The benefit of having spacious functions is that mistakes become embarrassingly easy to spot.
Likewise, properly written functions become very easy to parse, because they look so damn familiar.
I find "less lines of code" a dubious benefit.
A cramped style is more time-consuming to debug, both in terms of setting breakpoints and retracing logged exceptions.
Also, I definitely agree functions should not grow too big.. but stacking multiple logical steps on a single line only gives you the illusion of small functions.
I say: be spacious, let functions grow, and flag them for refactoring if they don't fit on a single page.
The point is to write code that's self-evident +6 months in the future.
Quick to read, amend and fix if need be.
|
|
|
|
|