I had huge success writing a trading system where everything went through the same `on_event(Inputs) -> Outputs` function of the core and a thin shell was translating everything to inputs and the outputs to actions. I actually had a handful of these components communicating via message passing.
This worked rather well as most of the input is async messages anyway, but building anything else this way feels very tiresome.
Usually two methods `onMessage(long timeNow, byte[] buf)` and `onTimer(long timeNow, int timerId)`.
All output sinks and a scheduler need to be passed in on construction of the application.
Then you can record all inputs to a file. Outputs don’t need to be recorded because the inputs can be replayed but it is useful for easier analysis when bugs happen.
I have even worked on systems where there were tools that you could paste recorded input and outputs to and they code generated the source code for a unit test. Super useful for reproducing issues quickly.
But you are spot on in that there is an overhead. For example, if you want to open a TCP socket and then read and write to it, you need to create a separate service and serialise all the inputs and outputs in a way that can be recorded and replayed.
I think I read here on hackernews that the Mona Lisa doesn't look at all like it did when it was freshly made. If I look at the restored copy https://en.wikipedia.org/wiki/Mona_Lisa_(Prado)#, I at least find the silk very nice.
Yeah, I work on avionics software where we sometimes need to support old releases with fixes for many years, and this is basically how we do it. Essentially maintaining multiple trunks and only backporting changes needed by customers using the old releases (there is a high bar so it has to be something like a security fix or an important bug fix)
we have a "release" branch and a "develop" branch. The release is trunked on the last released version and (in theory) only gets fixes. If we need to fix a more older version, we create a temporary branch on that version to fix it, and we cherry pick the fixes (or merge to) to release branch and then to develop branch.
The triple mortal loop, comes that we have two versions of the product. One with the old no responsive frontend and other with a modern responsive frontend. And we need to release and develop the two versions for sometime, before the direction decides to kill the old no responsive version. So we end with 4 branches: release, release_rwd, develop and develop_rwd. If we fix something in release, we need to do a diamond merge : release to release_rwd, release to develop, release_rwd to develop_rwd and develop to develop_rwd
reply