Join devRant
Do all the things like
++ or -- rants, post your own rants, comment on others' rants and build your customized dev avatar
Sign Up
Pipeless API
From the creators of devRant, Pipeless lets you power real-time personalized recommendations and activity feeds using a simple API
Learn More
Search - "method naming"
-
I wrote a database migration to add a column to a table and populated that column upon record creation.
But the code is so freaking convoluted that it took me four days of clawing my eyes out to manage this.
BUT IT'S FINALLY DONE.
FREAKING YAY.
Why so long, you ask? Just how convoluted could this possibly be? Follow my lead ~
There's an API to create a gift. (Possibly more; I have no bloody clue.)
I needed the mobile dev contractor to tell me which APIs he uses because there are lots of unused ones, and no reasoning to their naming, nor comments telling me what they do.
This API takes the supplied gift params, cherry-picks a few bits of useful data out (by passing both hashes by reference to several methods), replaces a couple of them with lookups / class instances (more pass-by-reference nonsense). After all of this, it logs the resulting (and very different) mess, and happily declares it the original supplied params. Utterly useless for basically everything, and so very wrong.
It then uses this data to call GiftSale#create, which returns an instance of GiftSale (that's actually a Gift; more on that soon).
GiftSale inherits from Gift, and redefines three of its methods.
GiftSale#create performs a lot of validations / data massaging, some by reference, some not. It uses `super` to call Gift#create which actually maps to the constructor Gift#initialize.
Gift#initialize calls Gift#pre_init (passing the data by reference again), which does nothing and returns null. But remember: GiftSale inherits from Gift, meaning GiftSale#pre_init supersedes Gift#pre_init, so that one is called instead. GiftSale#pre_init returns a Stripe charge object upon success, or a Gift (and a log entry containing '500 Internal') upon failure. But this is irrelevant because the return value is never actually used. Pass by reference, remember? I didn't.
We're now back at Gift#initialize, Rails finally creates a Gift object using the args modified [mostly] in-place by all of the above.
Another step back and we're at GiftSale#create again. This method returns either the shiny new Gift object or an error string (???), and the API logic branches on its type. For further confusion: not all of the method's returns are explicit, and those implicit return values are nested three levels deep. (In Ruby, a method will return the last executed line's return value automatically, allowing e.g. `def add(a,b); a+b; end`)
So, to summarize: GiftSale#create jumps back and forth between Gift five times before finally creating a Gift instance, and each jump further modifies the supplied params in-place.
Also. There are no rescue/catch blocks, meaning any issue with any of the above results in a 500. (A real 500, not a fake 500 like last time. A real 500, with tragic consequences.)
If you're having trouble following the above... yep! That's why it took FOUR FREAKING DAYS! I had no tests, no documentation, no already-built way of testing the API, and no idea what data to send it. especially considering it requires data from Stripe. It also requires an active session token + user data, and I likewise had no login API tests, documentation, logging, no idea how to create a user ... fucking hell, it's a mess.)
Also, and quite confusingly:
There's a class for GiftSale, but there's no table for it.
Gift and GiftSale are completely interchangeable except for their #create methods.
So, why does GiftSale exist?
I have no bloody idea.
All it seems to do is make everything far more complicated than it needs to be.
Anyway. My total commit?
Six lines.
IN FOUR FUCKING DAYS!
AHSKJGHALSKHGLKAHDSGJKASGH.7 -
This codebase reminds me of a large, rotting, barely-alive dromedary. Parts of it function quite well, but large swaths of it are necrotic, foul-smelling, and even rotted away. Were it healthy, it would still exude a terrible stench, and its temperament would easily match: If you managed to get near enough, it would spit and try to bite you.
Swaths of code are commented out -- entire classes simply don't exist anymore, and the ghosts of several-year-old methods still linger. Despite this, large and deprecated (yet uncommented) sections of the application depend on those undefined classes/methods. Navigating the codebase is akin to walking through a minefield: if you reference the wrong method on the wrong object... fatal exception. And being very new to this project, I have no idea what's live and what isn't.
The naming scheme doesn't help, either: it's impossible to know what's still functional without asking because nothing's marked. Instead, I've been working backwards from multiple points to try to find code paths between objects/events. I'm rarely successful.
Not only can I not tell what's live code and what's interactive death, the code itself is messy and awful. Don't get me wrong: it's solid. There's virtually no way to break it. But trying to understand it ... I feel like I'm looking at a huge, sprawling MC Escher landscape through a microscope. (No exaggeration: a magnifying glass would show a larger view that included paradoxes / dubious structures, and these are not readily apparent to me.)
It's also rife with bad practices. Terrible naming choices consisting of arbitrarily-placed acronyms, bad word choices, and simply inconsistent naming (hash vs hsh vs hs vs h). The indentation is a mix of spaces and tabs. There's magic numbers galore, and variable re-use -- not just local scope, but public methods on objects as well. I've also seen countless assignments within conditionals, and these are apparently intentional! The reasoning: to ensure the code only runs with non-falsey values. While that would indeed work, an early return/next is much clearer, and reduces indentation. It's just. reading through this makes me cringe or literally throw my hands up in frustration and exasperation.
Honestly though, I know why the code is so terrible, and I understand:
The architect/sole dev was new to coding -- I have 5-7 times his current experience -- and the project scope expanded significantly and extremely quickly, and also broke all of its foundation rules. Non-developers also dictated architecture, creating further mess. It's the stuff of nightmares. Looking at what he was able to accomplish, though, I'm impressed. Horrified at the details, but impressed with the whole.
This project is the epitome of "I wrote it quickly and just made it work."
Fortunately, he and I both agree that a rewrite is in order. but at 76k lines (without styling or configuration), it's quite the undertaking.
------
Amusing: after running the codebase through `wc`, it apparently sums to half the word count of "War and Peace"15 -
I am fed up working with unskilled software developers. Or to be more specific, working with people who have no idea of sofware architecture.
Most people I've worked with have simply no idea what they are doing in the broad picture, they can only follow patterns they see and implement their feature in the same way. They can't think about the abstract concepts which should be the foundation of the project.
They fail to write unit tests which are maintainable. They write one fucking test per method which is testing 50 things at the same time, making it often impossible to understand what is being tested.
They think putting stuff in private methods makes their class better and is some kind of separation of concerns.
They write classes and afterwards create interfaces for these classes named {Class}Interface, shoving all the methods into that interface. They think it's good design to do so.
They are unable to think about the reasons why things are done the way they are done and that you don't do stuff for the sake of doing stuff, but to achieve certain goals like interchangeability.
They don't undestand how to separate business logic from the application code.
They have no sense for naming things beautifully. They don't see how naming things is a major part of good software architecture.
They get layer concepts wrong and then create godlike {EntityName}Service classes, which do everything related to a particular entity.
They fail to shape the boundaries within a software project, entangling stuff which should live in individual modules.
All I want is to work in a team with professionals.2 -
Deciding a domain or project name, got to be the next worst after naming variables and exposed method names14
-
The code is a freaking mess. Shared behavior, terrible variable/method naming, misleading module naming, dynamic polymorphic spaghetti, whitespace errors, no consistency, confusing even if you understand what the code is doing, ... . It should never have passed code review. It probably wasn't code reviewed.
The comments are sparse and useless. Quality level: // This is bridge.
The documentation does not exist.
Testing steps for QA are missing several steps, including setup, so actually using the feature is bloody challenging. If one thing is wrong, the feature just doesn't show up (and ofc won't tell you why).
The specs for the feature are outdated and cover only 4 of 19+ cases. And are neigh useless for those 4.
The specs for the report I'm fixing don't even check the data on the report; it just checks for one bit of data on each row it creates -- a name -- which is also the same on each row. gg.
The object factories (for specs) are a mess, and often create objects indirectly, or in backwards order with odd post-create overwriting to make things work. Following the factories is a major chore, let alone fixing or extending them.
The new type has practically zero test coverage.
The factory for the new type also only creates one variant -- and does so incorrectly.
And to top it all off: the guy who wrote the feature barely ever responds. If he does, he uses fewer words than my bird knows, then stops responding. I've yet to get a useful answer out of him. (and he apparently communicates just fine, according to my micromanager.)
But "it's just fixing a report; it'll be easy!"
Oh, fuck off.8 -
Is it just me who sees this? JS development in a somewhat more complex setting (like vue-storefront) is just a horrible mess.
I have 10+ experience in java, c# and python, and I've never needed more than a a few hours to get into a new codebase, understanding the overall system, being able to guess where to fix a given problem.
But with JS (and also TS for that matter) I'm at my limits. Most of the files look like they don't do anything. There seems to be no structure, both from a file system point of view, nor from a code point of view.
It start with little things like 300 char long lines including various lambdas, closures and ifs with useless variables names, over overly generic and minified method/function names to inconsistent naming of files, classes and basically everything else.
I used to just set a breakpoint somewhere in my code (or in a compiled dependency) wait this it is being hit and go back and forth to learn how the system state changes.
This seems to be highly limited in JS. I didn't find the one way to just being able to debug, everything that is. There are weird things like transpilers, compiler, minifiers, bablers and what not else. There is an error? Go f... yourself ...
And what do I find as the number one tipp all across the internet? Console.log?? are you kidding me, sure just tell me, your kidding me right?
If I would have to describe the JS world in one word, I would use "inconsistency". It's all just a pain in the ass.
I remember when I switcher from VisualStudio/C# to Eclipse/Java I felt like traveling back in time for about 10 years. Everyting seemd so ... old-schoolish, buggy, weird.
When I now switch from java to JS it makes me feel the same way. It's all so highly unproductive, inconsistent, undeterministic, cobbled together.
For one inconveinience the JS communinity seems to like to build huge shitloads of stuff around it, instead of fixing the obvious. And noone seems to see that.
It's like they are all blinded somehow. Currently I'm also trying to implement a small react app based on react-admin. The simplest things to develop and debug are a nightmare. There is so much boilerplate that to write that most people in the internet just keep copying stuff, without even trying to understand what it actually does.
I've always been a guy that tries to understand what the fuck this code actuall does. And for most of the parts I just thing, that the stuff there is useless or could be done in a way more readable way. But instead, all the devs out there just seem to chose the "copy and fix somehow-ish" way.
I'm all in for component-izing stuff. I like encapsulation, I'm a OOP guy by heart. But what react and similar frameworks do is just insane. It's just not right (for some part).
Especially when you have to remember so much stuff that is just mechanics/boilerplate without having any actual "business logical function".
People always say java is so verbose. I don't think it is, there is so few syntax that it almost reads like a prose story. When I look at JS and TS instead, I'm overwhelmed by all the syntax, almost wondering every second line, what the actual fuck this could mean. The boilerplate/logic ration seems way to off ..
So it really makes me wonder, if all you JS devs out there are just so used to that stuff, that you cannot imagine how it could be done better? I still remember my C# days, but I admin that I just got used to java. So I can somehow understand that all. But JS is just another few levels less deeper.
But maybe I'm just lazy and too old ...4 -
This feature I'm building requires crossing over to a second application for some actions (fair, this reduces repetition), but the method used for it is kind of ridiculous.
To keep with the existing patterns, I followed suit, and added two PATCH and a DELETE routes, wrappers, and calls. (Typical CRUD + de/reactivate).
But. This freaking halfassed HTTP model doesn't support anything but POST and PUT! wtf. (Also, the various IDs, naming schemes, and required json data/formats differ across view, controller, and endpoints. but whatever?)
Two and a half hours later, and the feature is done and works wonderfully. Four times the functionality of the previous incarnation, and the code is only about 25% longer! haha.
Ahh, I'm complimenting myself again. (but somebody has to, right? 😅)
but really, when i want to get something done i'm actually surprised at how quickly it all comes together. Even when I need to patch API Guy's madness.
(and this time I actually found someone else's code in the mess! It was actually worse!)
I suppose taking a day off yesterday did me some good.rant double entendres are the best rest after rest root compliments herself expanding someone else's crud1 -
dear api author at my company pt. 2:
If you're gonna create an api method that takes some arguments.
And one of those arguments is an array.
THEN MAKE THE FUCKING ARGUMENT'S NAME PLURAL YOU FUCKING PIECE OF SHIT.
REPEAT WITH ME, MOTHERFUCKER.
ARRAY, PLURAL, NON-ARRAY, SINGULAR.
I need to pass a shitload of filters for the data for this table, and for every suckin fuckin filter I need to singularize this shit. Thank god for es6.
I know this sounds like nitpick, but I swear to fucking alpha omega this guy is inconsistent as fuck.
Every time it feels like he makes up a new rule.
Sometimes I need to send arrays of ids, other times arrays of objects with an id property on each.
He uses synonyms too, sometimes it's remove, other times erase.
PICK ONE MOTHERFUCKER.
If you can't do the basic things well, then what is to expect of more advanced stuff?
Naming conventions you fucking idiot, follow them. It's programming 101.
You're already sending them as plural in the fucking response. Why change them for the request?
And that's just style, conventions.
This idiot asshole also RARELY DOES ANY FUCKING CHECK ON THE ARGUMENTS.
"Oh, you sent a required argument as null? 500"
We get exceptions on sentry UP THE ASS thanks to this useless bone container.
YOU'RE SEEING THE EXCEPTIONS TOO!!!!! 500'S ARE BUGS YOU NEED TO FIX, YOU CUMCHUGGER
And sometimes he does send 400, you know what the messages usually are?
"Validation failed".
WHYYYYYY YOU GODDAMN APATHETIC TASTELESS FUCK???
WHAT EXACTLY CAUSED THE FUCKING VALIDATION TO FAIL????
EXCEPTIONS HAPPEN AND THANKS TO YOU I HAVE NO IDEA WHY.
The worst of all... the worst of fucking all is that everytime I make a suggestion to change shit, every time, you act like you care.
You act like the api is the way it is because you designed it in a calculated manner.
MOTHERFUCKER. IF A USER HAS ONLY PRODUCT A, THEN HE SHOULDN'T BE ABLE TO ACCESS DATA FOR PRODUCT B. IT IS NOT ENOUGH TO JUST RESTRICT SHIT WITH ADMIN ROLES. IDIOT!!!!!
This is the work of someone who has no passion for programming.10 -
My best code review experience?
Company hired a new department manager and one of his duties was to get familiar with the code base, so he started rounds of code reviews.
We had our own coding standards (naming, indentation, etc..etc) and for the most part, all of our code would pass those standards 100%.
One review of my code was particularly brutal. I though it was perfect. In-line documentation, indentation, followed naming standards..everything. 'Tom' kept wanting to know the 'Why?'
Tom: 'This method where it validates the amount must be under 30. Why 30? Why is it hard-coded and not a parameter?'
<skip what it seemed like 50 more 'Why...?' questions>
Me: "I don't remember. I wrote that 2 years ago."
Tom: "I don't care if you wrote it yesterday. I have pages of code I want you to verify the values and answer 'Why?' to all of them. Look at this one..."
'Tom' was a bit of a hard-ass, but wow, did I learn A LOT. Coding standards are nice, but he explained understanding the 'What' is what we are paid for. Coders can do the "What" in their sleep. Good developers can read and understand code regardless of a coding standard and the mediocre developers use standards as a crutch (or worse, used as a weapon against others). Great developers understand the 'Why?'.
Now I ask 'Why?' a lot. Gotten my fair share of "I'm gonna punch you in the face" looks during a code review, but being able to answer the 'Why?' solidifies the team with the goals of the project.3 -
Attracted by Python's powerful built-in libs, I learned it by myself. However, its naming convention is confusing me. It even can't correspond to itself in an object. For example, a dict object has a method named has_key and a method named popitem. So I need to check up on the function names frequently.6
-
!rant
the most popular ecommerce solution in php is a massive (cosmological scale) pile of corporate crap (magento) and the next most popular is an abomination (opencart)
after fucking around with both for a month (the client asked for the project to be using only one of the two) I'm still barely reaching any results, and most of my time is wasted with the stupid bloated spaghetti that is opencart FUCK THIS,
like seriously. who the fuck writes a single line three left joins sql querry with four or five aliases a couple concacts and a bunch sorting fuckeries just to query the categories list, then just query the details of the specific category from a different function,
also why the fuck map each language string manually. or the fucking hardcoded seo urls, or the use of myisam for all tables, and no fucking foreign keys, let that settle for a minute, no foreign keys, the delete method in the model has at least a twenty lines, and then he came with the genius idea of duplicating models, in the front and the backend, accessing the same data, as the same user, but different naming conventions
I'm going to convince him to use something sane like codeigniter/laravel/fuelphp or I'll deny the project8 -
Lmfao, in a book teaching Java, there's a chapter that contains a class called AddMeth to illustrate adding a method to a class.
They could have used a better name, though..7 -
while(people say something){
Listen();
Smile();
Agree();
DowhateveRtHeFUckyouaregOintodoAnyway();
}
PS: that's some heavy method naming😂 -
Usually, when I programme for myself or in a German-only team and they agree, I/we do it in German because it makes naming things much simpler (no naming conflicts, never, and a strict visible separation between your code and libraries).
This time, I thought: "Nooo, let's do it in English, because, you know, reasons and it fits into the situation"...
Booom, stack overflow!
"How in the hell did that happen?" I never had a stack overflow before outside of recursive programming.
And what was it? I had made a class to encapsulate an API, added a property with getter and setter, naming in English and similar to the said API... very similar... in fact, the property had the same name as the API function, resulting in a getter calling itself over and over again.
This was a harmless mistake, and found very quickly, but it's interesting so see how a habit (or working method) probably prevented similar or worse sources of error in the past.3 -
If not understanding code, read the documentation or debug the code. When trying to modify...
1. Follow proper indentation.
2. Don't make spelling mistakes and follow naming convention.
3. Don't try to write all the code in one line (based on line length set)
4. Simplify if else statements if possible.
5. If value of method call need to be used once, don't store it in a variable. Directly use where ever it is needed.
6. If there is duplicated code, put it in separate method and re-use it if possible.1 -
I'm always helping out a girl in my class with her coding assignments but her code is absolutely atrocious. I don't have the heart to tell her that her whole method, file and variable naming, and process is wrong and is causing her so many headaches.11
-
I'm going to confess: I am the type of developer that creates the ExcruciatinglyLongAndSpecificClassNameObject with the UtterlyDetailedExplanationMethod. It's just a thing I keep doing, despite voiced frustrations from people I've worked with. It just feels right in the mindset of self-documenting code
And while I acknowledge this isn't a flawless process, I see no other way around without losing information. I've tried alternatives, but everything feels like trading one issue for another:
- Abbreviations work as long as they are well known (XML, HTML, ...). As soon as you add your own (even if they make sense in the business context) you can bet your ass someone is going to have no idea what you're talking about. Even remembering your own shit is difficult after X months.
- Removing redundant naming seems fine until it isn't redundant anymore (like when a feature with similar traits gets added). and you can bet your ass no-one is going to refactor the existing part to specify how it differs from the newly added stuff.
- Moving details to namespaces is IMO just moving the problem and pretending it doesn't exist. Also have had folks that just auto-include namespaces in VS without looking if they need the class from namespaceA or namespaceB and then proceed to complain why it doesn't compile.
So, since I am out of ideas, I'd like to ask you folks: Is it possible to reduce class/method name lengths without losing information? Or is self-documenting code just an ideal I'm trying too hard to achieve? Or are long names not a problem at all? I'm looking forward to your answers.19 -
fuck the guy that writed the api that I consume at my company
he's not the worst guy ever, and he might be going through some stuff in life, or maybe he's just happy. There's no way to know actually.
but fuck him. fuck this fucking guy. fuck him with a thousnd dicks.
this guy defends his postures on the api like this thing was fucking sacred and masterly designed ok?
if I ask him to change one url's method from get to post so that I can send more longer data for the request, he comments "i cant believe they still haven't figured out a get request with a body". I appreciate him caring abkut the correctness.
but this is the same piece of shit that makes NOOO fucking validations on whatever I send to it. I get 500 for fucking EVERYTHING.
And if he does 400, the actual response messages are garbage, the same fucking text with no explanation.
FUCK YOU!!!!!!
I hate the way he structures the names of the url and the parameters, sometimes I have to send arrays of strings, other times arrays of objects, the naming is garbage and INCOSISTENT.
And when we asked him to do the API dotnet core, he was like "nah" FUCK YOU FOR USING SOON TO OBSOLETE TECHNOLOGIES!!!
THIS PIECE OF SHIT IS SLOW, because a coworker did another spi in core and the response times are hugely better.
I wouldnt mind if he was 100% of the time careless, but he actually makes a stand for his ideas, as if he actually gave two shits.
he's actually an ok guy though but... fuck hiim!!!! ive been holding onto this for a while... and I'm sure I have some flaws too.7 -
First rant;
First of all I am an applied computer science student in the second semester.
We've got a few assignments and the first set went fine but this last week boy ohh boy - first of all today I got noticed by one of my two teammates that the other one won't get stuff done in this assignment (he also did next to nothing in the first)
Also the the assignment is unclear and the given methods and parameters don't care about naming conventions (for one method I don't even know what it should do). Also we have to use new liberies (java.io etc.) and learn them on our own so far it would be okay, the time limit is two weeks, also doable
BUT the same chair also made one assignment for web development with the same deadline and also no explanation how to do stuff.
I don't say I am perfect but the expectations are too high, while also studying for other modules1 -
Ok, so currently in my Java course on Udemy we are going more in-depth into scope and visibility, and I'm currently doing the challenge for it.
So I'm doing it and the challenge is to have every single name of a variable or method be called 'x' (just to better understand scope and vis, he mentions how this is not a good practice AT ALL) with the exceptions of the classes and scanner var (but there is an optional challenge to also make them named x).
Now that I progressed into it, I noticed something. This challenge is literally making me make my code so DRY and outside-the-box-thinking that, what if, this could be a practice?
Not the naming everything in your code the same var name, but doing that at the start and then renaming the variables after coding. Because right now, I feel as though I am using SO MUCH less code than if I had the liberty of naming my classes, methods, and variables different things, it's actually kinda cool.
I'll attach my code from the challenge to this after by it really amazed me how well my code looked compared to my previous challenges and even personal projects!1 -
In my whole carrier as developer. I never felt so helpless as in naming things.
Could be class, method, file name. The worst thing is it become hard as the code base increase.
How you overcome this?8 -
So for the past two days I had to deal with a problem where I have to do a nested query with sequelize, pretty straight forward reading the documentation, or that was I think. I implemented everything according to the docs but the query stills fails, why ? I had no idea, I double check my implementation, I googled the error, no luck, after a day searching like crazy I talked with the backend lead about this and he help me to realize that the naming convention was changing because sequelize is creating a nested (SELECT * FROM) because one of the relations has a one-to-many realtion with the root model and I'm why the heck is doing that? But we both didn't know, and the problem was solved by just modifying the names, so we let it through, and sent it to QA. The next day I see the task rejected by QA and the reason was after the changes were merged another part of the app was broken, ok np, I'll fix it right away, and oh God I found the error was caused by another query that was including the first query we fix yesterday ! It was a nested query with 3 lvls! And the names became even more complex ( like `model1->model2.colum1`), goddamit, ok, I spent most of the day searching again, nothing, read the specification of the findAll function, nope, tried to put that name in the ON clause as the docs suggested, still an error, shit, then the lead helps me again and creates a literal which can hold that name and voila! Everything is happiness, at least for that moment, but I was still curious about this behavior, so I keep digging on it and I've just found an issue where a great guy posted an option to the findAll method that is not documented in any version of sequelize ! WTF ! And this option was "subQuery" which if you set it to false it won't create that additional (SELECT * FROM) from before, FUUUCK! I can't believe it, I know that all the effort works in my favor because I learn more about sequelize, but FFS I'm still angry because this shit shouldn't happen, you need to update the god damn docs, it's just adding a row and telling the people what it does. Well to end this, after putting that in the query and replacing all the workarounds with the expected syntaxis everything works like charm.1
-
I recently built an automated payout functionality for bank-to-bank transfers, and we initially looked at using the pain.001 XML schema to do it. Luckily, we ended up finding a service that has a simple REST API to do this instead. (Thank god we didn't go with the XML method, I know how much of a headache that could become, I can imagine the treasure trove of memes with naming an XML schema with the name PAIN)
Anyway, for one of our big-brained product managers, this will forever be the infamous "XML Task" that he continues to ask about and bring up. I've already clarified a few times that we have long chosen a solution process that has nothing to do with XML, but to no avail, it will forever be his "XML Task". Wonder what name he'll pick next time we need XML in a solution? "Second XML Task?" Let's just keep the mental overhead idiot train going!2 -
Some of the rants that I’ve read recently have inspired me to write this one:
You know how some OOP based APIs require you to call the base implementation of an overridden method?
If you think about it, its pretty shit. None of the languages have mechanisms to enforce it, so all you can do is to rely on the caller to read the docs for that method that he is overwriting and then do the right thing.
And then you can also have the requirement that the base implementation should be called at the start or at the end of that method.
I really think that this is an OOP problem because if I would have to design it, I’d make a function that takes a closure as a parameter and then call that closure at the start or at the end of that "base" code. This is implicitly documented (by naming the closure appropriately so that the caller knows if it is called at start or end). And it is impossible to miss it because you need to pass something to that parameter. (Alternatively, you could also pass the closure to the constructor).7