Skip to content

Instantly share code, notes, and snippets.

@brantburnett
Created October 4, 2016 03:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save brantburnett/60fd3756149b53540f0c424440c37647 to your computer and use it in GitHub Desktop.
Save brantburnett/60fd3756149b53540f0c424440c37647 to your computer and use it in GitHub Desktop.
Proposal for handling synchronous methods in the .Net Standard version of the Couchbase .Net SDK

Couchbase .Net Standard 1.5 Sync Methods

Overview

In .Net Core, .Net Standard, and other related technologies Microsoft has moved away from synchronous method implementations for any method that may involve latency. Instead, they favor only offering async methods. This is especially true for any methods that involve I/O, such as network connections, streams, file access, etc. This forces the consuming developer to recognize the inherently asynchronous nature of the operation and develop their application based on this knowledge. It becomes a syntax-level and compiler recognized way to ensure that developers recognize the delays involved in the operation they are performing.

How This Affects The Couchbase .Net SDK

Actions on a Couchbase server (whether K/V, View, N1QL, or even management) involve network latency, timeouts, etc. If we follow the new Microsoft paradigm, methods supporting these actions should only have an asynchronous surface area. Synchronous methods should not even be available for use by the consumer.

.Net Core support within the SDK is a new binary targeting .Net Standard 1.5, which is included in the Nuget package side-by-side with the traditional .Net 4.5 binary. This allows for changes to the API surface area within the SDK without creating issues with backwards compatibility. However, this is only an option so long as we are in the Developer Preview phase. Once released, backwards compatibility becomes a requirement until version 3.0, since the SDK follows semver.

Possible Approaches To Synchronous Methods

  1. Easiest but paradigm breaking - Just leave the methods in place and don't worry about it

  2. Easy and clean - Use conditional compilation directives to remove all network access synchronous methods from the .Net Standard binaries. This leaves only the asynchronous methods to be used within .Net Core and other platforms being supported by the .Net Standard binary.

    The downside to this approach is that is more limiting that developers are accustomed to. If relies on the entire stack, from MVC action to business logic layer to data access layer, being implemented asynchronously. If not, then the developer will tend to convert the async call to synchronous, losing all of the advantages and decreasing performance.

    The counter-argument is that new applications written in .Net Core will almost certainly use async development patterns throughout.

  3. Easy and messier - Use conditional compilation directives to flag all synchronous methods as Obsolete in the .Net Standard binary.

    The upside is that the developer can still choose to use the synchronous methods, but is discouraged from doing so. The downside is that we are locked into supporting these methods until at least version 3.0 due to semver.

  4. Hardest but most flexible - Move the synchronous methods to an optional Nuget dependency for the .Net Standard binary. Leave them in place in the main binary for the .Net 4.5 SDK.

    The upside is that the developer is even more discouraged from bad practices than they were for option 3 above. The downside is that this will be more difficult to implement.

How Do We Do Option 4?

  1. Exclude all synchronous methods from interfaces in .Net Standard 1.5 using conditional compilation directives.

  2. Make all synchronous methods on classes into internal methods in .Net Standard 1.5 using conditional compilation directives.

  3. Add a new project called CouchbaseNetClient.Sync, which will be used to make the new Nuget package. This package will be a "null" package that installs no libaries if someone consumes it on .Net 4.5, it will only be used for .Net Standard 1.5 purposes.

  4. Use InternalsVisibleTo to grant access to some internals to this new project.

  5. Add shortcut extension methods that call the internal implementations

public static class BucketExtensions
{
  public IOperationResult<T> Get<T>(this IBucket bucket, string key)
  {
      var couchbaseBucket = bucket as CouchbaseBucket;
      if (couchbaseBucket != null) {
          return couchbaseBucket.Get<T>(key);
      }
      
      var memcachedBucket = bucket as MemcachedBucket;
      if (memcachedBucket != null) {
          return memcachedBucket.Get<T>(key);
      }
      
      throw new NotImplementedException();
  }
}
@brantburnett
Copy link
Author

@jeffrymorris

I tried to sort out and write up my thoughts on sync versus async methods for .Net Core support. I'm not really sure which option is my favorite, what do you think?

@jeffrymorris
Copy link

@brantburnett -

Nice write up. My vote is either 2 or 4, leaning towards 4 since it gives us an out.

Thanks,

Jeff

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment