|
What I've mostly been struggling with during the past decade, was unmaintanable pile of spaghettig mixed with baclava I inherited. So breaking down things into maintainable single-responsibility modules kinda got hammered into my head.
What I struggle with instead, now that I get to build new generations of those systems from scratch, is the usual nerd tendency to overengineer things. "Hey, I just broke down this monster into maintainable modules, but I could break it down even further to serve even more different use cases".
I have to strongly discipline myself, using my conscious willpower to hammer YAGNI, KISS and similar into my brain. I'd say, getting that internalized so I don't have to remind myself is my next milestone.
Well, that and the usual: requirements changing, underspecified requirements with the not-so-techie product manager assuming I know what he means while not bothering telling me what he actually means.
|
|
|
|
|
I also have trouble remembering what I was doing in other modules. My solution is a little different from yours.
I keep a bound and page numbered notebook. In it, I record my thought processes as I break down a problem into solvable units. I repeat this decomposition until I have manageable units, each of which does one thing. At this point, I also plan my error and exception handling.
Then, I review the units. I group all the units that directly act on a given data structure into a single module. Typical entry points to these modules have names such as CreateInstance, DestroyInstance, GetPreviousInstance, GetNextInstance, SerializeInstance, DeSerializeInstance, one or more versions of FormatInstanceForPrinting, GetValueFromInstance, and PutValueIntoInstance, where "Instance" is the name of or shorthand for the given data structure.
All of the input/output routines are placed in one stream dependent module modules. One for the main window. Each subordinate window has their own module, with a separate business logic module. One module for the printer. One module for each file that needs to be read or written. One module for each database accessed.
Next, I review my previous libraries of code. Often, I have an existing module that I can directly use or use with a little rewriting. Some I have used so often, I have created a .dll for each.
Now, I begin writing code. Into the top of each module, I copy the design notes from my notebook into a comment block. First, the missing I/O routines. Then, the main window with its controls, followed by the subordinate windows with their controls. At this point, I can demonstrate the flow of control through the windows to the customer to get their feedback. Lastly, I write the business logic modules and tie the whole program together.
After a little "alpha testing," I ask the customer to provide some real users to do some "beta testing." When the customer is happy, the code is done.
Having the comment blocks in each module refreshes my memory and provides a notebook number and page number to look up my thinking when I wrote the code. This really simplifies code maintenance.
The notebook not only documents my design, but also the problems I encountered and the dead ends I reached while designing the program. It also records where I was at the end of the day or when I have to put the project aside for some dumb meeting or a higher priority task.
__________________
Lord, grant me the serenity to accept that there are some things I just can’t keep up with, the determination to keep up with the things I must keep up with, and the wisdom to find a good RSS feed from someone who keeps up with what I’d like to, but just don’t have the damn bandwidth to handle right now.
© 2009, Rex Hammock
|
|
|
|
|
That works for bizdev, but not so much with IoT and embedded where you can't usually afford much abstraction and every byte of memory matters. When you're dealing with 2kB-4kB of RAM at 8MhZ and 256kB program space you forgo a lot of the things you take for granted in business software.
Real programmers use butterflies
|
|
|
|
|
I agree. I "cut my teeth" writing embedded code for DOD avionics computers and FAA radar systems. It had to be written in assembly language because the compilers of the day (1970s) were horribly inefficient and the "optimizers" were buggy. Everything had to be documented to DOD specifications and data item descriptions (DIDs). Thankfully, the source code, however, did not get loaded into ROM. The source code was printed, bound, and included in the documentation, along with a punched paper tape or punched card deck for the source and paper tape for the binary. Only the binary was programmed into the ROM chips - the largest avionics system I worked with in those days had a whopping 12K of ROM for the program and 4K of RAM for data.
When I moved to the commercial world, I programmed Intel 8008, 8080 and 8086 and Motorola 6800-class processors. (PS: I preferred the flexibility of the instruction set of Motorola processors over the Intel processors.)
Later, I moved on to minicomputers (remember them??), UNIX, C and finally to Intel 80x86-based "personal computers" running Windows 3 and 3.1 on top of DOS.
__________________
Lord, grant me the serenity to accept that there are some things I just can’t keep up with, the determination to keep up with the things I must keep up with, and the wisdom to find a good RSS feed from someone who keeps up with what I’d like to, but just don’t have the damn bandwidth to handle right now.
© 2009, Rex Hammock
modified 3-Dec-21 2:42am.
|
|
|
|
|
I struggle with people who don't know what the word "omphaloskepsis" means
«The mind is not a vessel to be filled but a fire to be kindled» Plutarch
|
|
|
|
|
I struggle with style as it pertains to the coding of others. I can best understand a function by collapsing it into its primary logic gates, so when others fail to tab nest, the collapse is ugly at best and non-functional at worst. If these others would also add appropriate comments, I wouldn't mind as much, but it seems that not leaving notes goes with not nesting. I find that frustrating.
Also along the lines of style, I like to see standardization throughout in things like error handling, security, and naming conventions. I don't care so much which method you choose, but stick to one for the sake of others who come behind you.
BTW I don't bother trying to remember my function calls and parameters, I just copy/paste. I ctl-f, ctl-c, ctl-v all day every day, plus split screen editors. Tools, baby! I love 'em.
|
|
|
|
|
Documentation for end users. Currently reworking a 1000 page manual covering a variety of related programs. I hope I finish it next year.
|
|
|
|
|
I'm fairly dyslexic, gets much worse when I'm tired or too stressed. especially verbal to writing or reading out loud, it all gets jumbled up. sequences of more than 4 numbers I can't remember. As a result, I don't trust my memory.
So like you I don't like to spread my code all over the place, but I will still breakdown issues into smaller chucks, usually in the same file, so it's just a scrolling issue. if it's across multiple files then splitting the screen is an absolute must.
Since I don't have confidence in what was written, I test early and often whenever I can. but that also means I have way less issues in production than a lot of my peers. I also document my code, and when the language supports it add signature docs to each function, so when typing out code to connect to other code, the IDE will help me remember what params to pass or other relevant information.
My biggest issues are usually switching between languages and remembering how to do something when two different languages do things similar, but not quite. so C, C#, Java, JavaScript, Rust, D, kind of blur together event though not the same. Had the same issues with ADA, Basic, and SQL oddly enough.
|
|
|
|
|
Quote: you'd think I'd be better at making it accessible to other developers. Maybe hand out copies of this with your source: How to Quickly Understand the Code of a Function - Fluent C++
Cheers,
Mike Fidler
"I intend to live forever - so far, so good." Steven Wright
"I almost had a psychic girlfriend but she left me before we met." Also Steven Wright
"I'm addicted to placebos. I could quit, but it wouldn't matter." Steven Wright yet again.
|
|
|
|
|
i also like longer functions. like i say "when you find the responsible function you have already won".
high cognitive load is not the problem, but you should aim to improve the "difficult to decipher code" part.
|
|
|
|
|
Gem took pride losing thumbs up maybe (7)
"Life should not be a journey to the grave with the intention of arriving safely in a pretty and well-preserved body, but rather to skid in broadside in a cloud of smoke, thoroughly used up, totally worn out, and loudly proclaiming “Wow! What a Ride!" - Hunter S Thompson - RIP
|
|
|
|
|
PERIDOT - a gem
TO OK PRIDE
Software rusts. Simon Stephenson, ca 1994. So does this signature. me, 2012
|
|
|
|
|
YAUT - well done
"Life should not be a journey to the grave with the intention of arriving safely in a pretty and well-preserved body, but rather to skid in broadside in a cloud of smoke, thoroughly used up, totally worn out, and loudly proclaiming “Wow! What a Ride!" - Hunter S Thompson - RIP
|
|
|
|
|
The first method below is probably 3e-9 seconds faster per call than the second method...
And a code reviewer asked that I used that syntax
private IMultipleComponentHandler SelectionHandler
{
get
{
if (m_selectionHandler == null)
{
var objects = SelectedObject;
<pre>
if (objects is IMultipleComponentHandler handler)
return m_selectionHandler = handler;
object[] collection;
if (objects is IEnumerable e
&& !objects.GetAttributes<IgnoreIEnumerableAttribute>().Any())
{
collection = e as object[] ?? e.Cast<object>().ToArray();
}
else if (objects != null)
{
collection = new[] { objects };
}
else
{
collection = Array.Empty<object>();
}
return m_selectionHandler = new InspectorMultipleComponentHandler(collection);
}
return m_selectionHandler;
}
}
private IMultipleComponentHandler m_selectionHandler;</pre>
but... that extra variable annoys me (var objects = SelectedObject; ), I see it as increasing code complexity for little benefit. I prefer that simpler version
private IMultipleComponentHandler SelectionHandler
{
get
{
if (m_selectionHandler == null)
{
if (SelectedObject is IMultipleComponentHandler handler)
return m_selectionHandler = handler;
object[] collection;
if (SelectedObject is IEnumerable e
&& !SelectedObject.GetAttributes<IgnoreIEnumerableAttribute>().Any())
{
collection = e as object[] ?? e.Cast<object>().ToArray();
}
else if (SelectedObject != null)
{
collection = new[] { SelectedObject };
}
else
{
collection = Array.Empty<object>();
}
return m_selectionHandler = new InspectorMultipleComponentHandler(collection);
}
return m_selectionHandler;
}
}
private IMultipleComponentHandler m_selectionHandler;
What says you?
For the record this is in a view model, this code is absolutely NOT performance critical.
|
|
|
|
|
Super Lloyd wrote: a code reviewer asked that I used that syntax
Why ?
|
|
|
|
|
because it's faster! (by perhaps as much as 1% I reckon!)
but yea, that's exactly what I am thinking as well....
it's one of those day I want to say, f*** those code comments....
|
|
|
|
|
Ok, you mentioned speed but it did not occur to me that this was the very reason for the change.
When not performance critical, readability takes over anything else.
Maintaining code is a nightmare, maintaining spaghetti code is a PITA inside the nightmare.
|
|
|
|
|
yea, yea, I totally agree.. this comes from C++ developer doing C#....
they pretend be very concerned by speed but their own code is an indecipherable big bowl of spaghetti...
|
|
|
|
|
If we are talking about sexiness it annoys me way more that you have
if (m_selectionHandler == null) instead of if (m_selectionHandler != null) return m_selectionHandler;
Rules for the FOSW ![ ^]
MessageBox.Show(!string.IsNullOrWhiteSpace(_signature)
? "This is my signature: " + Environment.NewLine + _signature
: "404-Signature not found");
|
|
|
|
|
ha, err... yea, I don't care either way.. but now that you mention it, I usually tend to it more that way too.. mm...
I think what happens is some previously annoying code comment and refactoring, so it ended up that way...
|
|
|
|
|
Well, you know i didn't use it much at first but then i found it very useful, since i prefer reading a method not like a chapter of a book but a "flowchart".
So if i get into that method i don't want to scroll down to see what happens if something is something
but i want to know what happens if this is true, okay return. Next "branch" if this happens, do that and return. And so on.
Makes readability in my opinion way better and if you are looking for a specific branch of actions you may find it faster.
But that's just my approach
Rules for the FOSW ![ ^]
MessageBox.Show(!string.IsNullOrWhiteSpace(_signature)
? "This is my signature: " + Environment.NewLine + _signature
: "404-Signature not found");
|
|
|
|
|
exactly my thoughts process too!
but, those code reviews are getting to me, too many stupid comments, and style guideline I don't like, so those days I just give up and do whatever the hell they say, but that also puts me in a bad mood and makes me think.. less clearly shall we say...
|
|
|
|
|
If you can't change the rules, break the rules XD
Nah srsly, i tend to go on change it, love it or leave it mentality. This solves many frustration related issues for me so far.
Rules for the FOSW ![ ^]
MessageBox.Show(!string.IsNullOrWhiteSpace(_signature)
? "This is my signature: " + Environment.NewLine + _signature
: "404-Signature not found");
|
|
|
|
|
The "extra" variable doesn't bother me. I don't think there's much difference in the cognitive load required to understand each function.
Given that the first one passed code review, it's "sexier", IMO.
Edit: I have to add, is the extra time you're spending trying to decide which version is more readable adding the requisite amount of value? *hides*
Real programmers use butterflies
|
|
|
|
|
I am just fed up with all those rubbing me wrong micro management useless comments...
I try to just shrug it off...
But it annoys me every time some (of those particular) guys reviews... but on the other hand getting any review at all is also hard work, so bloody annoying...
|
|
|
|
|