Applying the Gestalt Principles to Code
yetanotherchris.dev
yetanotherchris.dev
There was one numerical project I worked on where I had these _x and _y suffixes showing up very frequently in identifiers. Having the code vertically aligned actually made spotting copy paste bugs very easy because you can trace the vertical and find all _x’s lumped together or whatever the case may be. Inconsistencies stood out more readily I want to say.
One thing I try to do with the visual aspect of my code is to organize things semantically when possible with a good clear comment that tersely covers the operation: initialize abc, validate xyz, calculate, compute, guard clause: ignore case 1, load config, override X, etc
I suspect that the impact on the lexer is negligible.
Of course, as every Lisp programmer knows, programs represented in almost any high-level language are actually trees, and to force them into a 2D grid of symbols is rather unnatural and awkward. Specifically, almost all 2D grids of symbols are lexically or syntactically invalid programs, and many natural source code transformations require either manual labor or special support from the editor.
some_object.some_method((p, q) =>
{
do_things()
})
while the right way of doing this clearly is some_object.some_method(
(p, q) =>
{
do_things()
})
The 'broken lambda' that one tends to see everywhere is driving me nuts.The principle is that code already should give the right impression of what is going on at the first glance. Another thing that is quite a spectacular failure in this regard is the google style guide. The indents of 2 tabs combined with braces that do not line up must have been optimized to be as unreadable as possible.
some_object.some_method((p, q) => {
do_things()
})
Your preferred version has way too much useless whitespace.That would also help with one of the main arguments against "visual" programming languages - they get too hard to read as programs get larger. Simply don't allow scrolling or zooming the source.
public void shittyLongFunctionPart1(...) { //First line of screen 1
..
..
shittyLongFunctionPart2(...);
}//last line of screen 1
public void shittyLongFunctionPart2(...) { //First line of screen 2
..
..
shittyLongFunctionPart3(...);
}//last line of screen 2
Yet another example of culture trumping process. At the end of the day you need developers who give enough of a shit about their craft to write readable/testable/maintainable code. And that sucks because it seems relatively rare.But this is easily hackable around. What you really want is a programming language that does not allow functions longer than 25 lines.
Anyway then you would get stuck policing exactly how long a "line" is, do comments count, etc...
A line is 80 characters. Indent is 8 spaces. Comments do not count.
https://www.kernel.org/doc/html/latest/_sources/process/codi...
https://wiki.musl-libc.org/coding-style.html
https://www.freebsd.org/cgi/man.cgi?query=style&sektion=9
https://man.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man9...
Just like written code, you need to create higher level abstractions. In simulink for example, you might have 1 top level box called a "Radar". You drill down into that, and find lower level components like an RF transmitter, but still those are abstractions that you can drill down into [0]
Yes if you squeezed all low level implementation onto one screen it'd be hard to read, but same as if you put all low level c code in one giant file without any abstractions.
[0] https://www.mathworks.com/help/examples/simrf/win64/RadarSys...
Not sure this is the type of article for juniors. I don't think it's really a handbook for writing more pleasing code. It's more a statement, that the way we structure and style our code is a design decision. Code's visual design is an area that many programming languages have experimented with mostly over trial and error, but it's not something that is well studied.
New programming languages come out all the time, and they often tout advantages such as speed or security, but they rarely try to justify design decisions based on visual design and readability. It seems like a ripe field to dive deeper into.
Most definitely. I worded that poorly. I meant "my juniors" as in those with less experience than I, but not fresh out of the oven devs.
I'm not sure if it's the right word but I've taken to using the word "locality", since it has prior usage in a similar concept in https://en.wikipedia.org/wiki/Locality_of_reference
Of course, coders' tendency to nest breaks the idea a bit on levels deeper than a method. Though I think with a lot of fiddling some variation can still be achieved.
Being a mere moral, I must consult the code to find an answer.
This does not mean that 90% of your time is spend reading code. There are other tasks that programmers do during their day.
I would say that the 90% number sounds roughly true for me. And probably I read my own code somewhat less than that, but spend more time reading others’ code, either due to code reviews or just to understand things before making changes to existing systems.
At the moment I'm reading https://github.com/golang/go/blob/master/src/encoding/json/e... to diagnose a problem in my code.
Overall, the readability is good. My only complaint is the terse variable names, which makes the more complex methods more time consuming to follow (because you have to keep going back to refer to their definitions to remember what they are). For example, https://github.com/golang/go/blob/master/src/encoding/json/e...
When you dive into the code, especially at the point I chose, you are presented with:
e.string(kv.s, opts.escapeHTML)
And so, you have the following questions: What is e? What is kv? What is s in kv? To answer these, you have to scan upwards. e is encodeState. OK, not too bad. kv is maybe key-value of something? it comes from sv (string value maybe?), which comes from: sv := make([]reflectWithString, len(keys))
So a string value? Or a list of string keys? A list of structs, OK. s might be a string value inside, which has ... some meaning I guess? Digging around, I see it defined as: type reflectWithString struct {
v reflect.Value
s string
}
So it is a string, but I still don't know what its purpose is. After a bunch of digging around to see how it's used, it looks like s is a string representation of the value, but I'd need to look over more code to be 100% sure.Now, contrast this with:
encoderState.string(keyValue.asString, opts.escapeHTML)
Now I know what this calling string() on the encoder state, using the string representation of the key value. "string" is still a bit cryptic. It could be renamed. Looking inside "string" I see that it's writing things, so maybe a better name is: encoderState.writeString(keyValue.asString, opts.escapeHTML)
With this version, I know without having to look at any other lines that this code is supposed to write the string representation of a key value to the encoder state, doing HTML escapes. I don't need to look inside the guts of anything to figure this out. I don't even have to leave this line.This is code U/X.
I do prefer method names to be descriptive, so verbs are nice. Well, unless we are dealing with very generic lambda code, then there might not be better options beyond f, g, and p.
A great example of this is "i" as a standard indexer, or "x" and "y" as horizontal and vertical coordinates. They are used often therefore terseness can be applied and is useful. Also why "KV" is often used to be mean key-value, the concept is just very pervasive. The terseness for variable names in the linked to code seems more acceptable because those variables of consistency and repeated usage.
It's also generally a good sign if you spend less time writing code, because the hard part is usually in the design/planning phase of a new system or product. Days of programming saves hours of planning.
But it felt like quite a productive week: they were the "right" four classes, and I could have written a lot more code that did the job less concisely.
We also do team code reviews on a big screen over pizza twice a month. It gives a chance for the entire team to learn something new without being under pressure. So yea, lots of reading happens around here. The side-effect is some pretty good (and readable) code IMHO.
The more experienced I become, the less time I spend writing code and the more time I spend thinking about it and drawing diagrams on paper.
Coding should not be the bottleneck. The bottleneck should be deciding what solution to choose because there are usually a lot of factors to consider and it takes a while to identify all the main ones. It's not unusual for me to spend multiple days just thinking through different technical solutions without writing any code.
IMO developers who commit often and too many lines are juniors. Most of these lines will have to be rewritten because there wasn't enough thought behind them.
Of course, there are many kinds of valid working styles in between. I personally would rather see juniors write, make mistakes, and rewrite than just be paralyzed with thought/planning anxiety, which is perhaps more effective for more experienced developers.
(We could do with a serious version of "thedailywtf" for interesting debugging stories, I think it would open a few eyes)
It's been a ramp up of course, starting with a totally blank codebase, I started with 100% of time "writing" code (quotes meaning : thinking about and then actually writing, I assume it goes together).