1

I was looking into the Enum design recommended by Microsoft (see here), and I found a statement that made me stop to think for a while:

X DO NOT use an enum for open sets (such as the operating system version, names of your friends, etc.).

It says that OS versions are considered as open set, therefore it should not be enumerated. Moving forward with my doubt: I'm developing a proxy to an API, and I'm thinking in allow the proxy's consumers choose the API version. The approach that I got in mind it's just define an enum that lists all the API versions, thus consumers are allowed to pass which API version they want to use.

However, due to API versions is something that would be considered as open (eventually there will be more versions), I'm doubting in include the version choosing feature. So, does this guideline not fit in my scenario?

3
  • Using an enum would work if it is only being used in selecting the API version your client is able to work with. Either your server knows the version and provides the service, or it doesn't know it and maybe replies with the highest supported version. But there are many more cases (such as listing available versions for the user) where tgis breaks. – Hans-Martin Mosner Jul 25 '19 at 13:40
  • "does this guideline not fit in my scenario?" too many negatives – Ewan Jul 25 '19 at 16:10
  • By "API" do you mean something like a class library or a web service? – Greg Burghardt Jul 31 '19 at 13:57
5

Enums are intended for things that are unlikely to change.

For example, a traffic light has three colors: red, green and yellow. That would be a good candidate for an enum. Even if you included all of the possible shapes such as right-arrows and left-arrows, that would still be a good candidate for an enum.

To change the colors or shapes of a traffic light, for example to add the color blue or the diamond symbol, would not be inconceivable, but it would require changes in the law and significant upheaval.

1

It depends on how coupled the consumer is to your proxy.

If using an enum, and the consumer wants to use a yet to exist API version, it requires updating to the latest proxy.

If that's the only reason for the update is the enum, then it's bad practice. For example, if you are just passing back a response that may have changed formats.

But if the new API version means new features that would already require a new proxy, then it's reasonable to use an enum. For example, if the new API means a different authentication scheme that would require a new workflow. However, then the distinction would likely be more than a version number, making the version number unneeded.

While there are instances that make sense, it's hard to predict if you might want to decouple your proxy version from the API version in the future.

An alternative other than letting consumers pass strings would be a class with named static values. It has the bonus of allowing you to encapsulate logic for validation and features. Something along the lines of:

    public class ApiVersion{
        readonly public string Version;

        public ApiVersion(string Version){
            if (Version == null || Version.Any(c => !char.IsDigit(c) && c != '.')){
                throw new ArgumentException();
            }
            this.Version = Version
        }

        public override bool Equals(object obj) {
            return string.Equals((obj as ApiVersion)?.Version, this.Version);
        }

        public bool SupportsListAssetEndpoint(){
            return string.Compare(Version , V1_2.Version) > 0;
        }

        public static ApiVersion Version1_2 = new ApiVersion("1.2");
        public static ApiVersion Version1_3 = new ApiVersion("1.3");

    }
0

What does it imply that an enum is for a closed value domain?

  • On a future addition (even more for a removal), all uses in the form of a switch must be checked/adapted.

  • The software version determines the right enum class version. Any the API client and the library develop separately, it can become more painful. Especially with sample code.

What would be the alternative?

  • A lookup mechanism of versions. Java SPI provides such a mechanism, but there are other solutions thinkable for other languages.

  • A feature detection of specific capabilities of the API. Supports test functions sometimes are simple, but not very flexible or elegant. You can provide a lookup function that is passed an interface and will return an instance, an implementation if
    it has that capability:

    Optional<Flying> flying = animal.as(Flying.class);
    flying.ifPresent(f -> f.fly());
    

This decouples code, separates concerns, and is extendable. Especially it is a safe handling of a feature, a case.


However I am aware that your case concerns OS versions. Which seems limited in number and variation. You could have a table/matrix of versions & features. However there is not a single Microsoft OS line, so it might be that you burden the developers to handle individual cases by versions/supportsXyz. In fact a developer is likely to do a minimal handling of just a couple of cases. Breaking the applications when the context changes.

So a version type in the API is just lowering of the software quality. As overview documentation on may give tables of OS versions and their features. That may help a developer to do some cross-OS development.

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.