In my first real job, I worked for a company that maintained a large legacy product programmed in a combination of COBOL and Java.
In order to work on the Java side of the product, you checked out individual files from source control to work on, which 'locked' the files and prevented other developers from checking out the same files. This functionality was not part of our actual source control system, but was instead accomplished with a series of csh shell scripts you could run after ssh'ing into our development server.
Each of our customers had a 'master' jar file that represented the actual final compiled product (a jar file is really a zip file archive, which bundles together the resulting compiled java class files).
Once you had finished implementing your code changes, you ran another set of scripts which found the master jar file for each customer, unzips it, copies the compiled files from your local machine into it, and zips it back up again. Finally the source control lock is released.
This means, effectively, that the codebase was never compiled as a whole at any point in the process, instead, we just manually patched the jar file over time with individually compiled class files.
Over the years, small errors in the process allowed a huge amount of inconsistencies to creep into the codebase. Race conditions would allow two developers to lock the same file at once, or a developer would change a class that was a dependency of some other code that somebody else was changing. Sometimes code changes would make it into some of the customer jar files, but not others. Nobody knew why.
It took a small team two years to migrate the entire codebase to git with proper CI, and a huge chunk of that time was reproducing a version of the codebase that actually compiled properly as a whole. After the project was finished, I resigned.
So they had a problem, got 2 years of approved development effort of a small team to solve it property which they did successfully, and then you resigned? After they fixed the problem?
Of course where they started was just awful but a place that recognized it's problems, commits to fixing it, and has sufficient competency to actually fix it sounds rather nice to me. Many orgs get stuck at step 1.
I presume there were other reasons for resigning, or you just like massive refactoring projects.
It was a little tongue in cheek, but yes. I had large grievances with the software culture there, but after I got sign off on the project to modernise our build process, I couldn't bring myself to abandon ship in the middle of trying to fix it.
After everything was finished up, I was feeling burnt out and realised that I'd held on for too long at a company with a fundamentally bad culture that wasn't going to change just because the tech did, so I moved on.
Thank you for the clarification. Because you said “it took a small team … and then I resigned”, it was unclear that you were part of that small team and instead made it sound like you left because the problem was fixed.
I worked at a company recently where I couldn't get a team to do the fairly simple task of cleaning up our git ignore (so we wouldn't have to painstakingly add certain files to the index every time we changed something) so I take it as a massive accomplishment moving to git within two years.
If I know anything about work, I doubt this is all they did for two years. Business doesn't care you have an important project. They will bug you to do other things.
Had a similar thing on a small team at a bigger company. We didn't have any type of version control so the team did all development on a shared dev server that we SSH'd into. We'd use vim to edit files one at a time and rely on vim's file locking to make sure that we weren't editing anything at the same time as anybody else.
Oddly, the project was one of the best I've ever worked on.
I recall something similar from my first job, except the shared file locking was a full on feature in Macromedia dreamweaver.
CSS was just starting to get adopted and every project we worked on just had one “gobal.css” file. When someone else had global.css locked, you’d call dibs if you needed it next. Inevitably, everyday someone would leave the office and forget to unlock global.css and no one else could get anything done.
Macromedia flash / .fla files weren't particularly ideal for collaboration either, though I still feel a bit nostalgic for working with flash in general
SVN provided the ability to steal locks, and locks were opt-in so e.g. you wouldn't have made CSS need locks because it's a text file and merges fine. Mandatory locking was mostly for binary work files e.g. PSD and the like.
I think a lot of people who've only learned programming in the last 10 years or so don't realize that Git, and even more so the large-scale popularity of Git, is actually pretty new. A lot of programming happened before Git was created, and before it became mature and popular enough to be the default for everyone.
Many of these earlier systems sound terrible and hacky to us, but they were the best that was available at the time. Systems to "lock" files you were working on were pretty common because basically nobody did merges well. Most of them were based on having a server to manage the whole thing too, so they were only really common in corporations and larger and more mature hobbyist teams - this was also before you could spin up a cloud server for most things with a few keystrokes and $5 a month. It's low-effort to spin up a local Git repo to track your work on a tiny personal project, but nobody's going to set up a CVS server for that.
Anybody remember Joel On Software's 12 Steps [0], written in the year 2000, 5 years before the Git project was started? Where "use source control" is Step 1? There's a reason why that's there - at the time it was written, source control was clunky and a pain in the ass to set up, so a lot of smaller companies or ones with less mature development teams never got around to it.
I may be getting a little "old man yells at clouds" here, but be really thankful that Git is FOSS, ubiquitous, works great for 98% of projects, and is superlatively awesome compared to everything that came before it.
I use CVS, RCS and Subversion on my personal projects for several years before I learned git. I don’t remember any of them being a pain to setup for small projects and Sourceforge provided free CVS hosting for small projects.
I started with Rational Clearcase, which I interacted with via Eclipse, and I remember that you did have to lock a file to make changes to it... pretty sure there was no merge capability (but maybe I was just too junior to know stuff like that, it was definitely not something you would do as a matter of routine, like we do now with git). Someone leaving for vacation and forgetting to unlock a file could be a huge pain in the ass.
After that I used Subversion via TortoiseSVN for Windows, which was quite nice to use, though I don't really remember much of the details... I do remember asking myself why everyone was moving to git when "perfectly good" source control already existed, but after 10+ years on Git, I think I was wrong and we did need it, we just didn't know it yet.
Rational Clearcase is a disaster but you could do merges.
The fun/frustrating part was getting branching and "views" correct.
I worked at an organization on this side of the century where it was one person's full-time job to handle merging code from different teams. The same organization didn't actually use raw Clearcase either -- it was wrapped in hundreds-of-thousands-of-lines-of Perl scripts.
I've never actually set up CVS myself, so I suppose I can't accurately say how easy or not easy it is. The "nobody" might deserve an asterisk - I'm sure it's not literally not a single person, but it seems to be pretty rare in my impression. Nevertheless, AFAIK, the non-distributed nature seems pretty limiting.
In Git, I can just create a local repo for anything, and I don't have to decide where I want it. I could never push it anywhere, or push it to a private hosted repo to collaborate with a person or team, or push it to a public repo to open-source it, and change between any of those at any time. I don't think you can really do that with these hosted systems. You could spin up a local CVS server if you really wanted to, but if you later decided you wanted to open-source it on Sourceforge, don't you have to abandon the history and publish it there as-is?
I don’t think so, it’s been a while, but I think there were tools for copying history between cvs servers. I don’t remember CVS being particularly difficult to manage.
I’ve used Clearcasse in 2006 and it had all the branches that we needed. We didn’t use locks because that was annoying. It was at Deutsche Bank and we were 200.
When I moved to SVN, it was a regression. I really don’t understand why people describe SVN as cutting-edge (and why people didn’t like Clear Case).
I once worked at a corp that sold software. For the exact same software product, maybe 10-20% of customers received so much benefit we could have charged 2-3x the price and they would still be very happy. On the other end, for maybe 10-30+%, the exact same product ranged from painful to a disaster. Often because they would try to force it to work the way their pre-existing paradigms worked instead of taking the time to learn how it actually worked.
> source control was clunky and a pain in the ass to set up
I concur. Creating a CVS repository was not harder than creating a git repository now `cvs -d $dir init`, and using, typical for the time, shared network drive, gives server experience without setting up a specialized server. It was just not included with Windows/typical Windows dev tools, so you had to know it existed, and knowledge was slower and harder to get.
Even those before git - what they're describing sounds a bit like RCS, the precursor to CVS, which came before SVN.
I've never used RCS or CVS myself, but I remember the file locking thing in descriptions of it, and that it was why CVS was named "concurrent" - it fixed that limitation.
This sounds so much like dealing with MS Access databases... Unfortunately, part of my responsibility in my current role is to manage a handful of Access applications... they are ancient, I am talking early 2000's. They are the most unruly thing I have ever had to work with, and I will not go into details but your story reminds me so much of having to work on these apps...
MSAccess is a tragedy, imo. Right-up until, say, Access 2007, it was a simple (in a good way!) RAD platform following those zombie 4GL predecessors, but it’s been left to stagnate without any real effort to modernise it, and it’s clear from how Microsoft’s been downplaying Access that it’s a product they’d really rather not have to support, but they know if they do kill it then it would weaken on-prem Office’s moat and everyone will probably just rush to Google Firebase.
Most of Access’ problem is how it’s inseparable from both VBA and COM. While Microsoft has tried to make COM sexy again with WinRT and C++/CX, VBA is quite senile now. Microsoft has killed VBA in Outlook, killed VBScript in Windows Server, and is now trying to kill VBA in Excel too. MS is pitching modern JS as a successor (which I’m not too mad about…) but I just don’t see how JS could unseat the sheer volume of Access VBA out there. Especially as “Office JS” is intentionally kneecapped for things like local computer files and Win32 so it has feature parity on web vs mobile app vs desktop - it’s going to be awful.
> It took a small team two years to migrate the entire codebase to git with proper CI
I'm amazed they even allowed people to spend company time and money doing this. Corporations tend to not see the value in improving such precarious situations as long as the software keeps working. They just want employees to cope and accept the messiness. People usually cope by quitting.
I’ve worked on “check out” code bases very similar to this. I mean. Nothing so insane as scripts patching class files in to jars Willy nilly, but it seems the “just check out a file so nobody else can work on it” thing is a “common” “solution” to this.
I am interested in how you managed it when someone had to hold code for years (as I’ve seen)? Basically, we also had a way to share control with one other person, and the person who was taking the second source were responsible for updating both versions at the same time manually (which never happened, so implementing a large project that touched hundreds of source files had to dedicate a couple weeks to manually hand comparing files, manually implementing the changes, and then manually retesting)
> In my first real job, I worked for a company that maintained a large legacy product programmed in a combination of COBOL and Java.
> In order to work on the Java side of the product, you checked out individual files from source control to work on, which 'locked' the files and prevented other developers from checking out the same files.
COBOL + Java and file lock... I thought we worked on the same project and it brought back many nightmares!
But we were using Subversion's lock system and had a proper CI/CD with Jenkins.
Did you know, theres a GitHub repo called [you-poor-bastard](https://github.com/SirkleZero/you-poor-bastard)? It converts a vss repo to git (not very well, but well enough), ignoring the VSS "passwords."
IIRC SourceSafe could be configured with strict locking or advisory locking? I might be wrong about that.
The admin user could override or unlock locked files. We had to do this if a developer left a file checked out after they left, or were on vacation. Nobody knew the admin password for the SourceSafe repository. That was OK though, all you had to do was make a local account on your PC named the same as a the source safe admin acccount, and you'd have admin access in SourceSafe.
> IIRC SourceSafe could be configured with strict locking or advisory locking? I might be wrong about that.
IIRC SourceSafe could be configured with either strict locking (you had to lock a file in order to edit it) or no locking à la SVN (the tool would check if your file was up to date when trying to commit it).
I recall that I spent a while suffering under strict locking at my first internship before a colleague discovered this mode existed and we were able to work more reasonably (there were no editable binary files so locking was never really needed).
We still use VSS for a couple codebases. We’re a small enough team that conflicts are rare, but the occasional Teams message “hey, let me know when you’re done with module.cpp” is not unheard of.
I'm so sorry. We were using it in the late 90s, and on a monthly basis it would be down for a day or two while the admin plunged out the database. Good times.
The crux of Atkinson's argument seems to be that the upfront emissions from the manufacturing process, and shorter lifespan of electric vehicles, does not make up for the reduction in tailpipe emissions.
Is this true? I know that the Tesla Impact report [0] refutes this, stating
> "While EVs today still emit more greenhouse gases during the manufacturing phase, including emissions from the supply chain, it takes less than two years' worth of driving before the total emissions from an EV fall below that of a comparable ICE vehicle."
If you'd like to read more about the roots of Effective Altruism, ranging from old mailing lists, LessWrong, bitcoin, cults, AI and the surprising connections to many well known figures in tech, I highly recommend the 7-part Extropia's Childen series from Jon Evans [1]
This feels like the endless debate about whether America is forever tainted by the sins of its founding fathers.
I’m pro-American because I believe in its stated values. Moreover, I believe that despite original and continuing failures to perfectly reflect those values, there is large and concrete progress in aggregate.
I feel the same way about EA: I aspire to their ideals (including the continued discussion and reconsideration of those ideals) and believe the weight of thousands of people quietly moving concretely in the right direction far exceeds the damage of bad actors (who would have twisted any ideology they were immersed in).
So the bad actors should be punished. The parts of the community system which failed should be changed. AND the many others who are earnestly trying to live according to these values should be judged according to their _own_ impact.
I can’t imagine having the optimism you have. My rude mind is thinking this person is naive but you know I’m pretty naive too haha!
I disagree and think both the US and institutions like EA are too tainted. The US hasn’t done anything about slavery except make things worse still. That’s not on the founding fathers any more only. It’s on the US since the civil war. EA will take money from future multimillionaire and billionaires. Much like the US, they are both completely controlled by capitalism. I am in the US but not pro US.
Golly. I'm on part 2 and it sounds like they're about to invent Scientology.
> The full post goes into more depth and nuance, but it's worth stressing how heavily Leverage relied on “debugging,” based on Anders's “Connection Theory.” Debugging consisted of — to paraphrase and oversimplify — opening up one's psyche, history, self, and emotional core to maximum vulnerability, generally to one's hierarchical superior, and then doing all you could to follow their suggestions to “fix” your mind.
Incredible letter, I had no idea about the SWATing. Tbh the Epstein donation seems like a nothingburger compared to the other allegations in that letter.
Admittedly I don’t follow this rationalist thing on the internet at all, so I don’t know what’s going on with them. But that was hell of a read. I am no stranger to people being dicks, but still, that all is just sick.
This is all cult-like behavior, reminds me of the much documented Lyndon Larouche 'creative mentation' stuff, and pretty much any cult in their stage of grilling people to take down their preconceived notions.
Now with this info, that's all I need to know about these characters.
I'm generally bearish on AI, but I do feel that there are going to be a surprising number of applications where 'good enough' results are actually perfectly fine.
In particular, a couple of industries that I think are likely to get disrupted in the next few years are stock art, and the art-by-commission scene. The ability to use a Stable Diffusion + Dreambooth style setup to easily generate new artwork in the style of your favourite artist that's "good enough" is incredibly powerful.
Slightly tangential but I've worked for several companies now that use `make` as a simple command runner, and I have to say it's been a boon.
Being able to drop into any repo at work and expect that `make init`, `make test` and `make start` will by convention always work no matter what the underlying language or technology is, has saved me a lot of time.
I've worked on a few projects that apply this pattern of using a Makefile to define and run imperative commands. A few people develop the pattern independently, then it gets proliferated through the company as part of the boilerplate into new repositories. It's not a terrible pattern, it's just a bit strange.
For many junior colleagues, this pattern is the first time they've ever encountered make -- hijacked as some kind of imperative command runner.
It's quite rare to run into someone who is aware that make can be used to define rules for producing files from other files.
I find it all a bit odd. Of course, no-one is born knowing about middle-aged build tools.
i'm talking working on projects with people whose first encounter with make is in a project where someone else has defined a Makefile to wrap imperative actions, e.g. `make run-unit-tests`, `make deploy`. If they think about make at all, there's a good chance they think make is for performing imperative actions, and has nothing specifically to do with producing files from other files using rules and a dependency graph, or the idea of a target being a file, or a target being out of date.
This is what I do for all non-rust projects. I knew what it was supposed to do, but wow if it took me forever to figure out how to do it (the connection between rule name and file name is really poorly documented in tutorials, probably should've just read the man page)
This was the nicest thing about blaze at google. I'm a big believer that having a single standard tool for things is a huge value add, regardless of what the tool is. I didn't really like blaze particularly, and I don't really like make particularly, but it's amazing to just have a single standard that everybody uses, no matter what it is.
No, I believe GP is advocating against language-specific tools being the standard. In the ideal world you would have a Makefile that calls cargo so "make" still works like it does identically in the js or python or golang repos.
Conventions are great, but that doesn't look like anything specific to make, a shell wrapper could do that:
#!/bin/sh
case $1 in
init)
... do whatever for each project init
;;
start)
... do whatever for each project start
;;
test)
... do whatever for each project tests
;;
*)
echo "Usage: $0 init|start|test" >&2
exit 1
;;
esac
In my home/personal projects I use a similar convention (clean, deploy, update, start, stop, test...), I call those little sh scripts in the root of the repo "runme".
The advantage could be, maybe, no need to install make if not present, and no need to learn make stuff if you don't know it.
Sometimes they don't match the usual words (deploy, start, stop, etc) but then I know that if I don't remember them, I just type ./runme and get the help.
For my scenario, it's perfect because of it's simplicity.
Complete with automatic parallelization if you ask for it! And automatic KEY=VALUE command line parsing, default echoing of commands (easily silenced), default barf on subprocess failure (easily bypassed). The variable system also interacts reasonably sensibly with the environment.
I've never rated Make for building C programs, but it's pretty good as a convenient cross-platform shell-agnostic task runner. There are also several minimal-dependency builds for Windows, that mean you can just add the exe to your repo and forget about it.
To tell the truth, make sucks incredibly for building modern C programs. There are just too many targets. It's why all of them generate their makefile with some abomination.
True, that's where Make shines. Though given the popularity of so many Make alternatives (the strictly subset of command runner variety, like just[1]) who keep its syntax but not this mechanism, I wonder if for command runner unnecessarily re-running dependencies is really a big deal. Because quite often the tasks are simple and idempotent anyway, and then it's a bit of a hassle to artificially back the target by a dummy file in Make (which your example doesn't do here e.g.).
> I wonder if for command runner unnecessarily re-running dependencies is really a big deal.
I've used in in the past with python/django roughly like so (untested from memory, there may be a "last modified" bug in here that still makes something run unnecessarily):
Setting up these prerequisites takes a while and doing every time you start the dev server would be a pain, but not doing it and forgetting when requirements were updated is also a pain. This would handle both.
Specifies order without a hard more-recent-than dependency on everything after the |. So if the timestamp on "environ" is updated, that won't cause the "environ/lib" recipe to run, but if they both have to run then it ensures "environ" happens before "environ/lib".
It might not be necessary for this example, but I've found being more liberal with this feature and manually using "touch" has been more reliable in stopping unnecessary re-runs when the recipe target and dependency are directories instead of just files.
+1 for this, free autocomplete is the reason that I love using Make as the top-level tool, even if the actual heavy lifting is done by CMake or something.
This is standard in Node.js ecosystem and I love it. Each package has scripts in package.json that you can run with npm run [name], and some of these like start, test or build (and more) are standardized. It's really great DX.
I did this for a while but make isn't well suited for this use case. What I ended up doing is have a shell script with a bunch of functions in it. Functions can automatically become a callable command (with a way to make private functions if you want) with pretty much no boilerplate code or arg parsing. You can even auto-generate a help menu using compgen.
The benefit of this is it's just shell scripting so you can use shell features like $@ to pass args to another command and everything else the shell has to offer.
Nice shell script. It’s rare to see one written so well. I’ll add you to my list of people I can still count on one hand that properly quote variables.
If I had to pick one nit, and it’s a stylistic choice, you use braces around variable names where they aren’t strictly needed.
I agree whole-heartedly with OP's use of "braces around variable names where they aren’t strictly needed". I have two reasons. First, consistency is nice. Second, they aren't needed now, but invariably you will end up coming back and adding to the script, and will end up needing them.
OK, maybe I have 3 [I mean 4] reasons. 3) if you always put the braces in, it won't break your script when they aren't required. However, if you don't put the braces in when they are required. it will break your script. 4) often putting the braces in when they are not required makes the script easier for me to read. I often use spacing that is not required for the same reason.
I'm not saying I never break my own "rules" (they are really more guidelines than rules). You will find variable names used in my shell scripts that have no surrounding braces, but I probably use more of the "unnecessary" ones than a lot of people do. And yes, I'm aware that sometimes not having them makes me less consistent. Everything has a balance, people just differ on what style provides the balance they prefer.
My thought process around using braces when they're not needed is mainly around consistency. If you pick and choose when to add them then you need to make a decision every time you add a variable. I've written about that here: https://nickjanetakis.com/blog/why-you-should-put-braces-aro...
That is a good call about `set -u`, it's something I've been using more recently but I haven't added it into that script yet but thanks for the reminder, I will soon. I ended up making a post about that here: https://nickjanetakis.com/blog/prevent-unset-variables-in-yo...
Another small thing I've been doing recently is defining options like this:
set -o errexit
set -o pipefail
set -o nounset
It's a little more explicit on what each option does. It might be just enough context to avoid having to look up what something does. Philosophy wise that's also something I've been doing semi-recently which is to use long form flags over short flags in scripts https://nickjanetakis.com/blog/when-to-use-long-word-or-shor....
It adds too much visual noise for me, especially since you already need to double-quote the variables to protect against whitespace expansion. The rules around when braces are needed are simple so I leave them off when they aren't necessary. The rules around when double-quotes are needed are much more subtle, so I almost always use double-quotes, even when they aren't needed. e.g.
foo=$bar # quoting not needed but I'd still do this:
foo="$bar"
A bug-bear of mine is unquoted variables especially with braces, even when using them for optional args:
${TTY}
Using your original script as an example, I'd prefer this:
dc_exec=(docker-compose "${DC:-exec}")
dc_run=(docker-compose run)
if [[ ! -t ]]; then
# we have no TTY so we're probably running under CI
# which means we need to disable TTY docker allocation
dc_exec=("${dc_exec[@]}" --no-TTY)
dc_run=("${dc_run[@]}" --no-TTY)
fi
_dc() {
"${dc_exec[@]}" "$@"
}
_build_run_down() {
docker-compose build
"${dc_run[@]}" "$@"
docker-compose down
}
Of course, this uses bash arrays and isn't POSIX. But the ergonomics of using an array for construction a long command are so much nicer than backslashes or long lines that I use them all the time now.
The postgres variables are sourced in the line above I use them, they will always be set. It's a hard requirement of the Docker postgres image. I did end up pushing up the nounset change and it didn't complain about it since it's set from being sourced.
I'm not personally a fan of videos, but I have plenty of collegeues who are that I'm going to happily start pointing at your videos. Some of these will be very handy references I can add to code reviews.
A paper I read recently (Harper 2016 - 10.1089/space.2015.0029) has numbers based on the supplies needed to the ISS.
The gist was, "Without some sort of recycling and/or use of in situ resources, meeting the lunar settlement goal of 100 people would require delivery of over 1 million kilograms of life-support consumables per year."
And then assuming a PLSS life support system you get to to needing about 5500kg of consumables delivered per person per year.
So ~5T/person/year, let's plug in the Starship launch costs: at $1mn/T, this is only $500mn/year for the whole base. This seems a little too good to be true.
Isn't this pretty much the point of such an endeavor though, or at least part of one?
There's a lot of science we'd like to do on the moon, chief of which would be to actually test the space-settlement self-sufficiency problems in an environment like that.
With the ISS as comparison, it's not going to be "bam 100 people" it's pretty obviously going to be a process of rotating in progressively larger crews while the systems and bottlenecks are worked out. Not to mention we'll benefit a lot from the sort of focused sustainability research this will generate.
there are experiments with moon simulant and mars simulant. both show that with proper prep, regolith is a sufficient grow medium. just as is, it sucks, but if you wash, and then fertilize, it will work. and then after the initial prep, you treat it like you would other soil.
Netflix also seems to take into account the language your profile is set to as well, so you may get more/different subtitle choices if you change your profile language. See https://help.netflix.com/en/node/101798
For myself, I would think that the best way to compel kids (and adults) to be more interested in learning and personal development is to relate it to their sense of identity.
People want to emulate their heroes and live into who they feel they are. The 'school nerd' phenomenon is one we're probably most familiar with; if you start seeing your identity as being a 'nerd' of the school, you tend to live into it even more. If you can somehow leverage that effect, it can be fairly powerful.
And then of course, just making learning fun, entertaining and a normal part of life and not just for school would certainly help. I read recreationally very early on because that was just normal in my home environment.
Overall, I'd worry less about making students feel good or bad over individual tasks, and pay more attention to fostering their desire to be the kind of person that needs to learn.
Earlier this year I spent roughly three months job hunting exclusively through cold-emails based on Who's Hiring posts (I'm in the London area). I applied for 10 positions (and got my 10th - at a fairly large media company)
Some numbers of reasons that I felt I didn't get through the hiring process at the positions I applied for:
* Company changed their mind hiring for the position - 3 cases
* Didn't get through due to insufficient experience - 2 cases
* Didn't get through due to for poor performance on the hiring test - 3 cases
* No response received - 1 case
These numbers are a bit flaky since in the end it's a combination of factors that results in a yes/no decision. But I tried to roughly divide them into what I felt was the main "deciding factor" of the interview process.
For background, I'm a backend / "full stack" developer with 5 years experience (Most of the places that I got filtered out for experience reasons were because I didn't have enough of Brand X, etc)
Were there any hints you noticed in retrospect that the insufficient experience or a bad hiring test results were probable? If I could somehow predict those experiences up front I think it would save myself and them time and anxiety by stopping short. The best I have on the experience bit is just being very honest up front with how familiar with that Brand I am rather than trying to skate by and stretch the truth e.g. "I can do C with classes so I know C++!"
In my first real job, I worked for a company that maintained a large legacy product programmed in a combination of COBOL and Java.
In order to work on the Java side of the product, you checked out individual files from source control to work on, which 'locked' the files and prevented other developers from checking out the same files. This functionality was not part of our actual source control system, but was instead accomplished with a series of csh shell scripts you could run after ssh'ing into our development server.
Each of our customers had a 'master' jar file that represented the actual final compiled product (a jar file is really a zip file archive, which bundles together the resulting compiled java class files).
Once you had finished implementing your code changes, you ran another set of scripts which found the master jar file for each customer, unzips it, copies the compiled files from your local machine into it, and zips it back up again. Finally the source control lock is released.
This means, effectively, that the codebase was never compiled as a whole at any point in the process, instead, we just manually patched the jar file over time with individually compiled class files.
Over the years, small errors in the process allowed a huge amount of inconsistencies to creep into the codebase. Race conditions would allow two developers to lock the same file at once, or a developer would change a class that was a dependency of some other code that somebody else was changing. Sometimes code changes would make it into some of the customer jar files, but not others. Nobody knew why.
It took a small team two years to migrate the entire codebase to git with proper CI, and a huge chunk of that time was reproducing a version of the codebase that actually compiled properly as a whole. After the project was finished, I resigned.