wanna_code_perl has asked for the wisdom of the Perl Monks concerning the following question:
Hello Monks!
I'll save you the complicated backstory, but suffice to say I now maintain a small, unpopular CPAN module that hasn't been updated for ten years. I'm not going to name it, so I can talk freely about its shortcomings here. I also have a local version of the module I have been using in-house that pretty much got an accidental rewrite, one line at a time, over the past two years, while all of my RT tickets went unanswered. The in-house version is objectively better, (it actually has unit tests, and a ton of bugs and new features got taken care of), but the API has diverged slightly. So in order to upload a new version, I need to address the API differences.
Aside from entirely new subroutines, I haven't changed any subroutine names, arguments, or semantics, but I have changed a few error return values. Previously it was a little inconsistent with throwing exceptions vs. returning failure, so I standardized that. I also changed a few croak messages to be more descriptive, so if anyone is looking for a specific $@ string (arguably a bad idea anyway), they could have subtle bugs.
Short version of that: if someone plonked my current version of this module in place in their project as-is, it would mostly work, but the program might die due to network errors if the calling code wasn't already using eval{...}. A few edge cases might cause some errors that would be easily caught and fixed during integration testing. As far as I can tell, any potential upgrade errors would be of the "loud and obvious" variety. Still, the API has been stable for a decade, so I'd like to tread a little carefully.
How would you go about migrating an API such as this? I am in no particular rush to do anything, so doing a lengthy deprecation cycle (with migration documentation) wouldn't be a huge issue, but still a decent amount of extra work (and risk of regressions), with a real possibility that zero people will actually update this module in the next six months. Or maybe you wise monks have an even better idea, which is why I'm here!
Copied from one of my replies, below:
The API changes I've made are deliberate, and ultimately for the good of the project. As an example of why I made these changes, there was a method that would:
Since returning non-zero had no semantic meaning beyond "nothing broke," and the distinction between return 0; v. croak() was already ill-defined, I changed this sub to always croak() on error, thinking most implementations would already be eval{...}-ing that call, or risk premature death.
That's the biggest change. The other 3-4 examples are similar but simpler (fewer cases).
The documentation for the methods was generally good, except when it came to error handling. So I'm not really even going against the existing documentation, here, though I'm not using that as an excuse to break people's code. :-)
|
|---|