What is it even suppose to do?
Who wrote this $# ....
Oh. It was me.
What is it even suppose to do?
Who wrote this $# ....
Oh. It was me.
Did Sir Pterry every address the question of which divinty attends to tangled cables? I mean, it seems likely to me that the duty would fall to Anoia. Right?
Still working on my little JavaScript side-project as a way of learning AI workflows. Still not using AI for a lot of code-gen but instead for friction reduction. It's going fine, thanks. I mean, the last few weeks haven't seem many new features, but instead a couple of re-factoring passes intended to enable big things in the future, but I count that as progress.
Anyway, while thinking about the evolution I had a question. I was fairly sure the language would do things the "right" way, but felt the need to test, nonetheless. And being an old guy, I wrote the test code by hand:
const primes = [2, 3, 4, 5, 7, 11, 13, 17];
const fibonacci = [0, 1, 1, 2, 3, 5, 8, 13];
let combined = [...primes, ...fibonacci];
combined.sort();
console.log(`primes: ${primes}`);
console.log(`fibonacci: ${fibonacci}`);
console.log(`combined: ${combined}`);
the point of which was just to assure myself that sorting the combined array would not scramble the source arrays. I would have been very surprised if it had, but I had to check.
That said, the results were not what I expected:
primes: 2,3,4,5,7,11,13,17
fibonacci: 0,1,1,2,3,5,8,13
combined: 0,1,1,11,13,13,17,2,2,3,3,4,5,5,7,8
An array filled entirely with numbers has been sorted lexically according to their naive string values.
And on reflection, that's not terribly surprising in a language, like JavaScript, that is both dynamically typed and quite compact because it is the prescription most likely to work in most situations. But it sure came as a surprise to a guy used to strongly typed systems intended for systems and scientific work.
A couple of months ago there were, at last, some promising smoke signals from corporate suggesting that IT is getting around to really thinking about, just maybe, supplying us with something by way of security-minded LLM support.
Okay, so it was a little more than that. They actually bought licenses for a commercial product (something that comes with security guarantees backed by performance penalties) for supplying that kind of thing. For the managers.1 That was a bit disappointing because I couldn't explore that space on my employer's dime.
But it got me to start thinking seriously about trying out LLM supported programming workflows, and I decided to apply it to some aspects of my hobby projects. After some thought I concluded that the models I was likely to run were going to be uninspiring on C++ projects. To maximize the utility of the tool, I needed a project where (a) the model would have seen a lot appropriate of training data and (b) I was not already highly conversant with either the domain or the tooling.
I decided to start writing some little games for the browser in JavaScript.
And, brimming over with excitement for my new project I ... spent about four weeks of spare time mucking about with tooling. Yeah.
I did eventually gets Emacs configured to know about JavaScript (including an LSP, a major side-quest what with some self-imposed limitations, but that's another post) and chose one of the multiple LLM interfaces for the editor. There were a few hiccups along the way, but a I got some advice from a couple of LLMs which really helped. Oddly all the configuration work was making me feel optimistic about the project: the models weren't really handling much tedious boilerplate, but they were getting me past some ignorance-driven friction and probably (at least maybe) saving me time. So really yeah!
Then I watched a couple of on-line tutorial videos on JavaScript animation and game-dev, created a new project repository and started random hacking about while asking the models a bunch of questions and having them try their hands at writing bits of code. In about a-week-and-a-half of spare time I had a canvas with four distinct objects moving around it, each under their own set of rules for speed, gravity, wrapping around edges and bouncing. The code quality was awful, but not because the models wrote it. The parts I wrote were just as bad because this was a "just get something working" exercise. Almost everything was in global scope and free functions poked into the depths of the object collections to manipulate internal state. Classic.
The next thing to do, of course, was impose some order on the chaos. To channel interconnectedness through designed mechanism, and achieve a degree of uniformity in implementation.
I broke everything that worked to separate some concerns here, name elements
of the modeling there and so on. And after burning another week of spare time on
it, this afternoon I had all the same data in the program in a much more orderly
manner and the first frame drawing as expected. But nothing was changing even
though it looked like I had all the plumbing back in place. The application of
some judicious console.log calls2 proved that the animate
function was getting called, it was iterating through the object and telling
them to update themselves, and they were iterating through their update action
list and calling them. But the display was not updating.
And also, I hadn't asked the LLM anything for days of real-time and hours of coding time despite (if you believe Mrs. NoSwampCoolers) a steady stream of swearing at the code. I've been "a programmer" since sometime between 1982 and 1992, depending on what you want to credit with the title (1982 was first typing the classic 2-line "hello" infinite-loop in basic; 1992 was my first production code). I have deeply ingrained habits for both learning new things and tackling problems with code-bases. And "ask the AI" does not, currently, feature in those habits. Which is a me problem to the extent that "ask the AI" is better than my other approaches, but is still a thing to be overcome if a transition is to occur.
Anyway, I did eventually think to "ask the AI". I used my LLM
interaction tool to pick four (quite short) files out of the project directory
and asked why the actions called by Obj2d.update were failing to
update the positions.
After telling me many thing about the code that I knew (because I had
designed them in), and complaining about the bits of context I hadn't show it
because they did matter, noticing (out loud) that they didn't matter, and
deciding (out loud) to move on, it first proclaimed that there wasn't anything
reason for issue and then said, "but wait". Turns out the joker who
wrote this code didn't provide setters for some concepts he's trying to set in
the bowels of the Vec2d class. Which was the correct resolution
of the issue.3 Facepalm. Score one for the model.
1 Whose main day-to-day complaint (at least in my unit) is that they don't get enough time to do technical work what with all the people, contracts, and paper work they're saddled with.
2 Yes, there is a debugger in the browser, and yes I've largely figured out how to use it. But my "just hack on things" machine has a small display which (added to the unfamiliarity of the language and debugger) made print-debugging feel more comfortable. Presumably I'll get over it as I go.
3 I don't think I've mentioned on the blog before, but I
really hate environments that silently fail. And Firefox will let you
write v.x = new_value; when v has neither a public
data member nor a setting named "x". Really. So the f'ing environment gets some
of the blame here.
Accumulated over the years, but I got another one the other day that triggered me.
It's all about context seneitivity. Or the lack thereof.
1 With "Real" pronounced as a single sylable. Of course.
I've been reading The Hobbit to the child for bedtime story recently. Bit of a slog at times because (a) she falls asleep in the most surprising places in the text, (b) frequent stops to discuss new vocabulary and previously unknown customs, and (c) lengthy interruptions to hear how she things the story should proceed. That latter bit came to a head tonight as we neared the end of Chapter 8. She believes that the story would be better if we dispensed with the spiders and added some unicorns and has decides to make up her own, improved version.
Shortly after we moved into our present dwelling we started sending my then two year old daughter to a local preschool. That was nearly four years ago and today was her very last day there. I've managed not to think too hard about it for the last few week, but driving over to pick her up today is all hit me like a ton of bittersweet bricks. We're talking Time Stand Still playing in a loop in my head and flashbacks to my own transitions through the years.
Yikes!
The funniest part of it is that we've been scaffolding this change for her for more than a year. I just somehow forgot to scaffold it for myself.
Consider the canonical Meyer's Singleton implemetaion in C++ (2011 or later
standard):
class Singleton
{
Singleton();
~Singleton();
public:
Singlton(const Singleton &) = delete;
Singleton & operator=(const Singleton &) = delete;
Singleton & instance()
{
static Singleton s;
return s;
}
};
It has all the properties you might want of a Singleton:1 things like
guaranteed single initialization and thread safety. Plus, it's easier to
remember than any of the other functional variants I've seen.
But there is a subtle trap in the fact that I haven't shown you my
implementation of the c'tor.2 One that I just tripped on in a big
way. What happens if you were to call instance() in the
constructor?
Now, it is unlikely that anyone will write
Singleton::Singelton()
{
instance();
}
and overlook the silliness of it for long after the program hangs during
testing. However, writing
Singleton::Singelton()
{
supportRoutine()
}
where supportRoutine() calls helperWidget() which
calls instance() is a lot easier to miss for a few frustrating
hours. Trust me.
This is about the object lifetime model in modern C++. And honsestly I didn't know enough about the hoary details to figure out what the standard requires when I realized what I had done, but MSVC 2019 appears to enter an infinite recursion. Luckily the internet is full of people who have more (or at least different) expertise than me, so I was able to get some help. The first source that my google-fu found was a blog post by mbedded.ninja which includes an explicit call-out to the standard3 telling us this is undefined behavior.
So, yeah. Don't do that.
Late addition: on reflection, the reason I got into that pickle in the first place was that I was using the Singleton both to manage an OS resource and and as a repository for utility code related to the resources. Having them in the same context made it too tempting to trigger some of the utility code from the c'tor and involke the recursion. Re-writing the code to better folloow the Single Responisibility Principle made the loop imnpossible in the first place and made me re-think when to invoke the utility code.
1 Assuming, of course, that you want a Singleton; more on that in another post.
2 I've left the d'tor unspecified as well for a philosophical
reason: you should always decide on their implementaion as a pair. I don't want
to commit to = default; for the d'tor until I know what I'm doing
in the c'tor. In the instance that brought the subject up I was grabbing OS
resources in the c'tor and so needed a non-trivial d'tor that would nicely give
them back. Cue "but technically's" about the destruction order fiasco. I
said I would discuss the (often ill-)advisability of Singletons in another
post.
3 Section 6.7 paragraph 4 which says in part:
If control re-enters the declaration recursively while the variable is being initialized, the behavior is undefined.
I got a Kindle Scribe for Christmas. Yeah, now I hav an e-reader I can actually read papers on! Cool.
Of course, this just means I've been sucked into Amazon's ecosystem. You can only use a few formats on it, but that includes PDF. Except...
Fine. I'll pretend I don't think they're spying on my content, and I'll even try to believe that they are spying responsibly. But honestly they already know a lot about me.
But that doesn't mean that there aren't any surprises here. You see, the machine has a web browser. It's not very good, but it's there. That browser won't save PDFs directly to the machine, which is a little weird, but the big oddity is that it also has no facility to route them through Send to Kindle. To somehow manage to make matters worse, the "Send to Kindle" page has a link for a "Send to Kindle" browser extension!
Seems like a no-brainer to me. Perhaps I should send them a note, but they make that weird, too.2
1 More "Send to Kindle" breakage: it will convert ebook files to a Kindle friendly format for you, but will silently drop on the floor any files already in Kindle preferred format (that perhaps, you downloaded from a DRM-free source like Standard EBooks).
2 The device supports a "Contact Us" feature, which lets you send missives into the void, but they specifically disavow any intention to hold a conversation as a result (or even just telling you what they are doing about it). There doesn't seem to be a customer facing issue tracker where you can see that your suggestion is already in progress or follow deliberations on how to handle an issue. I'm spoiled by the culture of the open-source world.
Our daughter is intensely interested in upcomming changes in her life. In particular she's aware that she is currently attending the most senior program as her pre-school (a transitional class the state will accept in lieu of kintergarten) and wants to know about where she will go to "homework school".1
The phrase is descriptive and its meaning is clear, so it's a logical neologism, but I'd never heard it before. Is that a term of art among the pre-school set?
1 A very good question about which we are currently having a slow motion panic. Much research is being conducted and many experts are being consulted.

What with one thing and another I learned about the TEA project recently. Ambitious stuff, and I'm completely unprepared to talk about the project as a whole, but being a ex-academic, I wasted no time downloading the white-paper, and brought along a dead-trees version for flight as we took our spawn off to visit one set of Grandparents.1 The paper concerns itself with a distributed crytographic ledger to be used for archiving and authenticating the open-source ecosystem but also to provide a framework for distributing donations across that ecosystem.
The point is that much of the open-source ecosystem is un-sexy tooling and infrastructure that only excites the people who use it to write other open-source software, but donation come from either users (who tend to direct them to sexy top-of-the-stack end-user stuff) and companies (who direct them to things they are specifically trying to improve). Very little money flows to underlying stuff that "just works" even if it requires on-going maintenance to preserve that state of operability. There is a reason Randall uses the word "thanklessly" in the comic. Anyway, the paper observes that to perform such a distribution you would need to know how much each project contributes to the ecosystem, and then that a package manager (such as apt, pip, npm, or homebrew) is exactly an encoded version of that knowledge.
I'm pretty sure my jaw hung slack for the several seconds it took for my mind to re-orient on my freshly remade understanding of the open-source ecosystem. Of course, the package managers already know that stuff. At least collectively.2 And maybe missing the dependency links implicit in rarely used build options. But for the most part it's there.
1 Between the pandemic and our commitments taking care of honorary Grandma we'd been able to avoid this for some time. Now we will, no doubt, have to do the other Grandparents soon as well.
2 It is worth noticing that there are multiple classes of package managers and build dependency systems out there, handling independent (well, largely independent) and distinct (again, largely) ecosystems. To perform as envisioned the proposed tea protocol will need to be flexible enough to express relationships within and between all such groupings. Not easy stuff.
I contacted a support desk with an issue that I should have had instructions for but didn't. So far so good.
However, I followed up by asking a question about their response that I'd have answered for myself if only I'd scrolled beyond the page break. Not a good look.
In my defense there was a huge blob of whitespace at the botom of the page and I thought I'd reached the end of the document.1
Alas, after they poliely didn't tell me what an idiot I was being, I commited the "didn't read far enough" error again. Sigh.
Sorry guys. I did frontline support for a while and I feel for 'ya.
1 Because Word is paricularly crappy at layout even by word processor standards. One of the things I miss about academia is LaTeX: the typesetting and layout might be boring but they will avoid the easy misakes by default.
Aside: As opposed to using the build system or the template processor which are totaly different except in the ways they are completely the same.
Languages with C-derived syntax and exceptions generally have a try-catch construct and the ones I'm familiar with have a little trap for the inattentive programmer: the catch block is a different scope from the try blocks. Which means when you merrily write
try {
ErrorInfo e;
someRiskyOperation(e)
} catch (...) {
print("Risky operation failed with error %s\n",e.explanation());
}
because the argument to someRiskyOperation is an out-param1 and you hope to capture the error data that was generated before the exception was thrown, you actually get a compilation error because e isn't in scope when you try to issue the message.
Not a big problem, of course, at least two work-around are obvious.
Except that I tried to send a message to our logger, so the code looked like
try {
ErrorInfo e;
someRiskyOperation(e)
} catch (...) {
LOG_WARN("Risky operation failed with error " + e.explanation());
}
where LOG_WARN is a macro whose purpose is to capture the file and line where the error occured.2 And that's a problem if this code occurs in a library that can be compiled with logging support turned off by simply defining the logging macros as nulls: #define LOG_WARN(explanation) , because in that case the compiler never sees the offending e.explanation. It was rewritten as nothing even before lexing. So you can test the code with logging turned off to your hearts content and never find the bug. Sigh.
1 Yes, I agree: out-params are generally evil. It's a legacy API. Perhaps we'll get around to replacing it eventually.
2 When it actually does something it looks something like
#define LOG_WARN(explanation) do { \
logger:Message logmsg(__FILE__, __LINE__, explanation, logger::Warning); \
logger::getLogHandler().post(logmsg); \
while(false)
and it can't be a function because __FILE__ and __LINE__ are macros and have to be evaluated in place. Unless and until the language provides operators for capturing source position data like that this is the best we can do.
If you pick up the phone and call many businesses these days you find yourself talking to a computerized system before a human being. Such is the modern world, but a few thoughts keep coming back to me.
1 The reason is clear enough, unless they have a driving focus on customer experience they don't want to pay any call center people to sit around doing nothing, so they try to optimize their staffing so that the hold queue never never quite empties out. If their load consists of relatively few long call this means long waits for people calling in. They are optimizing for their interests at the cost of their customer, and how to make such call is a strategic choice for a business. But please don't lie to me: I notice and I care.
Today my news feed included yet another article about the terrible plight of hiring managers these days. The poor dears are being left high and dry by job seekers who don't care about their wasted time and don't feel the need to offer their victims even the common courtesy of a phone call or email. Or even a text message. Such unprofessional behavior! Who could credit it?
Or something like that.
I am aghast In theory. But not in reality.
You see I conducted professional job searches in 2004-5, 2007-8, 2012-13, and 2017-18; making somewhere between 250 and 300 applications in total. Consequently I have a reasonable statistical basis on which to make some observation of what "professional, business behavior" associated with hiring situations has actually turned into over the last decade and a half. Albeit, based on my memories rather than good records. You've been warned.
First a few observations about the large scale context:
Before we go on, I should mention that I've sat on hiring committees. I've sat in bed next to my loving spouse pouring over a slush pile of packets sorting out those that should never have been sent from those that at least come close to having the background we asked for. The next week I was working over a subset of them to select a set of promising prospects for deeper investigation.2 I've called references. I've sat through two rounds of telephone interviews and hosted the in-person appearances. I've debated the pros and cons of the multiple interviewees who were almost but not quite the candidate we wanted, each with their own strengths and weaknesses.
I know how painful, labor intensive, and demoralizing it can be to be on the hiring end of these things.
That said, I want to focus on a particular feature of the hiring system we've developed in these glittering first decades of the twenty-first century: in many, many cases the system is designed solely for the convenience of the hiring manager at the cost of the job seeker. First I have to register with a portal to start the process. Including, of course username3, password4, and recovery questions. No, you won't be able to re-use any of that; every employer has their own portal. Then not only should I upload my carefully formatted resume (or CV), cover letter, and other documents but I also need to copy the data therein to an endless series of web forms.5 Then I get to answer a set of true/false or multiple choice questions to confirm that I have the minimum requirements for the job.6,7 Then I'm lucky even to get an automated email confirming that the system received my application8 and even more lucky to receive further communications if I don't get called for an interview.9
Total time screwing around in the web interface: 30-60 minutes. Exclusive of (a) finding the prospect, (b) any research on the company you care to do, and (c) any customization of your packet materials you care to do.
The "painful, labor intensive, and demoralizing" bit I experienced when trying to hire was never a patch on what it was like to be a job seeker.
And there are three key points here. First, no one on the other end gives a fig how well this system works for the job seeker. Your blood, sweat, or tears are of no consequence to them. Second, while people are looking for a "fit" they care more about being able to identify a reasonable fit than about finding the perfect (or even a great) fit if it means more work to do it. And finally, the last fifteen plus years have been spent normalizing the idea that one side of this negotiation is allowed to drop the other side without a word. Some folks just imagined that only one side would ever exercise the option.
Ghosting your partner in this interactions is the standard of professional business behavior in the hiring game. Because a significant fraction of hiring managers have been working hard to make it so for decades.
Now, it's just possible that the people interviewed for these articles are the compassionate few who insisted on maintaining polite, if automated, contact with applicants up to the point that the position closed with those hopefuls still outside the door.10 It could be, but I doubt it.
I started this post with the intention of writing a sly observation on the reversal of fortunes. But somewhere along the way it turned into a bit of a rant. It seems I may have a little residual anger. Something on order of a coal-seem fire, perhaps. And I'm sure I'm not the only one.
In any case, schadenfreude is an ugly emotion and I try not to indulge, but sometimes it's very tempting.
1 And let's face it: those filters are utter trash. Natural language processing has come a notable way since the early 1990s but it is still better characterized as "artificial unintelligence" than AI. If you write it by hand you use word and phrase matching, and if you hand it over ot a ML system you get a more finely weighted word and phrase matching system. Either of which suck at seeing transferable skills and related experience. You can try to fix that with some kind of mapping systems but only if you can accurately anticipate what related experience and transferable skills will appear in your application pool. And of course, if you care to spend the not inconsiderable amount of money turning such predictions into work code would require.
2 I'm positive, both as a job seeker and a hiring committee member, that good candidates get screened at this step.
3 But not that one, it's already taken.
4 But not that one, it has characters we don't allow. Or doesn't have a character from this class. Or doesn't have characters from enough classes. Or whatever.
5 Occasionally the system tries to pre-populate the forms for you by parsing the documents you uploaded. I presume this works OK if you upload in Word format (but why would you upload something like that in an editable format?!?) and use a popular template.
6 Always after you've done all the other work.
7 Which means these things are hard fails with no chance for intelligent consideration of the other factors. A friend who chaired the IT security committee at a major public university and gave talks at major security conferences was ruled out of a position in IT security because he didn't have a master's degree. Of course, you could lie to the computer, but how will the hiring manager feel about that?
8 I'd guess this was roughly 50% of systems in my earliest search reported here and had dropped to less than 25% by my latest one.
9 A few systems do make it possible for you to log back in to track the progress of your applications. For those you actually have to hold on to that username/password pair you made.
10 I even had a handful of personal emails telling me I hadn't been selected back in the noughties. One person took the time to write what looked like a personalized encouraging message. Nothing like that in the teens, however.
We've had my in-laws here for the last week with our nephew for "Camp Cousins" to ensure that the youg'uns know one another. Lots of activities around the house: arts, crafts, games, and even an intoduction to Roblox development for the eight year old (which is why it had to be here and not in California where the in-laws live); and trips out to the zoo, aquarium, science museum, and even putt-putt.
I had shirts made. But they took longer than expected to come, so we didn't get them until Thursday and couldn't wear the to the zoo for the planned pictures. We rescheduled that for today (the last day). When the time came we headed out to the (new) planned location (where we could include the same mountains in the background as I had put on the shirts), only to find that it was starting rain (out of season) even as the dust storm continued (very much in season).
Rain and dust storm. Of course.
Given the possibility that the title could be taken as a pejorative, I should get a few things out of the way:
But ... those same bullet points explain why they get bagged on: their mistakes are highly visible, annoying, and they generally turn out to be something that some segment of the users consider to be "obvious". As in "How could anyone with half-a-brain not know that?!?" kind of obvious to some part of their audience. And they don't generally hear from the cohort who shares their ignorance.
The answer to that exasperated query is that it takes time, effort, and experience to become good at cross-disciplinary stuff. You need to know a few things in great depth, a larger number of things to moderate depth, and a little bit about a huge number of things. That takes time.
Now, twenty years ago web programming had a reputation for low barrier to entry. Is that still true? I don't hang around the right places to know what people say about it these days. But combining low barriers to entry with pretty high requirements for preparation is a recipe for disaster.
So, "What brought this on?" I hear you saying.
Well, not really because you're on the other side of the internet from me, I haven't hacked your microphone, and it's not clear that anyone actually reads this thing with any regularity. But I have a good imagination, so I hear you saying it anyway.
Setting my security questions and responses for a web site. Unfortunately,
Now, young programmers in my end of the business are pointed at a few documents early on to give them a starting familiarity with some of the more trap-laden parts of our work. Things like What Every Programmer Should Know About Floating-Point Arithmetic and What Every Programmer Should Know About Memory (PDF link) . I would have thought that Falsehoods Programmers Believe About Names and Falsehoods Programmers Believe About Addresses would be reasonably obvious candidates for the same role among web programmers. In fact these kinds of document make up a little genre of their own, and it's one worth taking a little time to explore. I promise you'll find one or two that you're guilty of.
Rather than hurling imprecations at web programmers in general, or even at the miscreant in this particular episode I'll just ask anyone going into web programming to find some resources for how to think about these things. Please.
Tension between conflicting goals is as much a part of software as it is of life in general. Today I am thinking in particular of the tension bewteen planning ahead and generality on one hand and KISS and YAGNI on the other. Plan too little and you either end up with multiple slightly incompatible implementations of parts of your design or you metaphorically paint yourself into a corner and have to redsign at a large scale. Plan too much and you both over complicate and waste time writing features you never use. Somewhere in the middle is a sweet spot that you aim for.
I've been working on reining in my tendency to overplan for some years, and I'm doing a lot better these days. Except for one one paricular case: making thing type-generic. If I'm writing a class and ask "Hmm ... what type of underlying data should this use?" and don't find an immediately obvious answer my first reaction is to type template <typename T>.
Looked at naively this is a good trade-off: the mental cost of writing and reading a simple template that just serves to defer the choice of underlying type is barely more than that for the untempalted code, and it increases the generality of the code. What's not to like?.
But there are hidden costs: increased compile times; latent bugs,1 and the need to chose between explcit declaration of desired instances and header-only code. And of course, header-only code makes the compile time issue worse. Now I'm aware of techniques like thin templates, but that negates my claim that the template isn't any harder to write or read than the untemaplated option.
Today, while I was waiting on yet another overly long build I had a long overdue insight. In most case that template class starts something like:
template <typename T>
class Thing
{
public:
using part_t = T;
//...
That is I've borrowed the habit of naming types related to my classes using type aliases (seen in the standard library and elsewhere). But here is the crucial observation: I could write Thing without templates and still use the type alias with a interim choice for the type:
class Thing
{
public:
using part_t = float; // Just pick something for now...
//...
If I change my mind about the type fixing it is a one-line edit.2 And if I find that I need multiple choices later coverting the class to a template is a straight forward refactoring step, but I don't pay the template costs until I actually make that call.
1 Even latent compile time bugs. I've had to fix compile-time bugs in code that's been in the repositoy for months because we finally instantiated it with a type where the bug surfaced.
2 As long as I am consistent in using the alias, but I'm trying to do that for readability anyway.
Another one that came up at work today. A method was behaving as if an argument was taking on it's default value even though there was an argument right there in the code.
Abstracted to it's bare essentials it starts with a method
class Thing {
// c'tors and so on
void method(const std::string & s1,
const std::string & s2 = "");
};which was called in a section of code that had significant history Thing thing;
thing.method("string"// oldWayToDeduceString(),
"second string");Do you see it?
Only one argument is being passed to Thing::method due to string concatenation and the comma that used to separate the first argument from the second being commented out. The compiler doesn't complain because the second argument takes on it's default value.
The real failure here (and it was mine, if you really need to know) was not removing the commented code after testing and before committing this code the last time 'round.
const accessor method that returns the result of a computations (i.e. is not accessing a feature of the current implementation but a feature of the model that can be deduced from stored elements of the implementation)const because it isn't changing any feature of the underlying model.const), but I did lose the const marking on the accessor because I didn't know about mutable.