Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove support for .NET 4.0 #696

Merged
merged 5 commits into from
Mar 16, 2016
Merged

Remove support for .NET 4.0 #696

merged 5 commits into from
Mar 16, 2016

Conversation

mmdriley
Copy link
Contributor

Microsoft ended support for .NET 4.0 in January 2016:
https://blogs.msdn.microsoft.com/dotnet/2015/12/09/support-ending-for-the-net-framework-4-4-5-and-4-5-1/

Removing support in our libraries and bringing anything framework-
sensitive up to 4.5 will allow us to drop a lot of vestigial
dependencies that have caused problems for, e.g., customers using
us from DLLs. It also lays the groundwork for supporting .NET Core,
since net40 and dnxcore share no PCL profiles in common.

Even assuming customers aren't running on .NET 4.0, their projects may
still target it by specifying a target framework. Those customers will
not be able to use new versions of our NuGet packages without retargeting
their apps. Old versions of the libraries will continue to work.

In terms of implementation, the steps here were:

  • Rename _Net40 projects to _Net45

  • Retarget any project that previously targeted 4.0 to 4.5.

  • Reinstall NuGet packages to rewrite targetFramework in packages.config
    and to update references in the project to net45 versions.

    The useful command here was: Update-Package -ProjectName <project> -Reinstall

  • Remove dependencies on Nuget packages like Microsoft.Net.Http
    that are no longer necessary.

  • Fix a few uses of TaskEx from the now-removed BCL NuGet packages.

  • Remove now-unnecessary binding redirects from app.config.

  • Change Net45 projects to refer only to other Net45 projects, rather
    than PCLs. This should make it easier for customers to use our
    libraries from DLLs, since app.config won't be necessary to rewrite
    dependencies that differ between Net45 and PCL.

  • Retarget the PCL projects from net40 to net45:

    Profile328 = portable-net4+sl50+netcore45+wpa81+wp8

    Profile344 = portable-net45+sl50+netcore45+wpa81+wp8

    If we don't do this, the package will still support net40 but won't
    include the PlatformServices assemblies for net40. Customers would
    be upgraded to new libraries that might break their apps.

  • Update the .nuspec files to reflect new targets.

No content changes yet.
Microsoft ended support for .NET 4.0 in January 2016:
https://blogs.msdn.microsoft.com/dotnet/2015/12/09/support-ending-for-the-net-framework-4-4-5-and-4-5-1/

Removing support in our libraries and bringing anything framework-
sensitive up to 4.5 will allow us to drop a lot of vestigial
dependencies that have caused problems for, e.g., customers using
us from DLLs. It also lays the groundwork for supporting .NET Core,
since net40 and netcore50 share no PCL profiles in common.

Even assuming customers aren't *running* on .NET 4.0, their projects may
still *target* it by specifying a target framework. Those customers will
not be able to use new versions of our NuGet packages without retargeting
their apps. Old versions of the libraries will continue to work.

In terms of implementation, the steps here were:

* Rename _Net40 projects to _Net45 (done in previous commit to help
  with diffs)
* Retarget any project that previously targeted 4.0 to 4.5.
* Reinstall NuGet packages to rewrite targetFramework in packages.config
  and to update references in the project to net45 versions.

  The useful command here was:
  `Update-Package -ProjectName <project> -Reinstall`
* Remove dependencies on Nuget packages like Microsoft.Net.Http
  that are no longer necessary.
* Fix a few uses of TaskEx from the now-removed BCL NuGet packages.
* Remove now-unnecessary binding redirects from app.config.
* Change Net45 projects to refer only to other Net45 projects, rather
  than PCLs. This should make it easier for customers to use our
  libraries from DLLs, since app.config won't be necessary to rewrite
  dependencies that differ between Net45 and PCL.
* Retarget the PCL projects from net40 to net45:
  `Profile328` = `portable-net4+sl50+netcore45+wpa81+wp8`
  `Profile344` = `portable-net45+sl50+netcore45+wpa81+wp8`
  If we don't do this, the package will still support net40 but won't
  include the PlatformServices assemblies for net40. Customers would
  be upgraded to new libraries that might break their apps.
* Update the .nuspec files to reflect new targets.
@googlebot googlebot added the cla: yes This human has signed the Contributor License Agreement. label Mar 13, 2016
@mmdriley
Copy link
Contributor Author

/cc @chrsmith

When the solution builds the ReleaseTravis target, the new Net45
projects build for ReleaseSigned, but all existing projects were
configured to build in Release. The new Net45 projects failed to
compile because they were taking a dependency on non-strongnamed
assemblies.

Now that the signing key is available in GitHub, Travis should
build everything in ReleaseSigned.
These tests relied on cancellation behavior of the HTTP client from the
Microsoft.Net.Http NuGet package. Now that they use the framework
implementation, the tests' expectations about what exception they'll
see -- and how it will be returned -- need to change.

Since our implementation calls ThrowIfCancellationRequested(), it has
always been possible that we'd return OperationCanceledException as
we now see in the tests. This doesn't indicate a breaking change.
Mono's HttpHeaders.Add rejects valid values for ETag that we use in
our tests. https://bugzilla.xamarin.com/show_bug.cgi?id=39569
@peleyal
Copy link
Collaborator

peleyal commented Mar 13, 2016

I just want to mention two things:

  1. Do we have numbers about how many of our users use .NET 4.0? I don't think we have anything like that, and maybe it's a good idea to post something on one of our groups and check if people respond there.
    In addition do we have any numbers about how many people use .NET 4.0 and .NET 4.5?

  2. If we do move forward with this CL, IMO, it's important that the next client version will be 2.xxx and not 1.xxx because it's a major change to the library. If so, maybe it's also a good time to take a look in other components that we are not happy with and we can change now.
    I can only think right now about our logger, but I'm pretty sure there are more things we can and should improve.

Any thoughts?

@mmdriley
Copy link
Contributor Author

As you say, we don't have statistics on clients' runtime version or, perhaps more importantly, their projects' target framework version. I think it's safe to say a small but nonzero percent of projects that use us are still targeting .NET 4.0. The impact for them will be that future client releases will be unavailable until they retarget their project.

We're by no means alone. A quick search suggests there are about ten thousand NuGet packages that target net45 but not net40.

With more effort, we could continue to support net40 customers. However, with our current resources, I think we can do the greatest good for the greatest number by dropping net40 (and sl50 soon) to make sure the net45 and dnxcore experiences are great.

As for incrementing the major version: I take your point, but I also see a lot of reasons not to move to 2.X right now:

  1. We don't have an inventory of the breaking changes we might want to make, and we're not in the best place to spend time creating one.
  2. We don't know that we actually want to make any API-incompatible changes, since that would negatively impact more of our clients.
  3. Incrementing the major version makes it more likely that we strand net45 customers on these old versions when they could actually upgrade seamlessly.
  4. NuGet won't offer new versions to net40 clients for installation or upgrade, so this shouldn't break any customers in place. These customers will be stranded either way.

@mmdriley
Copy link
Contributor Author

If we determine this was the wrong course, we can re-add .NET 4.0 support (with its accompanying complexity) in a future minor version.

@chrsmith
Copy link
Contributor

Based on my understanding, which is largely informed by Matt's research, I feel good about this change. The biggest thing is that as long as we keep the existing 4.0 NuGet packages around existing apps will continue to work. (Although they won't pick up on any new platform features we add.)

👍 assuming nobody has any remaining major objections.

@ivannaranjo
Copy link
Contributor

As I mentioned before I do think that we should update the major version of the package because we need to signal to our users that this is indeed a breaking change. The fact that we could get away with not updating the version doesn't change the fact that it is a breaking change.

I also happen to agree with Eyal and that we should look for more breaking changes/cleanup that we want to do here. Removing support for .NET 4.0 is not an urgent matter so I think we can take the time to do it right, including removing support for SL, Windows Phone, etc, etc...

My main concern really is the fact that .NET 4.0 users will silently stop receiving updates, any new feature added to the package will just not appear on the .NET 4.0 .dll which will remain and rot in the machine and no apparent error message will indicate as to why the missing features.

Updating the version number will also give us a clean separation between the two "branches" (pre and post .NET 4.0 removal) so we can port bugs (if they are severe enough) from the supported branch (the one that doesn't support .NET 4.0) to the dormant one (the one that support's .NET 4.0). While creating an actual branch is not actually necessary for the release (a tag would be sufficient) a branch will undoubtably be created if and when we need to go back and port a fix.

This also calls for a starting the discussion on a clear support policy for the packages, so we can indicate when and if changes are indeed going to be backported, until when that will happen, etc...

@mmdriley
Copy link
Contributor Author

cc @jskeet for his opinion as well.

Whether or not we move to v2 to drop .NET 4.0 support, the experience for customers with projects targeting .NET 4.0 will be the same: they will run Update-Package or nuget update and nothing will happen. They won't get any new features but their code will continue to work. Changing the major version number (and entertaining breaking API changes while we're at it) will, however, break or disrupt most of our current customers (those on .NET 4.5) without offering them any compelling benefit in return. I don't think that's the right call.

If we're staying with 1.X, then, how should we proceed?

We have three support libraries that target desktop CLR: Google.Apis.PlatformServices, Google.Apis.Auth.PlatformServices, and Google.Apis.Auth.Mvc. There is real benefit to having versions of those libraries that target .NET 4.5: it will fix a number of dependency problems we've seen and avoid installing a lot of unnecessary packages in customer projects.

If we drop .NET 4.0 support, we can simply retarget those libraries. Otherwise we need to add and maintain three new projects.

We also want to target .NET Core sometime soon. There is no PCL profile that targets both net40 and dnxcore50. If we drop support for .NET 4.0, we can retarget our existing PCLs. Otherwise, we need to add new projects for all of them, including each of our generated libraries. That's a lot of new projects to continue supporting a dead platform.

Our codebase also uses a nontrivial amount of reflection. .NET 4.0 and .NET Core speak incompatible reflection APIs so we'd have to have two copies of that code.

All told, I think the cost of continuing to support .NET 4.0 far outweighs the benefits of continuing to provide updates, especially since customers with projects that still target 4.0 probably aren't updating their NuGet dependencies aggressively.

I think we hurt customers by changing the version number. I think we hurt ourselves by continuing to support .NET 4.0. If I'm forced to choose between the two, I'll choose the latter, but I think we can safely avoid both.

What if I'm wrong?

If we find a critical correctness or security problem with the existing libraries, we can cut a branch right before this PR, make the fix, and ship a new 1.10.X version that targets .NET 4.0.

If it turns out we caused more customer pain than I expected by dropping support for .NET 4.0, we can do the work I described above and reintroduce support for .NET 4.0 in a future minor version.

We can undo v1.11 with v1.12. We cannot undo v2.

@jskeet
Copy link
Collaborator

jskeet commented Mar 16, 2016

I agree with Matt. While it feels wrong to make this change on the 1.x line, I can't fault Matt's logic. I would note that we're basically assuming people will use NuGet to get updates - it is a breaking change in terms of anyone who just copies a DLL around manually. However, they'd be copying the DLL out of a directory which is clearly not meant to support .NET 4.0, so I don't think it's unreasonable for that to break - and I suspect the number of people actually doing that is 0 anyway.

@ivannaranjo
Copy link
Contributor

If we do a major release our .NET 4.0 customers will not update because
there will not be anything for them, if customer use the right flags in the
Update-Package (in NuGet 3.0 you can use -ToHighestMinor) to update to the
latest minor version within the major version. Otherwise they will get the
new package and we will be in the same situation. My point here being that
the major version bump actually serves as a barrier for users to determine
up to what version are they willing to support.

As everything else a major version update is nothing more than a signal, I
do agree that technically is not required, it is more about the message
that we want to convey to our users, where we want to establish barriers
and in my mind what are we willing, as the active owners of the project, to
support and how back we plan on helping people.

I also agree that major versions cannot be undone, and that is by design
and the right thing to do, should we need to support .NET 4.0 for longer
instead of adding the support back we would just support the previous major
version, without having to encumber the new version with that legacy again.

Just as a parting thought we need to deliberate in our choices and clearly
signal what we're doing here, I think that a major version update will be
as deliberate as we can make it, this is not the same package, it is not
intended to be compatible, only pick it up if you need it. Picking new
major versions of a package is not something that people will do lightly (I
think) so it is the appropriate signal for our users that they need to give
attention and extra testing to this change.

On Wed, Mar 16, 2016 at 6:50 AM, Jon Skeet [email protected] wrote:

I agree with Matt. While it feels wrong to make this change on the 1.x
line, I can't fault Matt's logic. I would note that we're basically
assuming people will use NuGet to get updates - it is a breaking change
in terms of anyone who just copies a DLL around manually. However, they'd
be copying the DLL out of a directory which is clearly not meant to support
.NET 4.0, so I don't think it's unreasonable for that to break - and I
suspect the number of people actually doing that is 0 anyway.


You are receiving this because you commented.
Reply to this email directly or view it on GitHub
#696 (comment)

@ivannaranjo
Copy link
Contributor

After talking with Jon and having some time to reflect on this I don't feel
as strongly as I did this morning about updating the major version. It
makes me uneasy to drop platform support on a minor update but the pain of
a major update is too high price to pay to be correct in a pedantic way,
the pragmatic approach is better. So I withdraw my objections.

On Wednesday, March 16, 2016, Ivan Naranjo [email protected] wrote:

If we do a major release our .NET 4.0 customers will not update because
there will not be anything for them, if customer use the right flags in the
Update-Package (in NuGet 3.0 you can use -ToHighestMinor) to update to the
latest minor version within the major version. Otherwise they will get the
new package and we will be in the same situation. My point here being that
the major version bump actually serves as a barrier for users to determine
up to what version are they willing to support.

As everything else a major version update is nothing more than a signal, I
do agree that technically is not required, it is more about the message
that we want to convey to our users, where we want to establish barriers
and in my mind what are we willing, as the active owners of the project, to
support and how back we plan on helping people.

I also agree that major versions cannot be undone, and that is by design
and the right thing to do, should we need to support .NET 4.0 for longer
instead of adding the support back we would just support the previous major
version, without having to encumber the new version with that legacy again.

Just as a parting thought we need to deliberate in our choices and clearly
signal what we're doing here, I think that a major version update will be
as deliberate as we can make it, this is not the same package, it is not
intended to be compatible, only pick it up if you need it. Picking new
major versions of a package is not something that people will do lightly (I
think) so it is the appropriate signal for our users that they need to give
attention and extra testing to this change.

On Wed, Mar 16, 2016 at 6:50 AM, Jon Skeet <[email protected]
javascript:_e(%7B%7D,'cvml','[email protected]');> wrote:

I agree with Matt. While it feels wrong to make this change on the 1.x
line, I can't fault Matt's logic. I would note that we're basically
assuming people will use NuGet to get updates - it is a breaking
change in terms of anyone who just copies a DLL around manually. However,
they'd be copying the DLL out of a directory which is clearly not meant to
support .NET 4.0, so I don't think it's unreasonable for that to break -
and I suspect the number of people actually doing that is 0 anyway.


You are receiving this because you commented.
Reply to this email directly or view it on GitHub
#696 (comment)

@chrsmith
Copy link
Contributor

:shipit:

mmdriley added a commit that referenced this pull request Mar 16, 2016
Remove support for .NET 4.0
@mmdriley mmdriley merged commit 248e830 into googleapis:master Mar 16, 2016
@mmdriley mmdriley deleted the net45 branch March 18, 2016 22:16
@LindaLawton
Copy link
Collaborator

I feel as though i have missed the boat on this I was unaware of this thread.

How much of the auto generated API packages are effected by this. If there are changes in an API and the auto generated package is updated will someone using .Net 4.0 still be able to get these changes? or are you saying that we will need to manually update those packages as well when an API is released?

Is it just the core library that is no longer going to be updated for .Net 4.0 users. I am trying to determine the ramifications of this sudden and unexpected change.

@mmdriley
Copy link
Contributor Author

My intent was to end support for .NET 4.0 in any new versions of the support or generated libraries. Developers looking to use new features or new APIs would need to retarget their projects to .NET 4.5.

I outlined my reasoning in the discussion above, and concluded:

I think the cost of continuing to support .NET 4.0 far outweighs the benefits of continuing to provide updates, especially since customers with projects that still target 4.0 probably aren't updating their NuGet dependencies aggressively.

I still believe that, and I still believe this change would have been appropriate if NuGet had left customers on the last version of the libraries that supported their target platform. That's not how things work, so we need a new approach. Thus #716.

Whatever solution we arrive at, providing updates to .NET 4.0 projects is not a priority.

My current understanding is that retargeting applications to .NET 4.5 should be relatively straightforward. If that's not the case, and there are compelling reasons to ship new features to projects that target .NET 4.0, let's start that discussion in another issue.

@LindaLawton
Copy link
Collaborator

While I understand your decision to no longer support 4.0. I dont have to agree with it. It is not as simple as you think to switch to 4.5 there are still a lot of applications running on systems that are not upgraded. That for one reason or another cannot be upgraded. Developers who have been using this client library for years have probably been upgrading dlls to support new features released by their chosen API are now left hanging with no more updates.

  • You haven't even told them they aren't going to get updates they are just never going to appear.
  • You haven't recommended that they switch to 4.5 because 4.0 will no longer be supported.

I think you need to inform your users in some way that it will no longer be supported. What if Google decided tomorrow to shut down Google Drive API without first giving developers a chance to plan alternate solutions.

Again I do understand this decision it is probably a lot of work to keep 4.0 going. What i dont understand is why this change wasn't announced ahead of time so that people could prepare.

Dont forget to update the read me : ReadME

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cla: yes This human has signed the Contributor License Agreement.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants