First, make sure none of your commits actually build out of the box; forget a file for a few revisions, accidentally check in a corrupted XML file, etc.
Create a "trunkV2" directory, and keep committing to both trunk and trunkV2. Add a third trunk inside the "branches" tree (/branches/featureX/newTrunk; I have seen this n practice, with random customer branches sprinkled in)
In the tree of the service that your program calls, do something different, for example by starting with a simple tag 'V1 frozen', adding the revisions of the V2 version and then occasionally unfreezing the V1 one by committing a combined "undo everything since V1" and "tiny fix to the v1 protocol that we thought was frozen", followed by an "undo that, and do something else" commit. Make sure to comment those commits as "version for customer X" and "bug fix #3 for customer Y"; do not mention "V1" or "V2".
Also, make sure that "customer X" has both V1 and V2 deployed, so that future developers cannot learn that "customer X" implies "version 2".
(and when I say 'saw happen', I mean 'I spent a week in Kiev at 12 degrees below freezing trying to figure out where the source code had gone'...we never found all of it)
I was also successfully able to export all of this to git with every deleted branch now still in existence.
short change cycles are easier to reason with.
Then when a dev checkout a branch in one repo, they need to find and checkout the matching branches in the other repos in order to build the project.
To make it more fun you can name the branches slightly differently from one repo to another, like "mybranch3" in one, and "my_branch3" in another.
Sometime a feature only affects one repository. That's fine - just create a branch there, and leave the other repo to the default branch - "master" (or sometime "release", unless it's "current_test", or maybe "dev-temp", or...).
Copy folder X, paste it and name it 'X-branch-<date>'
Make sure that <date> is not in the same format as any previously used, if you run out of formats, change the ordering or add your name, e.g.:
Much fun to be had there. Even just setting up PostgreSQL partition tables can defeat the most diligent maintainer (as they suddenly find RETURNING id_column fails everywhere).
1. Don't write fast running behavioural tests that verify the software is working as required.
With fast running tests I can maintain any old crap. Well, technically speaking I can rewrite it, but no-one will mind.
Part of the information contained in a test is the intent of the verification being performed, and part is code for mapping that intent onto the implementation. The latter part can be discarded during a rewrite. Cucumber/SpecFlow etc. make the difference between these explicit.
Wait, what?! The more I listen people talking about TDD, the more I discover I always misunderstood it, and the less I want to actually understand it.
Try that on multiple teams across timezones actively developing multiple branches, with big merges on a weekly basis.
"Rewrite module X" never happens. Even if you have a healthy suite of behavioral tests, it will still feel brittle because rewriting large sections of code will inevitably bite you in the ass.
And no you can't say "you're merging main into your branch? your responsibility."
The guy has an e-mail address hosted at a top level domain. 1999 was a silly time.
I thought I was doing well to have my name be a valid domain: https://david.kitchen/
If you support multiple countries this is probably an inevitability. Same with province vs state, potentially others.
I guess you could have one variable called "postalCode" and one called "zip", but that seems potentially more confusing.
Also, sometimes your UI shifts - should all your code change then? Because the boss wants to call something different in the UI? "We were calling them admins, now we want to call them CSR." Is it time to write a regexp to rename everything?
"Never document gotchas in the code. If you suspect there may be a bug in a class, keep it to yourself. [...] Remember the words of Thumper "If you can't say anything nice, don't say anything at all". What if the programmer who wrote that code saw your comments? What if the owner of the company saw them? What if a customer did? You could get yourself fired."
P R I N T S (A,L)=1,(S,T)=I N G
G I V E N A
O F A=L:L:S Q:U=A R E S B=E L O W (A*A),!
I S (U,R,E)=T H 1 N K I T=S G O O D
Am wondering when our industry will see this forest for the trees...
The quest for other program representations is still open. The state of the art uses text as "storage" format plus an IDE that does some semantic analysis to help the developer navigate. Many of the ideas mentined in the article (navigation, coloring, auto-format) have been integrated into IDEs and editors.
With almost 20 years of research between the article then and now, what semantic techniques are you dreaming of in your development environment? What are you missing? What feature would greatly improve your productivity (but is possibly too costly to implement by yourself)?
I'm aware that this is from 1997-1999, but I'm curious: Do people still print out source code for better reading?
More seriously, there were discussions of library versioning schemes, backward compatibility etc.
I see Susan no longer lectures, which is a shame, as she was one of my favourite lecturers.
(The replacement course seems to be this: http://www.imperial.ac.uk/computing/current-students/courses... )
For me it's much easier to focus if I take my printouts and get away from the computer and edit and write code by hand, then go back and type in the changes.
I started doing this when I thought back to times I programmed back in high school and college and remembered that I'd always had the most success with programs working correctly when I'd written them out by hand before typing them in. I think it forces me to really think about what's happening, rather than just trying stuff until things "mostly" work.
I find that when I'm sitting at the computer, I have a much more iterative style, where I try something, see how that went, and make changes. When I'm working out something away from the computer, I have to have a coherent mental model of what I'm trying to accomplish.
So at the computer is good for experimenting and exploration, away from the computer is good for coherent designs.
I think there's something analogous with languages, I find dynamic languages much easier to deal with when I'm sitting at the computer, but if I'm working away from the computer on paper, then I prefer languages like SML or OCaml (or maybe even Go?) where I can look at the code and work through in my head exactly what is going on.
Tangent: speaking from personal experience, sifting through an existing foreign code base is a really exciting task for some people, figuring out what makes it tick and how the pieces fit together can be fun. Granted, I was reverse-engineering a closed-source product, not reading its actual source, but that was even more fun :D Come to think of it, the tool I used for that, IDA Pro, has some interesting features that IDEs don't, such as graphical representations of function call graphs  and function basic blocks . It would be interesting to see what a creative person could do by integrating those into a regular IDE.
> Do people still print out source code for better reading?
It's easier to solve a problem when you remove all the fluff and noise. On the other hand, you won't know if you have a good solution until it's implemented. A bit of a trade-off.
I know a bunch of embedded C programmers who have been doing it for a long time who do this regularly. They know their stuff. They don't print out the whole codebase, just a few pages of whatever they're working on, then they annotate it with a pen while thinking about whatever problems they are solving.
>then they annotate it with a pen while thinking about whatever problems they are solving.
Paper and pen offer a lot of options you don't have in vim (or emacs/notepad.exe/etc ;)). Circling, doodling, arrows, underlining, furiously scribbling...
These are all good red flags to check for in existing code bases before you join a team. If you see them, chances are their code review process is poor or non-existent and you'll be fighting a battle against crap code every single day.