Welcome Guest ( Log In | Register )

Outline · [ Standard ] · Linear+

 Versioning your rest api

views
     
TSlife4
post Feb 23 2021, 03:40 PM, updated 4y ago

Getting Started
**
Junior Member
211 posts

Joined: Apr 2012
How you guy versioning your rest api without code duplication?

1. if version like v1, v2 in the url then part of the logic change but not compatible with v1 how to change without duplication?

2. if like signature of the some service method change in v2 logic, how u going to manage this kind of change without code duplication and impact the v1

Any tools or way to follow or cleaner way to do instead like controllerv2 servicemethodv2 etc?


Thanks.

This post has been edited by life4: Feb 23 2021, 10:58 PM
ketnave
post Feb 23 2021, 04:09 PM

Enthusiast
*****
Senior Member
850 posts

Joined: Sep 2009
From: douchistan, pekopon


QUOTE(life4 @ Feb 23 2021, 03:40 PM)
How you guy versioning your rest api without code duplication?

1. if version like v1, v2 in the url then part of the logic change but not compatible with v1 how to change without duplication?

2. if like signature of the some service method change in v2 logic, how u going to manage this kind of change without code duplication and impact the v1

Any tools or way to follow?
Thanks.
*
If there's no change in logic for v2, then I will add route for v2 to point to the same class/function in v1.

Example:

No logic change for login in v1 and v2, so I will point it back to the User controller login function
$routes->get('/v1/login', 'User::login');
$routes->get('/v2/login', 'User::login');

If there's logic changes for profile under v2 api, then I will point the v2 route to the new function under User controller, v1
$routes->get('/v1/profile', 'User::profile');
$routes->get('/v2/profile', 'User::multiProfile');
flying_duck
post Feb 23 2021, 07:39 PM

Getting Started
**
Junior Member
269 posts

Joined: Mar 2020


QUOTE(life4 @ Feb 23 2021, 03:40 PM)
How you guy versioning your rest api without code duplication?

1. if version like v1, v2 in the url then part of the logic change but not compatible with v1 how to change without duplication?

2. if like signature of the some service method change in v2 logic, how u going to manage this kind of change without code duplication and impact the v1

Any tools or way to follow?
Thanks.
*
If you are using ASP.Net,
you may refer to this https://github.com/microsoft/aspnet-api-versioning

TSlife4
post Feb 23 2021, 09:43 PM

Getting Started
**
Junior Member
211 posts

Joined: Apr 2012
QUOTE(flying_duck @ Feb 23 2021, 07:39 PM)
If you are using ASP.Net,
you may refer to this https://github.com/microsoft/aspnet-api-versioning
*
no experience with asp but i roughly go through , does that mean the api it self will always pass the version number to like service method? the service method calling another method then pass down like that
and do customization of the method acorddinly to api?


but if i need to add another param pass to controller(let say v1 do not have but v2 needed) and pass to service method , this will still duplicate the logic right? or my understanding wrong?


TSlife4
post Feb 23 2021, 09:44 PM

Getting Started
**
Junior Member
211 posts

Joined: Apr 2012
QUOTE(ketnave @ Feb 23 2021, 04:09 PM)
If there's no change in logic for v2, then I will add route for v2 to point to the same class/function in v1.

Example:

No logic change for login in v1 and v2, so I will point it back to the User controller login function
$routes->get('/v1/login', 'User::login');
$routes->get('/v2/login', 'User::login');

If there's logic changes for profile under v2 api, then I will point the v2 route to the new function under User controller, v1
$routes->get('/v1/profile', 'User::profile');
$routes->get('/v2/profile', 'User::multiProfile');
*
git got v3,v4,v5 then just keep growing the new function?
silverhawk
post Feb 23 2021, 10:07 PM

I'm Positively Lustrous
Group Icon
Elite
4,735 posts

Joined: Jan 2003


Your routing logic needs to have a default fallback. Then if a new version requires something that breaks compatibility, you define a new route for the new version.

So it doesn't matter if someone tries to do /v3/login, if that route doesn't exist but the default fallback "/v1/login" exists, it will load that instead.

flying_duck
post Feb 23 2021, 10:14 PM

Getting Started
**
Junior Member
269 posts

Joined: Mar 2020


QUOTE(life4 @ Feb 23 2021, 09:43 PM)
no experience with asp but i roughly go through , does that mean the api it self will always pass the version number to like service method? the service method calling another method then pass down like that
and do customization of the method acorddinly to api?
but if i need to add another param pass to controller(let say v1 do not have but v2 needed) and pass to service method , this will still duplicate the logic right? or my understanding wrong?
*
It's a matter of methodology..
Your understanding may not be wrong, but your methodology probably is.

For example, in your scenario, v2 has an additional parameter that v1 does not have.
If you say "this will still duplicate the logic right?", that means these 2 APIs with different versions are doing the same thing and you are now violating the DRY principle.
If your logic is duplicated, you wouldn't need another version for it in the first place.
TSlife4
post Feb 23 2021, 10:52 PM

Getting Started
**
Junior Member
211 posts

Joined: Apr 2012
QUOTE(flying_duck @ Feb 23 2021, 10:14 PM)
It's a matter of methodology..
Your understanding may not be wrong, but your methodology probably is.

For example, in your scenario, v2 has an additional parameter that v1 does not have.
If you say "this will still duplicate the logic right?", that means these 2 APIs with different versions are doing the same thing and you are now violating the DRY principle.
If your logic is duplicated, you wouldn't need another version for it in the first place.
*
i mean not totally the same but there are might be just minor change only but maybe 80 percentage are the same. but you surely can can refactor the common part but if this keep growing will not be very hard to

maintain?


and if with this methodology will not be hard to maintain? if passing the version number to the service method to do customization seem prefer way is create method2 can calling this will be more clean cut as like you
are versioning ur service method with pass paramerter which not clear break the method self descritpoin as can do v1 or v2
TSlife4
post Feb 23 2021, 10:53 PM

Getting Started
**
Junior Member
211 posts

Joined: Apr 2012
QUOTE(silverhawk @ Feb 23 2021, 10:07 PM)
Your routing logic needs to have a default fallback. Then if a new version requires something that breaks compatibility, you define a new route for the new version.

So it doesn't matter if someone tries to do /v3/login, if that route doesn't exist but the default fallback "/v1/login" exists, it will load that instead.
*
but what i am asking is how to version the api without code duplication or a cleaner way not routing problem

This post has been edited by life4: Feb 23 2021, 10:57 PM
ketnave
post Feb 24 2021, 02:09 PM

Enthusiast
*****
Senior Member
850 posts

Joined: Sep 2009
From: douchistan, pekopon


QUOTE(life4 @ Feb 23 2021, 09:44 PM)
git got v3,v4,v5 then just keep growing the new function?
*
There's gotta be reason as to why you are creating a new version of the API, right ?

It could be your initial /v1/login does not integrate with other IAM, then your /v2/login you want to now support logging in with other IAM (say Okta and Auth0). Clearly, you will need to introduce new function/code for /v2/login right ? As to how much code will be duplicated on /v2/login, that depends on how you want to approach it right ? You can rewrite everything or try to reuse as much as possible.

Old version are slowly deprecated and you inform your client or users to migrate over to the newer version of your API. That's my 2 cents.
silverhawk
post Feb 24 2021, 06:09 PM

I'm Positively Lustrous
Group Icon
Elite
4,735 posts

Joined: Jan 2003


QUOTE(life4 @ Feb 23 2021, 10:53 PM)
but what i am asking is how to version the api without code duplication or a cleaner way not routing problem
*
you achieve it via routing, so when you have a breaking change in the next version, you just write the code for that, and you make a route for it. The routes that didn't change, you don't need to do anything. This only works if you have a fallback route of course.

So for example
CODE

/v1/login -- [routes to] --> AuthController::login
/v1/logout -- [routes to] --> AuthController::logout


Then say you have a new auth protocol for v2. You write a new method in the AuthController called "loginv2"
CODE

/v2/login [routes to] AuthController::loginv2


Say your logout method doesn't need to be changed, but someone is using v2 as the version and calls "/v2/logout", the route will do
CODE

/v2/logout [route doesnt exist] -> [look for fallback version: found /v1/logout] -- [routes to] --> AuthController::logout


So the only things you had to do is
1. Write the new method
2. Write the new route

No code duplication.
TSlife4
post Feb 26 2021, 01:08 AM

Getting Started
**
Junior Member
211 posts

Joined: Apr 2012
QUOTE(ketnave @ Feb 24 2021, 02:09 PM)
There's gotta be reason as to why you are creating a new version of the API, right ?

It could be your initial /v1/login does not integrate with other IAM, then your /v2/login you want to now support logging in with other IAM (say Okta and Auth0). Clearly, you will need to introduce new function/code for /v2/login right ? As to how much code will be duplicated on /v2/login, that depends on how you want to approach it right ? You can rewrite everything or try to reuse as much as possible.

Old version are slowly deprecated and you inform your client or users to migrate over to the newer version of your API. That's my 2 cents.
*
yea if a completely different logic then i think surely no problem doing like that, what i am asking like 80 percentage are similar . we all know best way is to deprecte api but let says you have 10k client , impossible like you inform everyone to ask them to change though like you said gradually deprecated the api

or like mobile app you might rollout the api but some still using old app version using old api
TSlife4
post Feb 26 2021, 01:11 AM

Getting Started
**
Junior Member
211 posts

Joined: Apr 2012
QUOTE(silverhawk @ Feb 24 2021, 06:09 PM)
you achieve it via routing, so when you have a breaking change in the next version, you just write the code for that, and you make a route for it. The routes that didn't change, you don't need to do anything. This only works if you have a fallback route of course.

So for example
CODE

/v1/login -- [routes to] --> AuthController::login
/v1/logout -- [routes to] --> AuthController::logout


Then say you have a new auth protocol for v2. You write a new method in the AuthController called "loginv2"
CODE

/v2/login [routes to] AuthController::loginv2


Say your logout method doesn't need to be changed, but someone is using v2 as the version and calls "/v2/logout", the route will do
CODE

/v2/logout [route doesnt exist] -> [look for fallback version: found /v1/logout] -- [routes to] --> AuthController::logout


So the only things you had to do is
1. Write the new method
2. Write the new route

No code duplication.
*
Yea i know if the api v2 are complete different logic then doing like this is surely not problem. i am saying case like mayb 80percentage are the same logic but just minor change in api v2 how u going to version it more elegantly

and if v1 and v2 calling like service v1 at the same time adn v2 maybe need to introduce new paramenter in servicev1 and this will break the service layer one as well and further down layer if breaking the signature again. in this case how to version it

more elegantly.

This post has been edited by life4: Feb 26 2021, 01:13 AM
ketnave
post Feb 26 2021, 12:16 PM

Enthusiast
*****
Senior Member
850 posts

Joined: Sep 2009
From: douchistan, pekopon


QUOTE(life4 @ Feb 26 2021, 01:08 AM)
yea if a completely different logic then i think surely no problem doing like that,  what i am asking like 80 percentage are similar . we all know best way is to deprecte api but let says you have 10k client , impossible like you inform everyone to ask them to change though like you said gradually deprecated the api

or like mobile app you might rollout the api but some still using old app version using old api
*
Well that's more related to how would you handle your client relationship for SLA and EOL. Again, you generally don't arbitrarily roll new version of API overnight, right ? Even if you do, that does not impact your existing client or user of the existing API.

Unless your API is open to the public, say for example, a weather API that you return the current weather given an zip code / post code and you didn't require any keys or authentication to use your API, then I can understand you will have an issue informing your user that you are deprecating the API, but that's a given with public facing API, it's provided as-is basis, the best you can do is to put a note on your site and say, hey this api will be deprecated by Z date, please use our new API.

For mobile App, you can trigger an update and force all older than x version to upgrade, right ?

Of course, you reuse as much as possible since it's been tested so it makes sense to use it more. So how reusable your code depends on you, right ?

If it's 80% similar but it's tightly coupled, you will be carrying all the baggage along with 80% similarity.

All in all, if you are adamant about avoiding code duplicate, just don't version the API and just keep adding function / feature to it. You don't have to maintain multiple version and worry about code duplication but carry the risk of breaking existing. In the end, you will have to decide, which works for you and what trade off you are willing to accept. I don't think there is ever a right or wrong answer.
silverhawk
post Feb 26 2021, 10:47 PM

I'm Positively Lustrous
Group Icon
Elite
4,735 posts

Joined: Jan 2003


QUOTE(life4 @ Feb 26 2021, 01:11 AM)
Yea i know if the api v2 are complete different logic then doing like this is surely not problem. i am saying case like mayb 80percentage are the same logic but just minor change in api v2 how u going to version it more elegantly

and if v1 and v2 calling like service v1 at the same time adn v2 maybe need to introduce new paramenter in servicev1 and this will break the service layer one as well and further down layer if breaking the signature again. in this case how to version it

more elegantly.
*
Its the same

Your API url/route is just an abstraction of what happens internally. You may have to refactor your code to be more reusable internally. You can't run away from writing or modifying code, you just want to avoid duplication, and that sometimes means writing more code.
Find The Way
post Feb 27 2021, 12:18 PM

Enthusiast
*****
Senior Member
724 posts

Joined: Nov 2004


Somehow I have trouble to understand what exactly the problem is... can't we do it the old school way?

Original:
v1/login -> login_entry_function() -> ClassB -> ClassC -> ClassD

Let say the minor change happens in ClassC:
v1/login -> login_entry_function() -> ClassB -> ClassC -> ClassD
v2/login -> login_entry_function_v2() -> ClassB -> ClassC v2 -> ClassD
or
v1/login -> login_entry_function() -> ClassB -> modified ClassC -> ClassD
v2/login -> login_entry_function_v2() -> ClassB -> modified ClassC -> ClassD

ClassC v2 could be a subclass of ClassC, if makes sense.
I usually prefer to keep the entry functions very thin without much code, delegate logic implementation to classes/modules afterwards.
In login_entry_function() and login_entry_function_v2(), set version signal in flow context, then in breaking point, pick up the signal from context and execute the right code accordingly.

Zero code duplication is kinda hard. Keeping code duplication minimal is achievable if code design is done well.

Do I misunderstand anything?

This post has been edited by Find The Way: Feb 27 2021, 12:42 PM
TSlife4
post Feb 27 2021, 04:09 PM

Getting Started
**
Junior Member
211 posts

Joined: Apr 2012
QUOTE(silverhawk @ Feb 26 2021, 10:47 PM)
Its the same

Your API url/route is just an abstraction of what happens internally. You may have to refactor your code to be more reusable internally. You can't run away from writing or modifying code, you just want to avoid duplication, and that sometimes means writing more code.
*
Yea i am more asking the internal implementation part how to version it more elegantly as the routing part as none of the concern here.
TSlife4
post Feb 27 2021, 04:20 PM

Getting Started
**
Junior Member
211 posts

Joined: Apr 2012
QUOTE(Find The Way @ Feb 27 2021, 12:18 PM)
Somehow I have trouble to understand what exactly the problem is... can't we do it the old school way?

Original:
v1/login -> login_entry_function() -> ClassB -> ClassC -> ClassD

Let say the minor change happens in ClassC:
v1/login -> login_entry_function()      -> ClassB -> ClassC      -> ClassD
v2/login -> login_entry_function_v2() -> ClassB -> ClassC v2 -> ClassD
or
v1/login -> login_entry_function()      -> ClassB -> modified ClassC -> ClassD
v2/login -> login_entry_function_v2() -> ClassB -> modified ClassC -> ClassD

ClassC v2 could be a subclass of ClassC, if makes sense.
I usually prefer to keep the entry functions very thin without much code, delegate logic implementation to classes/modules afterwards.
In login_entry_function() and login_entry_function_v2(), set version signal in flow context, then in breaking point, pick up the signal from context and execute the right code accordingly.

Zero code duplication is kinda hard. Keeping code duplication minimal is achievable if code design is done well.

Do I misunderstand anything?
*
Yes you understand it correctly

for 1 option
but let say v2 it break classB , class C and class D not only class C only then in near future coming v3 then breaking the same. i am seeking if there any way more elegantly to handle versioning problem


for 2nd option
let say if in future you need to depreacted v1 then your modified class C surely contain some logic related to v1 , then how u deprecated as well? meaning require more change and testing as well same go to if comiing v3
then the modified class C will be very not clean in a way that trying to customized for each version. if the break to class B and class D again meaning customization has to be done to class B and D as well. so any more cleaning way to
handle this versioning except like reactor the duplicate code part out or doing sth like inheritance or use different composition injection.
bumpo
post Feb 28 2021, 03:29 AM

On my way
****
Junior Member
632 posts

Joined: Mar 2013


QUOTE(life4 @ Feb 27 2021, 04:20 PM)
Yes you understand it correctly

for 1 option
but let say v2 it break classB , class C and class D not only class C  only then in near future coming v3 then breaking the same. i am seeking if there any way more elegantly to handle versioning problem
for 2nd option
let say if in future you need to depreacted v1 then your modified class C surely contain some logic related to v1 , then how u deprecated as well? meaning require more change and testing as well same go to if comiing v3
then the modified class C will be very not clean in a way that trying to customized for each version. if the break to class B and class D again meaning customization has to be done to class B and D as well. so any more cleaning way to
handle this versioning except like reactor the duplicate code part out or doing sth like inheritance or use different composition injection.
*
there simply isnt any sure fire way to handle this.
there is a lot of factors to take into consideration and these factors weighs in differently depending on organization, individual, etc. so you need to decide what works for you smile.gif

some big organization do this thing where coding are scanned for "supportability" (there is a name for this and i cant remember it) among other things and part of this is to enforce a certain standard that will minimize the issue you mentioning.
this will result in functions/methods being allowed only a limited lines of codes and classes having a limited dependency/references
one of the end result would be more modular/segmented codes which reduces issues of duplicated codes and make it easier to introduce "new version"




malleus
post Feb 28 2021, 07:55 AM

Look at all my stars!!
*******
Senior Member
2,096 posts

Joined: Dec 2011
QUOTE(life4 @ Feb 27 2021, 04:20 PM)
Yes you understand it correctly

for 1 option
but let say v2 it break classB , class C and class D not only class C  only then in near future coming v3 then breaking the same. i am seeking if there any way more elegantly to handle versioning problem
for 2nd option
let say if in future you need to depreacted v1 then your modified class C surely contain some logic related to v1 , then how u deprecated as well? meaning require more change and testing as well same go to if comiing v3
then the modified class C will be very not clean in a way that trying to customized for each version. if the break to class B and class D again meaning customization has to be done to class B and D as well. so any more cleaning way to
handle this versioning except like reactor the duplicate code part out or doing sth like inheritance or use different composition injection.
*
My personal preference these days is to opt for better maintainability, and DRY may not be suitable for this all the time. Not having code duplications is good, until it gets in the way of maintainability. So for proper separation of concerns, my opinion is that it is ok to have some duplications across the different versions, so when you deprecate the older version, you can just remove the old route and then the relevant files without effecting the newer versions.

In other words, keep the DRY within the same version only.

2 Pages  1 2 >Top
 

Change to:
| Lo-Fi Version
0.0162sec    0.21    5 queries    GZIP Disabled
Time is now: 28th March 2024 - 04:39 PM