Prism: Breaking changes in IModule

Created on 17 Jul 2018  路  15Comments  路  Source: PrismLibrary/Prism

Description

We are working on upgrade to latest version of Prism but because of breaking change in IModule unable to proceed. Considering number of existing modules requiring manual rewriting ( in hundreds of thousands for entire organization ) it is becoming too costly and impractical.

The company I work for ( one of the largest in NY ) is considering abandoning this library for in house solution because of this change. I am pretty sure there will be more unhappy customers as soon as v7 is out of pre stage and more organizations start to upgrade.

I understand you are striving for greatness but perhaps it could be done without breaking most fundamental and used pattern/interface?

Is it possible that you could reconsider this change and provide legacy support as well as new features?

Steps to Reproduce

N/A

Expected Behavior

Actual Behavior

Basic Information

  • Version with issue: 7.1
  • Last known good version: 7.0.0.336
  • Xamarin.Forms version:
  • IDE:

Screenshots

Reproduction Link

Most helpful comment

Actually, the complexity of the upgrade isn't in the code changes required - as Brian said that's pretty much a string replace job. However, enterprise users of Prism tend to write applications using multiple teams, each releasing their own part in some form, independent of the others. This works as long as shared components do not really change, allowing you to use assembly bindings. Having such a basic interface change breaks this, forcing all of these teams to update their code and release it all at the same time - the coordination involved could be quite the challenge. I can see this pushing companies towards either delaying the upgrade indefinitely (read: never) or removing Prism from their code, neither of which is optimal.

Even though Prism is an open source project and it doesn't have financial motivation to get people to keep using it, it needs to have a reason to exist - that is, it needs people to use it. I'm not sure if losing (some) enterprise users has a bigger impact than the gains from the standardization, but the whole issue could be avoided by offering some form of backwards compatibility (even if only maintained for a short timeframe). I'm thinking something along the lines of keeping the old IModule as-is, marking it obsolete and adding the new interface under a new name, then in version 8 or so moving completely to the new one. Letting them coexist for a while would allow large users of the library to update their stuff piece-by-piece, which I think would be a huge benefit. Would you consider this option if someone put in the effort to write it?

All 15 comments

This was a concern of mine when we first made this change, but we do have to move the framework forward. The changes to IModule really are for the better, and will result in a better developer API and experience. Honestly, you can update your IModule with very minimal effort. Just implement the new methods as empty, and then copy/past the code you have in the old Initialize method into the OnInitialized method. You don't have to change anything else. You don't even need to use any of the new interfaces in the new methods. My approach to this would be to create a simple console app that did this for all my modules and it's done in seconds.

I will note, that you are more than welcome to stop using Prism and create your own internal framework that you can maintain and support internally. Prism is open source, and we do not get paid when someone uses it. So if your company stops using it, we don't lose anything. If your company would like to take on the burden on creating and maintain their own framework, they should go for it. Many companies do that now, and a lot of those frameworks are based off of Prism.

Actually, I will say this. If your company (one of the largest in NY) would like to pay for this backwards compatibility, we can make it happen. It would require a lot of thought and work, because it is not a simple change, but if we are paid for that time, then we can make it work. It is probably cheaper than your company creating their own framework and maintaining it over the life of your projects, and then replacing Prism with your new framework in your current projects. Just a thought.

@ENikS I should add here, just like Unity had to make breaking changes (which broke EVERY single Prism app across all platforms using Unity) to move the framework forward, Prism also must make changes from time to time to move the framework forward. I'm sure as a the maintainer for Unity you can understand these sorts of breaking changes aren't made lightly. In fact we have often held back on changes because we feel it would be too painful for WPF developers.

Funny thing is, when those breaking changes were introduced into Unity, we had to modify Prism to help protect it's users from those types of dependency breaks in the future. So in reality, it helped motivate us to abstract away the container altogether and ultimately lead to the change in IModule.

@ENikS Do you propose to make one more breaking change? This will be painful for all Prism users who have already migrated their apps to latest version.
IMHO with this number of modules you need to expose your own abstraction. You can implement abstract class that will inherit IModule, implement its members and provide your own abstract API. Or I believe you can override ModuleCatalog and ModuleInitializer to load and instatiate your own IModule. Both option allow you to use Find and Replace feature of any text editor to change legacy code instead of manual rewriting.

Brian, it is not MY company, I just work there :)

Let me make one thing clear, I am not your enemy here. I like Prism and I use it everywhere I can and because of that I opened this issue. I would like to keep using it...

The decision to use or stop using the library is not up to me or even the team I work for, it is budget thing for the whole company. Think about economics of this change:

  • Every single module in the world needs to be manually changed (however simple it might be)
  • Every single method has to be accompanied with unit tests
  • Every single change has to be regression tested (manually tested for a lot of projects)

This creates unreasonable burden for all users of the library. The bigger the user, the more expensive it is. We are talking about hundreds of millions spent on this change worldwide and for WHAT?

Original IModule was brilliant in its simplicity and robustness. It was completely agnostic of container, platform, etc. It would easily accommodate any 'Resource Locator Pattern' you could throw at it, including new Prism one.

I am all for change and progress and I am not criticizing you for breaking the interface, but this particular change is too expensive for the benefits it provides.

I would like to propose a compromise: Lets have a discussion with wider audience of users on this issue, after all, we are a democracy here, and get more opinions on this matter?

Nobody forces you to leave v6 and go to v7, you can limit NuGet updates by using version ranges. It's a major version bump for a reason. Some of my clients are sticking to Autofac v4 to stay away from the immutable container, or on Json.net v9 to not drag in a zillion dependencies until they move to .NET Core.

But we do want to use the latest. We just don't want to pay so much for so little benefit.
Prism is a business library and economical considerations should be part of the equitation as well as style.

Let me make one thing clear, I am not your enemy here. I like Prism and I use it everywhere I can and because of that I opened this issue. I would like to keep using it...

@ENikS nobody is saying you're an enemy here. But certainly there is a huge irony that the person responsible for breaking so many Prism apps using Unity, is the one complaining about an API change in Prism that was made in large part because of the breaking changes that you did.

Think about economics of this change:

  • Every single module in the world needs to be manually changed (however simple it might be)
  • Every single change has to be accompanied with unit tests amended
  • Every single module has to be regression tested

I would say you're really making a bigger issue of this than it ought to be. All you really need is to add two lines of code to your modules and they'll work just fine.

public class LegacyModule : IModule
{
    public void OnInitialized(IContainerProvider containerProvider){ }

    public void Initialize(IContainerRegistry containerRegistry) => Initialize();
}

Original IModule was brilliant in its simplicity and robustness. It was completely agnostic of container, platform, etc.

The "Original" IModule was overly simply, and not very robust at all. IModule was hardly agnostic of a container, it was closer to a straight up Atheist denying the very existence of a Container. The resulting pattern meant that in order to register anything, the Module was explicitly tied to a container. By contrast the updated IModule with the IoC abstractions is more of an Omnist, believing it should be able to work with any container, except Autofac because they're determined to be immutable. In addition to that the new IModule helps developers enforce a pattern of Register / Do Stuff rather than putting all of the code they need into a single method (which let's be honest most people were doing).

@dansiegel You concentrating on me complaining about the change, breaking Unity, and simplicity of the change but you missing fundamental point: This change is prohibitively expensive to implement. Like in real money expensive,

It is not a namespace change, or rename, where Resharper or cut and paste can help you. This is required manual change for every single module with all the testing to follow...

I would say you're really making a bigger issue of this than it ought to be. All you really need is to add two lines of code to your modules and they'll work just fine.

This is not how it works in real world. You have to follow the rules and established procedure.

As for breaking Unity, I really had no choice in all these changes. I tried as hard as I could to preserve original contracts. I could go ever every single change with you and provide justification for each and every one. I do not think Unity breaking changes could be compared with IModule.

@ENikS I am hardly focusing solely on you complaining about the change. I do not think you fully appreciate the irony though.

The snippet below is all you need to make your module v7 compatible. If your company requires something more, as @brianlagunas mentioned before this is an Open Source library, you are more than welcome to fork or submit a PR. If your bosses feel it would be too expensive to add two lines of code, they are also welcome to pay for the backwards compatibility to be added for them.

@dansiegel The irony does escapes me, what am I missing?

Actually, the complexity of the upgrade isn't in the code changes required - as Brian said that's pretty much a string replace job. However, enterprise users of Prism tend to write applications using multiple teams, each releasing their own part in some form, independent of the others. This works as long as shared components do not really change, allowing you to use assembly bindings. Having such a basic interface change breaks this, forcing all of these teams to update their code and release it all at the same time - the coordination involved could be quite the challenge. I can see this pushing companies towards either delaying the upgrade indefinitely (read: never) or removing Prism from their code, neither of which is optimal.

Even though Prism is an open source project and it doesn't have financial motivation to get people to keep using it, it needs to have a reason to exist - that is, it needs people to use it. I'm not sure if losing (some) enterprise users has a bigger impact than the gains from the standardization, but the whole issue could be avoided by offering some form of backwards compatibility (even if only maintained for a short timeframe). I'm thinking something along the lines of keeping the old IModule as-is, marking it obsolete and adding the new interface under a new name, then in version 8 or so moving completely to the new one. Letting them coexist for a while would allow large users of the library to update their stuff piece-by-piece, which I think would be a huge benefit. Would you consider this option if someone put in the effort to write it?

It even can be the same name, just under a different namespace.

@istvanfarmosi

This works as long as shared components do not really change, allowing you to use assembly bindings

You should never try to use assembly redirects for a major version change as that indicates breaking changes, and almost guarantees your app will fail.

Having such a basic interface change breaks this, forcing all of these teams to update their code and release it all at the same time - the coordination involved could be quite the challenge. I can see this pushing companies towards either delaying the upgrade indefinitely (read: never) or removing Prism from their code, neither of which is optimal.

The truth is that any company that has vested into Prism and decides that Prism will not longer work for them because of an interface change in a major version release (which they have had plenty of time to prepare for since the previews have been out for a very long time) is asking for a much more time consuming and expensive task of removing Prism and trying to replace it with something else. Essentially rewriting their entire application. This is not likely. What is more likely is that they will either not upgrade the version of Prism, or they will simply update the interface and perform a find/replace to have the new OnInitialized method call the old Initialize method.

Let's say that we spent all the time to come up with a way to support the old IModule interface. All of your arguments still fail because the Unity container broke every single Prism app anyways. So you will still have to coordinate across all your teams to change all the namespaces and object names of Unity, and re-release. Either way you will have to do this if you want to keep using Prism. That or change your container, but because the old IModule creates a tightly coupled relationship to containers that would be even more code you would have to hand write.

As you pointed out, Prism is OSS and we have zero financial motivation. Honestly, I personally don't care if people use Prism or not. We get nothing in return. Nothing. Well... we get a lot of "thank you for making me and my company successful so that I can make money and provide for my family" type comments which are great. Yet, not many considers the time the Prism team spends away from their own families to maintain it. Frankly, if everyone decided to stop using Prism, do you know what would happen? We would actually get something in return... all our free time back.

We are making changes to Prism to help move it forward to make it less brittle for future change, remove the tight coupling to containers, to simplify the API, to make it easier to share your code across platforms, and to make it easier for the Prism team to maintain.

So to sum up, Prism for WPF v7.x is a major release with documented breaking changes (both in the library and it's dependent containers). Only upgrade if you are willing to fix those breaks. Otherwise, you can stay on v6.x, or create your own framework to update and maintain.

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

Was this page helpful?
0 / 5 - 0 ratings