1

I'm writing a PHP application where a block/module of domain logic is subject to frequent, significant changes over time.

The complication is the application needs to be able to use not just the latest version of the module, but any version that it has previously used, so it can reproduce the results of data that that version would have made.

I would use a facade and/or adapters or similar so the application's main code can switch between which versions of the module it uses without too much trouble.

As for the module, I was planning to use namespacing for each major revision (where the domain logic produces different results); duplicating all the classes in that domain logic module. I.e. effectively copy-and-paste the entire thing, including classes within the module that haven't changed.

This is a pungent code smell and I can't think of any way round it, let alone a simple way, given that the module may also undergo complete restructuring.

Any ideas?

2

Sounds like you need the strategy pattern. Basically, define an interface that all instances of your business logic can use, then invoke the proper instance (strategy) of the logic. Determination of what constitutes the "proper" instance is up to you, usually it's an attribute in the request header, but it could be contextual.

0

Preserve an external API over time. Even if it's subpar, make it consistent. Then, build a factory that accepts a date (or version number) and returns the appropriate implementation, with the same consistent API.

0

I'm wondering why you would WANT to do that. If your requirement is to display the result of your previous domain logic, you might be better off to simply store the output in some immutable form and display it.

For example, let's assume you are building a system that does price calculations for orders and these calculations are subject to government regulation and, hence, might change over time. It is a lot easier to simply store the previous orders as a PDF, for example, rather than recalculate the results every time. (In fact, from some legal standpoints this might even be a requirement)

If you have thought long and hard about your implementation and you find that you DO need to re-run the logic, isolate it in a separate library. Annotate your data so you know what library to run it against. Create a facade that you can pass data through and does the switching between different versions of the library. Using version control you just tag the version of the library, build your library, deploy and move on. There will never be a need to go back and change a previous version of a library because you always need to keep the old logic going. Simply code your changes onto the code as-is and use source control to look back at previous versions should the need arise.

  • I have been in a similar situation before, and it can be a desire to compare results using a previous algorithm versus the current algorithm. That is, "The old recommendation system would have recommended a 5% reduction, whereas the new recommendation system recommends a 1% increase." (Against new data, of course.) – asthasr Oct 1 '15 at 12:09
  • That option isn't ruled out by storing the results of the previous algorithm. You can always feed the same data into four or five versions just to see what comes out and compare them, doesn't mean your previous results based on the older data that was available at the time should always be re-calculated... – JDT Oct 1 '15 at 12:15
  • Sure, but I don't really see the implication in the question that they're not storing the original calculation. In my experience, it tends to be stored with a version marker, and you can then recalculate using other versions (but these recalculations don't get stored) – asthasr Oct 1 '15 at 12:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.