I omitted the name in case I had it all wrong, but I was thinking of “Stylish” (and I’d have to look it up to be sure whether or not I was right about what I said).
Tools also make our life easier.
And for a software dev the main tool they have is their computer.
Why are there still places that make it difficult for their devs to have good hardware?
The previous place whenever I got there for a project I’d get handed the latest Dell Latitude with good specs. Working on that was fine. Right now if I was working on the provided remote PC… yikes. It’s from 2014 and cannot run IDE, database tool and test environment at the same time. Luckily, they allow me to work on my own hardware.
I just watched a colleague go through the process of getting a new laptop approved. It’s giving me flashbacks from my old job.
Speaking of tools that make your life easier… Our head of software keeps pushing me to drop our test management software in favour of gitlab, which we use for project management, deployment pipelines, etc. The reason being that he thinks it would be easier if everything was on one platform. I’d be sympathetic… except gitlab isn’t for test management. I asked him how he proposed we manage our test library in gitlab and he suggested keeping it in a wiki and copy-pasting into the ticket every time we wanted to redo the test ![]()
Lions led by donkeys
I’ve never understood this, either. At my previous job, getting new hardware was like pulling hens teeth. I had to work on a several year old PC, that had pretty marginal specs when it was new. A build job took ten minutes. On a fast modern machine (not even that crazy, a $2K PC), the build took three. Say that saved me (and the other devs) half an hour a day, 2 hours a week. At what it costs to pay a developer, it doesn’t take very long for that to pay for itself.
At my current job, I have acceptable hardware at my desk, even overkill, since I actually run work in a devel virtual machine. Which is underspeced, really. there’s some internal friction about this. the devvms represent approximently what the production machines are, which means if you’re working on the application, if it’s slow on your devvm, it’s slow in production. I dont’ work on that, I’m not even on the production side of the house. the stuff I write is all infrastructure, and making it painful for me to work just makes it painful. (and so much of its performance depends on external stuff, its hard to tell when I make something worse. oNe thing I recently did takes between 3 minutes and 30 minutes to run. In the best case, over two minutes is waiting for network or databases. In the worst case, it’s over 29 minutes. Hard to profile my code, or even optimize it (beyond “don’t make calls you don’t need to”)
I spent all day debugging a thing.
This one is such great fun™ I will try to explain it.
- So we have a complicated database entity. Let’s name it Thing.
- Now these Thing entities represent media and can reference each other, like quotations in books. So there is a database representation of that’s called ThingSourceResultRelation:
- ThingSourceResultRelation
- Source (of Quote)
- Result (Thing that quotes source)
- some more fields signifying the location of the quote in Source etc.
So sometimes someone manags to have two Thing entries repesenting the same thing. So what happens then? Obviously, there is a method to merge 2 Thing entities into a single one.
And guess what whoever wrote the merge named the two Thing entities that get merged in that method?
void mergeThing(Thing source, Thing result)
So when we get to the part that handles the ThingSourceResultRelation it looks like this:
relations = findRelations(source as source) & findRelations(source as result)
if(relation.source = source) relation.source = result
if(relation.result = source) relation.result = result
Anyone still following?
Now I wrote a test for that because I took that ticket from the stack last week with someone complaining that for their special use-case where there are relations of both sides of a merge, isnt working.
All I found today is that the merge works (more or less by accident) but in the DAO (database access object) someone mixed up the source and result paths for the relations… possibly maybe that is the bug… I have not found out how to look at ThingSourceResultRelation in the UI or recreate the behavior that is described in the ticket.
TL;DR: if you have two intersecting use-cases make sure you do not name all the variables in such a similar way that they can get mixed up. Otherwise you can just go back to naming everything foo and bar.
Piece of code I fixed the other day
foo = foos.foo[0].foo
it had been
foo = foos.foo[0]
foos is an object with a field foo which is a list of objects that are not foos, but which have one in them. I can’t imagine how anyone got that confused.
Speaking of awful naming, I was looking at some of the most unreadable-despite-being-trivial logic I’ve seen in ages the other day. There were two boolean variable names ending in “_status” and one of them was true if its named thing was enabled, and the other was true if its named thing was disabled. These were even defined on successive lines. Let’s call that second one foo_status. We then had an if statement where somehow not foo_status had been chosen as the condition, despite there also being an else clause. The actions taken for the two branches were called add_attributes which removed things from view, and remove_attributes which added the things back again. The sheer quantity of inverted meanings in this tiny amount of code was just astounding. I added some comments:
if (bar_status) {
// bar is enabled
if (!foo_status) {
// foo is NOT NOT enabled (is enabled).
// Add 'disabled' attributes to HIDE other elements.
add_attributes();
}
else {
// foo is NOT NOT NOT enabled (is disabled).
// Remove 'disabled' attributes to SHOW other elements.
remove_attributes();
}
}
I look forward to deleting this ludicrous code in the near future.
Likewise. I have so many questions. I don’t know how it’s even possible to write this code without succumbing to an overwhelming need to refactor. On the plus side the author of this particular code does not work at my company, which limits my exposure to their particular brand of sense.
some people just think in negative logic. At a previous job, there was one such person. he wrote code like
(unless (not foo)
....)
Lisp has the when form
(when foo
...)
I wrote a regex that replaced the simple (unless (not word) cases with (when word, which I deployed the day he left. Many of his usages were not simple, but had me applying boolean logic to simplify them.
(both when and unless are single pronged conditionals, as a convenience to using if, which only allows a single form for the true and false cases. that form can be a progn, which is a list of forms)
I have a personal coding rule that if I extend a bit of code from
if (not thingy) {
do stuff
}
(or unless (thingy) if the language allowed that) to do other-stuff if thingy is true, it always gets shifted around into
if (thingy) {
do other-stuff
} else {
do stuff
}
even if that makes things less immediately convenient.
(I think triple-backtick mode in Markdown tries to guess the programming language, thus the different highlighting.)
Discussion in another place recently turned up this bit of Python:
third_tuesday = [day for week in monthcal for day in week if \
day.weekday() == calendar.TUESDAY and \
day.month == month][2]
It’s not just your personal rule, static code checkers like PMD, Sonar (et al) try to enforce “avoid negations where possible”… but I know too many devs who think such “small improvements” are beneath them.
There’s that whole thing (which I grew up in) of “well, programmers are socially inept, but you have to make allowances 'cos they’re smart” – but this can all too easily leave you with people who take advantage of that and never even try to learn any manners or anything beyond “give me what I want right now”. (And of course nonwhite and nonmale programmers don’t get to do this.)
I’m very relieved to say that the guy I worked with who fitted that description to a tee was let go.
Unfortunately we gave him plenty of time to fit in, so we ended up with plenty of his code on one particular project. For quite a while afterwards, whenever I encountered any of it my first question was always “will it be cost-effective to delete this whole thing and rewrite it?” If the answer wasn’t “yes” then there would invariably be some significant refactoring regardless; but when the answer was “yes”… what a happy feeling that was!
I’m a bit surprised we don’t have any commit time linters for logic (we have a bunch for other constructs, including cyclomatic complexity, and they’re amazingly opinionated about style.).
To defend some of this code, sometimes it sneaks up on you. It’s easy to discover you need to add another or clause to an if statement, and not realize you’ve crossed the line into excessive complexity. or realize that the problem was one of the internal clauses need negation, and get faced with the choice of just making that change, or rewriting it, and having to test all the paths through it. (and you know there’s not good test coverage for all the possible combinations.) You have an infinite things I could do, rewriting working code isn’t terribly high on the list of things that makes your performance report look good.
I try not to do that, but I see it a lot.
We’ve almost finished porting our unit tests to Google test.
So shortly we’ll be running our entire unit test suite on Windows and four different embedded platforms.
We’ve already found a handful of issues where things didn’t quite work properly on the hardware. Good thing no customer has tried to use that functionality in the last 4 years of this project.
I had a customer get in touch last week and the conversation went a little like this:
Customer: “We’ve turned on a compiler flag and your code now doesn’t compile.”
Me: Checks documentation. “The docs say you shouldn’t turn that flag on if you’re compiling C++, are you?”
C: “Yes.”
Me: “So why have you got it turned on?”
C: “I don’t know, nor does my boss, but can you look into it?”
This is the same chap I think I’ve previously moaned about. By trade he’s a software tester but for some reason we’ve contracted him to write some software.
I’m very fortunate in that my technical boss is me, and my non-technical boss is entirely happy with my speed if I only take as long to test as I took to write.
We find it helpful to document the effects of customers turning on forbidden compiler flags. The notable example is “<product> will crash.”
“Undefined. We really mean it. A big customer turned on this flag and now the only evidence they ever existed is in our Accounts Payable.”
