3 ms·
I did a reasonably big rewrite from JavaScript (Nashorn, long story) to Kotlin/JVM recently (with 60x speedup and elimination of huge variance in runtime). Key
by barrkel 2y ago
I did a reasonably big rewrite from JavaScript (Nashorn, long story) to Kotlin/JVM recently (with 60x speedup and elimination of huge variance in runtime).
Keys to success in a larger scale translation:
- don't redesign anything, do a port (see also, Typescript compiler to Go port)
- leverage LLMs interactively: per chunk (e.g. function), copy the old code into a comment in the new code, then use LLM completion to quickly fill out the translation
- get something basic up and running ASAP that you can test, ideally data-driven (inputs, expectations) tuples, that you can write scaffolds for execution of the old and the new code
- for every method / control flow ported, add tests that target the newly added code, validating it does the same as the old code
Some of this may be less applicable to scripts or harder to apply to imperative code, for which you might want to spend time converting side-effecting actions into data that can be asserted on (e.g. instead of performing commands, emit a list of commands); do this refactoring on the old code before porting.
Don't get tempted into doing refactorings as you go. When you notice an opportunity to refactor, create a bug for it. What you don't want to do is build up a list of transformations that increases the more code you port, and makes finishing everything harder and harder.
- anonzzzies 2y ago> - don't redesign anything, do a port (see also, Typescript compiler to Go port) > Don't get tempted into doing refactorings as you go. I would say those are the most important. We did so many migrations in the past 30 years and the only ones that went ok were the ones that held to these rules. If you don't, you are rapidly stuck in a lot of pain and probably you won't be able to get out.
- nailer 2y agoDo add TODO comments about proposed refactorings for later though.
- datadrivenangel 2y ago110% this. Resist the urge to make changes until everything is moved over. Any system 'enhancements' may also be viewed as bugs/defects, and reduces trust, requiring lengthier validation.
- mooreds 2y ago> for every method / control flow ported, add tests that target the newly added code, validating it does the same as the old code Nice, and as a bonus you end up with a well tested system. Can't speak highly enough of data driven testing for this kind of system. Gives you such confidence. > When you notice an opportunity to refactor, create a bug for it. Did you have success in getting time to revisit all these bugs? Did you get pressure to fix them along the way (in either codebase)?
- barrkel 2y agoI think data driven tests are underused by engineers generally. One advantage that shines in a porting scenario is that they can be language agnostic. There was pressure from a reviewer in one area where the code could obviously be improved and I pushed back fairly hard in principle, but this was our first big project together and we were building trust, so I compromised in some leaf functions that presented the same API.