4

I'm working on a Spring-based REST api that has v1 and v2 variants:

/api/v1/dates
/api/v2/dates

Correspondingly, there are v1 and v2 packages in the code base:

com.company.api.v1
com.company.api.v2

Is it a good practice to postfix class names with version number like below:

  • DatesControllerV1.java (in v1 package)
  • DatesControllerV2.java (in v2 package)

I prefer not postfixing version in the class name as:

  • their package names should tell you about the version already, redundant;
  • I simply don't like numeric character in class name.

However, not postfixing version(ie. same class name but in different packages) will increase the probability of using the wrong class accidentally due to IDE auto-complete/auto-import by careless developers.

I tried looking for a github repo that has similar code base structure and see how they deal with it. But could not find one unfortunately.

I'm wondering which approach do you think is better and the reason. I'm also wondering if there is a better approach(for the current code base setup) than these two?

UPDATE

With the help from Azuaron and CormacMulhall, I realized that I really don't have other options to improve my current situation, given that both the v1 and v2 APIs reside in the same code base and I cannot change this setup.

For those who are seeking for the proper way of doing this(having different versions of APIs), please see Azuaron's answer below.

3
  • 3
    The best approach is to have v1 and v2 of the API as two separate deploys, with two separate code bases. Anything else is going to be a massive pain, so there isn't really a 'better' way to do this. Not doing it is the better way of doing it. Can you explain a little why you can't do it. What are the limitations here? Is this code you maintain? Or are you just a single developer working on a team that maintains this? Aug 19, 2016 at 10:19
  • 1
    @CormacMulhall You are right, I'm only one of the developers working on this repo and I'm not the guy who can make this decision of splitting v1 and v2 code.
    – GJ.
    Aug 19, 2016 at 12:41
  • 1
    I then would stick with just naming the packages with the version number, and keeping the classes clear of that information. The programmers are going to already have to be so aware that the code base has two versions in it that you don't need to point this out in the class names. Aug 19, 2016 at 12:48

3 Answers 3

5

I must admit, my heart contracted in stress when I read "...there are v1 and v2 packages in the code base..." Typically, versioned APIs are, well, versions of your code, and don't live side-by-side in your codebase.

How I've done it before is forking the repo. V1 sticks around for bug fixes until we can get everyone onto V2, and V2 is where all the new features go. Then in production, you deploy both codebases (either on different servers, or side-by-side), and your URL routing points to the appropriate instance.

This gives you the following benefits:

  1. The only way someone writes code against the wrong API is if they're in the wrong repo (at which point, there's not much else you can do for that programmer).

  2. You don't have to worry about backward compatibility in "shared" non-API classes (utility, service, DAO, what have you).

  3. A deploy of one API does not impact the other.

  4. Honestly? It provides a demonstrable business reason to abandon v1 as soon as possible (you can shut down the old server) that can clearly be explained to non-developers.

The downside is that the codebase is not shared, so changes in one that are "necessary" in the other must be ported. I don't see this as a big deal. It shouldn't happen that much (new features go into v2, not v1, by design), and any changes that truly need to be shared can be extracted into libraries or other services.

2
  • 2
    While what you said is true, it does not help me with my current situation, as I have no way to change to have separated repos for v1 and v2. I think I need to clarify my questiona bit. Thank you for the answer anyways!
    – GJ.
    Aug 19, 2016 at 1:59
  • You can't have separate repos, or you can't have separate deploys? It seems like a "first pass" solution could even be to separate out the v1 repo, then include it as a library in v2. And if you can't even have separate repos, you could have v1 and v2 as subprojects in your one repo.
    – Azuaron
    Aug 19, 2016 at 10:12
0

I guess it depends on "Do you see them as two versions of essentially same concept OR do you see them as two different concepts"?

If you see two different concepts, it would definitely be better to name them separately (such as SavingsAccount versus CheckingAccount).


I hated the versions. But, in reality, I had to bite it and do versions in my c++ libraries, to better help my users. I used namespaces.

I used to ask my users (show them with sample code) to use appropriate "using namespace proj_lib_v1" declaration.

The evolution of code gets a bit tough though at times. You would be putting all your packages into a different namespaces (as many times as versions). I used to take out all the helper classes and put them into a different namespace (not exposed to the users).


0

Well, some of your options might depend on how much flexibility you have in declaring your URLs (I'm not entirely familiar with all the options available in Spring).

First off, if you have no flexibility at all, then I would suggest using the class name specification, unless your URLs map directly to your package structure, as it would be more straightforward to do things logically. Your API users will be using the URL, and not the class. The maintainers should really know the difference before mucking around in code.

If you have the ability to specify URLs to methods, like in some annotation packages, then you could have the same class provide both versions. Or there might be some magical way in Spring to do that in the web.xml file (or similar mapping file).

Your URL API is what is most important in REST. Structure of packages and classes should either be explained in package.xml (or other in-code documentation) or follow the URL logically.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.