Topics

Coupling Between Microservices

Drasko DRASKOVIC <drasko@...>
 

Hi all,
on last Go meeting we mentioned two problems:
- shared DB instances between microservices
- shared libs (data models, Java clases) between microservices

IMHO both are wrong. While almost everybody agrees that DBs should be
separated (duplicated), we did not have unison agreement on shared
libs.

I would kindly like to remind you that I have sent a (long) e-mail of
my research on the subject:
https://lists.edgexfoundry.org/pipermail/edgex-golang/2017-October/000001.html,
and I would like some feedback on this. Please follow the links in the
e-mail, I tried to select only the articles that look credible to me.

Dejan, Nikola,
as more experienced architects than me, can you please give some more
information why libraries (data models) should not be shared between
microservices, and also how is this problem solved in practice - is it
by data duplication in each of the services?

Best regards,
Drasko DRASKOVIC
Mainflux Author and Technical Advisor

www.mainflux.com | Industrial IoT Cloud
-------------------------------------------------------------------
Engineering Division | Paris, France

LinkedIn: https://www.linkedin.com/in/draskodraskovic
Twitter: @draskodraskovic

Car, Boran <Boran.Car@...>
 

Drasko,

You have a valid point, but there is a limit to it all. I'm taking this quote from https://blog.philipphauer.de/dont-share-libraries-among-microservices/:

"It's okay to have libraries for technical concerns (e.g. for logging or monitoring), because it's not likely for a business requirement to affect these concerns. But never move business and domain logic to libraries, because this will lead to frequently updates and deployments of all microservices. For instance, if the domain model classes are placed in a library and a new business requirement demands a change in this model we have to update all microservices using this model. Besides, in a microservice architecture, every microservice should be a bounded context anyway (see domain-driven design). Therefore, a microservice should have its own domain model. So there should be no reason for another microservice to use exactly the same domain classes."

And I completely agree with it. At Thales e-Security we're trying to prepare a template building block for microservices and have these aspect bits for logging and monitoring injected from a shared library. I'd say treat it as you would Aspect Oriented Programming and it's not a black and white approach. If two microservices of different kinds share the same business logic, that's better but that's also a potential refactor/redesign in the future, but aspects should be shared IMHO, with the ability to inject different aspect providers.

As for the database, I perfectly agree with you and have seen the concept breaking over eventually. Your solution with creating a data access API is sound, but we need to take some pragmatism. This data access thing may eventually become a shared aspect, too, and get injected. I don't know enough to recommend or take either side, but can present the case of Istio (https://istio.io/), which is a mesh network solution and it gets injected as a side-car (it's possibly the only side-car approach I like so far :) ) if it inspires anyone to take either side.

Regards,
Boran

-----Original Message-----
From: edgex-golang-bounces@... [mailto:edgex-golang-
bounces@...] On Behalf Of Drasko DRASKOVIC
Sent: 19 October 2017 16:08
To: edgex-devel@...; edgex-
golang@...; White, James (Dell); Tyler.Cox@...;
espy; dejan.mjc; Janko Isidorovic; darko@...; Nikola Marcetic;
manuel@...
Subject: [Edgex-golang] Coupling Between Microservices

Hi all,
on last Go meeting we mentioned two problems:
- shared DB instances between microservices
- shared libs (data models, Java clases) between microservices

IMHO both are wrong. While almost everybody agrees that DBs should be
separated (duplicated), we did not have unison agreement on shared libs.

I would kindly like to remind you that I have sent a (long) e-mail of my
research on the subject:
https://lists.edgexfoundry.org/pipermail/edgex-golang/2017-
October/000001.html,
and I would like some feedback on this. Please follow the links in the e-mail, I
tried to select only the articles that look credible to me.

Dejan, Nikola,
as more experienced architects than me, can you please give some more
information why libraries (data models) should not be shared between
microservices, and also how is this problem solved in practice - is it by data
duplication in each of the services?

Best regards,
Drasko DRASKOVIC
Mainflux Author and Technical Advisor

www.mainflux.com | Industrial IoT Cloud
-------------------------------------------------------------------
Engineering Division | Paris, France

LinkedIn: https://www.linkedin.com/in/draskodraskovic
Twitter: @draskodraskovic

_______________________________________________
EdgeX-GoLang mailing list
EdgeX-GoLang@...
https://lists.edgexfoundry.org/mailman/listinfo/edgex-golang

Car, Boran <Boran.Car@...>
 

My mistake, I mean to say if two microservices of different kind replicate the same business logic, in line with the article you shared originally.

-----Original Message-----
From: Car, Boran
Sent: 19 October 2017 18:04
To: 'Drasko DRASKOVIC'; edgex-devel@...; edgex-
golang@...
Subject: RE: [Edgex-golang] Coupling Between Microservices

Drasko,

You have a valid point, but there is a limit to it all. I'm taking this quote from
https://blog.philipphauer.de/dont-share-libraries-among-microservices/:

"It's okay to have libraries for technical concerns (e.g. for logging or
monitoring), because it's not likely for a business requirement to affect these
concerns. But never move business and domain logic to libraries, because
this will lead to frequently updates and deployments of all microservices. For
instance, if the domain model classes are placed in a library and a new
business requirement demands a change in this model we have to update all
microservices using this model. Besides, in a microservice architecture, every
microservice should be a bounded context anyway (see domain-driven
design). Therefore, a microservice should have its own domain model. So
there should be no reason for another microservice to use exactly the same
domain classes."

And I completely agree with it. At Thales e-Security we're trying to prepare a
template building block for microservices and have these aspect bits for
logging and monitoring injected from a shared library. I'd say treat it as you
would Aspect Oriented Programming and it's not a black and white approach.
If two microservices of different kinds share the same business logic, that's
better but that's also a potential refactor/redesign in the future, but aspects
should be shared IMHO, with the ability to inject different aspect providers.

As for the database, I perfectly agree with you and have seen the concept
breaking over eventually. Your solution with creating a data access API is
sound, but we need to take some pragmatism. This data access thing may
eventually become a shared aspect, too, and get injected. I don't know
enough to recommend or take either side, but can present the case of Istio
(https://istio.io/), which is a mesh network solution and it gets injected as a
side-car (it's possibly the only side-car approach I like so far :) ) if it inspires
anyone to take either side.

Regards,
Boran

-----Original Message-----
From: edgex-golang-bounces@...
[mailto:edgex-golang- bounces@...] On Behalf Of
Drasko DRASKOVIC
Sent: 19 October 2017 16:08
To: edgex-devel@...; edgex-
golang@...; White, James (Dell);
Tyler.Cox@...; espy; dejan.mjc; Janko Isidorovic;
darko@...; Nikola Marcetic; manuel@...
Subject: [Edgex-golang] Coupling Between Microservices

Hi all,
on last Go meeting we mentioned two problems:
- shared DB instances between microservices
- shared libs (data models, Java clases) between microservices

IMHO both are wrong. While almost everybody agrees that DBs should be
separated (duplicated), we did not have unison agreement on shared libs.

I would kindly like to remind you that I have sent a (long) e-mail of
my research on the subject:
https://lists.edgexfoundry.org/pipermail/edgex-golang/2017-
October/000001.html,
and I would like some feedback on this. Please follow the links in the
e-mail, I tried to select only the articles that look credible to me.

Dejan, Nikola,
as more experienced architects than me, can you please give some more
information why libraries (data models) should not be shared between
microservices, and also how is this problem solved in practice - is it
by data duplication in each of the services?

Best regards,
Drasko DRASKOVIC
Mainflux Author and Technical Advisor

www.mainflux.com | Industrial IoT Cloud
-------------------------------------------------------------------
Engineering Division | Paris, France

LinkedIn: https://www.linkedin.com/in/draskodraskovic
Twitter: @draskodraskovic

_______________________________________________
EdgeX-GoLang mailing list
EdgeX-GoLang@...
https://lists.edgexfoundry.org/mailman/listinfo/edgex-golang

Drasko DRASKOVIC <drasko@...>
 

Hello Boran,
yes, this is a tricky separation, and I can agree that when we have a
widely use library - like a common framework - it should probably be
shared between services.

However we run into this case: In order to rewrite
`export-registration` in Go you need also structures (Java clases)
from other repo - here:
https://github.com/edgexfoundry/export-client/blob/master/src/main/java/org/edgexfoundry/controller/ExportRegistrationController.java#L97
you are referencing classes defined here:
https://github.com/edgexfoundry/export-domain/blob/master/src/main/java/org/edgexfoundry/domain/export/ExportRegistration.java#L39.
And we can say that this is OK, because `export-domain` was separated
to hold the classes of `export client` and `export-domain`.

However, This class that I mention has some members like this:
https://github.com/edgexfoundry/export-domain/blob/master/src/main/java/org/edgexfoundry/domain/export/ExportRegistration.java#L46.
And `Addressable` is not defined in the same repo. Actually -
Addressable is not even defined in the same domain - it is defined in
the Core domain and then propagated around the system:
https://github.com/edgexfoundry/core-domain/blob/master/src/main/java/org/edgexfoundry/domain/meta/Addressable.java

So, now in order to re-write on micro-service in Go, you must either
rewrite core or duplicate some of the structures (like Addressable).
And you will have the same problem to rewrite some of the
micro-services in C (for devices domain) or any other language.

This is why I think that microservices - especially domains - must
encapsulate all data models they use, and then some extent of
duplication must happen.

What is your opinion on this concrete case?

Best regards,
Drasko DRASKOVIC
Mainflux Author and Technical Advisor

www.mainflux.com | Industrial IoT Cloud
-------------------------------------------------------------------
Engineering Division | Paris, France

LinkedIn: https://www.linkedin.com/in/draskodraskovic
Twitter: @draskodraskovic


On Thu, Oct 19, 2017 at 7:06 PM, Car, Boran
<Boran.Car@...> wrote:
My mistake, I mean to say if two microservices of different kind replicate the same business logic, in line with the article you shared originally.

-----Original Message-----
From: Car, Boran
Sent: 19 October 2017 18:04
To: 'Drasko DRASKOVIC'; edgex-devel@...; edgex-
golang@...
Subject: RE: [Edgex-golang] Coupling Between Microservices

Drasko,

You have a valid point, but there is a limit to it all. I'm taking this quote from
https://blog.philipphauer.de/dont-share-libraries-among-microservices/:

"It's okay to have libraries for technical concerns (e.g. for logging or
monitoring), because it's not likely for a business requirement to affect these
concerns. But never move business and domain logic to libraries, because
this will lead to frequently updates and deployments of all microservices. For
instance, if the domain model classes are placed in a library and a new
business requirement demands a change in this model we have to update all
microservices using this model. Besides, in a microservice architecture, every
microservice should be a bounded context anyway (see domain-driven
design). Therefore, a microservice should have its own domain model. So
there should be no reason for another microservice to use exactly the same
domain classes."

And I completely agree with it. At Thales e-Security we're trying to prepare a
template building block for microservices and have these aspect bits for
logging and monitoring injected from a shared library. I'd say treat it as you
would Aspect Oriented Programming and it's not a black and white approach.
If two microservices of different kinds share the same business logic, that's
better but that's also a potential refactor/redesign in the future, but aspects
should be shared IMHO, with the ability to inject different aspect providers.

As for the database, I perfectly agree with you and have seen the concept
breaking over eventually. Your solution with creating a data access API is
sound, but we need to take some pragmatism. This data access thing may
eventually become a shared aspect, too, and get injected. I don't know
enough to recommend or take either side, but can present the case of Istio
(https://istio.io/), which is a mesh network solution and it gets injected as a
side-car (it's possibly the only side-car approach I like so far :) ) if it inspires
anyone to take either side.

Regards,
Boran

-----Original Message-----
From: edgex-golang-bounces@...
[mailto:edgex-golang- bounces@...] On Behalf Of
Drasko DRASKOVIC
Sent: 19 October 2017 16:08
To: edgex-devel@...; edgex-
golang@...; White, James (Dell);
Tyler.Cox@...; espy; dejan.mjc; Janko Isidorovic;
darko@...; Nikola Marcetic; manuel@...
Subject: [Edgex-golang] Coupling Between Microservices

Hi all,
on last Go meeting we mentioned two problems:
- shared DB instances between microservices
- shared libs (data models, Java clases) between microservices

IMHO both are wrong. While almost everybody agrees that DBs should be
separated (duplicated), we did not have unison agreement on shared libs.

I would kindly like to remind you that I have sent a (long) e-mail of
my research on the subject:
https://lists.edgexfoundry.org/pipermail/edgex-golang/2017-
October/000001.html,
and I would like some feedback on this. Please follow the links in the
e-mail, I tried to select only the articles that look credible to me.

Dejan, Nikola,
as more experienced architects than me, can you please give some more
information why libraries (data models) should not be shared between
microservices, and also how is this problem solved in practice - is it
by data duplication in each of the services?

Best regards,
Drasko DRASKOVIC
Mainflux Author and Technical Advisor

www.mainflux.com | Industrial IoT Cloud
-------------------------------------------------------------------
Engineering Division | Paris, France

LinkedIn: https://www.linkedin.com/in/draskodraskovic
Twitter: @draskodraskovic

_______________________________________________
EdgeX-GoLang mailing list
EdgeX-GoLang@...
https://lists.edgexfoundry.org/mailman/listinfo/edgex-golang

Car, Boran <Boran.Car@...>
 

Hi Drasko,

I would side here with you and also recommend duplicating these type definitions (in code). The reason being, from my side, is we will inevitable end up changing them somewhat and that will lead to backwards compatibility issues. The best way to handle this in a centralized way is not to handle it in a library centralized way :), but have a global external xml/json/swagger/raml/(IDL)/(just plain documentation) definition and be generated/manually written again with some versioning spice on top. There's no duplication in that case, per se, but there's still the global schema that is the documentation and the base=truth. E.g. kinda like an API spec that microservices follow for the sake of interoperability, even if some use v1 of it, some others v2 and there might the need for an occasional adapter. Am I reading you right here?

Regards,
Boran
________________________________________
From: Drasko DRASKOVIC <drasko@...>
Sent: Thursday, October 19, 2017 9:19 PM
To: Car, Boran
Cc: edgex-devel@...; edgex-golang@...
Subject: Re: [Edgex-golang] Coupling Between Microservices

Hello Boran,
yes, this is a tricky separation, and I can agree that when we have a
widely use library - like a common framework - it should probably be
shared between services.

However we run into this case: In order to rewrite
`export-registration` in Go you need also structures (Java clases)
from other repo - here:
https://github.com/edgexfoundry/export-client/blob/master/src/main/java/org/edgexfoundry/controller/ExportRegistrationController.java#L97
you are referencing classes defined here:
https://github.com/edgexfoundry/export-domain/blob/master/src/main/java/org/edgexfoundry/domain/export/ExportRegistration.java#L39.
And we can say that this is OK, because `export-domain` was separated
to hold the classes of `export client` and `export-domain`.

However, This class that I mention has some members like this:
https://github.com/edgexfoundry/export-domain/blob/master/src/main/java/org/edgexfoundry/domain/export/ExportRegistration.java#L46.
And `Addressable` is not defined in the same repo. Actually -
Addressable is not even defined in the same domain - it is defined in
the Core domain and then propagated around the system:
https://github.com/edgexfoundry/core-domain/blob/master/src/main/java/org/edgexfoundry/domain/meta/Addressable.java

So, now in order to re-write on micro-service in Go, you must either
rewrite core or duplicate some of the structures (like Addressable).
And you will have the same problem to rewrite some of the
micro-services in C (for devices domain) or any other language.

This is why I think that microservices - especially domains - must
encapsulate all data models they use, and then some extent of
duplication must happen.

What is your opinion on this concrete case?

Best regards,
Drasko DRASKOVIC
Mainflux Author and Technical Advisor

www.mainflux.com | Industrial IoT Cloud
-------------------------------------------------------------------
Engineering Division | Paris, France

LinkedIn: https://www.linkedin.com/in/draskodraskovic
Twitter: @draskodraskovic


On Thu, Oct 19, 2017 at 7:06 PM, Car, Boran
<Boran.Car@...> wrote:
My mistake, I mean to say if two microservices of different kind replicate the same business logic, in line with the article you shared originally.

-----Original Message-----
From: Car, Boran
Sent: 19 October 2017 18:04
To: 'Drasko DRASKOVIC'; edgex-devel@...; edgex-
golang@...
Subject: RE: [Edgex-golang] Coupling Between Microservices

Drasko,

You have a valid point, but there is a limit to it all. I'm taking this quote from
https://blog.philipphauer.de/dont-share-libraries-among-microservices/:

"It's okay to have libraries for technical concerns (e.g. for logging or
monitoring), because it's not likely for a business requirement to affect these
concerns. But never move business and domain logic to libraries, because
this will lead to frequently updates and deployments of all microservices. For
instance, if the domain model classes are placed in a library and a new
business requirement demands a change in this model we have to update all
microservices using this model. Besides, in a microservice architecture, every
microservice should be a bounded context anyway (see domain-driven
design). Therefore, a microservice should have its own domain model. So
there should be no reason for another microservice to use exactly the same
domain classes."

And I completely agree with it. At Thales e-Security we're trying to prepare a
template building block for microservices and have these aspect bits for
logging and monitoring injected from a shared library. I'd say treat it as you
would Aspect Oriented Programming and it's not a black and white approach.
If two microservices of different kinds share the same business logic, that's
better but that's also a potential refactor/redesign in the future, but aspects
should be shared IMHO, with the ability to inject different aspect providers.

As for the database, I perfectly agree with you and have seen the concept
breaking over eventually. Your solution with creating a data access API is
sound, but we need to take some pragmatism. This data access thing may
eventually become a shared aspect, too, and get injected. I don't know
enough to recommend or take either side, but can present the case of Istio
(https://istio.io/), which is a mesh network solution and it gets injected as a
side-car (it's possibly the only side-car approach I like so far :) ) if it inspires
anyone to take either side.

Regards,
Boran

-----Original Message-----
From: edgex-golang-bounces@...
[mailto:edgex-golang- bounces@...] On Behalf Of
Drasko DRASKOVIC
Sent: 19 October 2017 16:08
To: edgex-devel@...; edgex-
golang@...; White, James (Dell);
Tyler.Cox@...; espy; dejan.mjc; Janko Isidorovic;
darko@...; Nikola Marcetic; manuel@...
Subject: [Edgex-golang] Coupling Between Microservices

Hi all,
on last Go meeting we mentioned two problems:
- shared DB instances between microservices
- shared libs (data models, Java clases) between microservices

IMHO both are wrong. While almost everybody agrees that DBs should be
separated (duplicated), we did not have unison agreement on shared libs.

I would kindly like to remind you that I have sent a (long) e-mail of
my research on the subject:
https://lists.edgexfoundry.org/pipermail/edgex-golang/2017-
October/000001.html,
and I would like some feedback on this. Please follow the links in the
e-mail, I tried to select only the articles that look credible to me.

Dejan, Nikola,
as more experienced architects than me, can you please give some more
information why libraries (data models) should not be shared between
microservices, and also how is this problem solved in practice - is it
by data duplication in each of the services?

Best regards,
Drasko DRASKOVIC
Mainflux Author and Technical Advisor

www.mainflux.com | Industrial IoT Cloud
-------------------------------------------------------------------
Engineering Division | Paris, France

LinkedIn: https://www.linkedin.com/in/draskodraskovic
Twitter: @draskodraskovic

_______________________________________________
EdgeX-GoLang mailing list
EdgeX-GoLang@...
https://lists.edgexfoundry.org/mailman/listinfo/edgex-golang

Car, Boran <Boran.Car@...>
 

Alternatively, if it is never visible externally, I'd just say bluntly duplicate it and microservices are free to own/evolve their data schemas (as they should). Any deviation is local and contained.

Regards,
Boran
________________________________________
From: edgex-golang-bounces@... <edgex-golang-bounces@...> on behalf of Car, Boran <Boran.Car@...>
Sent: Thursday, October 19, 2017 10:44 PM
To: Drasko DRASKOVIC
Cc: edgex-devel@...; edgex-golang@...
Subject: Re: [Edgex-golang] Coupling Between Microservices

Hi Drasko,

I would side here with you and also recommend duplicating these type definitions (in code). The reason being, from my side, is we will inevitable end up changing them somewhat and that will lead to backwards compatibility issues. The best way to handle this in a centralized way is not to handle it in a library centralized way :), but have a global external xml/json/swagger/raml/(IDL)/(just plain documentation) definition and be generated/manually written again with some versioning spice on top. There's no duplication in that case, per se, but there's still the global schema that is the documentation and the base=truth. E.g. kinda like an API spec that microservices follow for the sake of interoperability, even if some use v1 of it, some others v2 and there might the need for an occasional adapter. Am I reading you right here?

Regards,
Boran
________________________________________
From: Drasko DRASKOVIC <drasko@...>
Sent: Thursday, October 19, 2017 9:19 PM
To: Car, Boran
Cc: edgex-devel@...; edgex-golang@...
Subject: Re: [Edgex-golang] Coupling Between Microservices

Hello Boran,
yes, this is a tricky separation, and I can agree that when we have a
widely use library - like a common framework - it should probably be
shared between services.

However we run into this case: In order to rewrite
`export-registration` in Go you need also structures (Java clases)
from other repo - here:
https://github.com/edgexfoundry/export-client/blob/master/src/main/java/org/edgexfoundry/controller/ExportRegistrationController.java#L97
you are referencing classes defined here:
https://github.com/edgexfoundry/export-domain/blob/master/src/main/java/org/edgexfoundry/domain/export/ExportRegistration.java#L39.
And we can say that this is OK, because `export-domain` was separated
to hold the classes of `export client` and `export-domain`.

However, This class that I mention has some members like this:
https://github.com/edgexfoundry/export-domain/blob/master/src/main/java/org/edgexfoundry/domain/export/ExportRegistration.java#L46.
And `Addressable` is not defined in the same repo. Actually -
Addressable is not even defined in the same domain - it is defined in
the Core domain and then propagated around the system:
https://github.com/edgexfoundry/core-domain/blob/master/src/main/java/org/edgexfoundry/domain/meta/Addressable.java

So, now in order to re-write on micro-service in Go, you must either
rewrite core or duplicate some of the structures (like Addressable).
And you will have the same problem to rewrite some of the
micro-services in C (for devices domain) or any other language.

This is why I think that microservices - especially domains - must
encapsulate all data models they use, and then some extent of
duplication must happen.

What is your opinion on this concrete case?

Best regards,
Drasko DRASKOVIC
Mainflux Author and Technical Advisor

www.mainflux.com | Industrial IoT Cloud
-------------------------------------------------------------------
Engineering Division | Paris, France

LinkedIn: https://www.linkedin.com/in/draskodraskovic
Twitter: @draskodraskovic


On Thu, Oct 19, 2017 at 7:06 PM, Car, Boran
<Boran.Car@...> wrote:
My mistake, I mean to say if two microservices of different kind replicate the same business logic, in line with the article you shared originally.

-----Original Message-----
From: Car, Boran
Sent: 19 October 2017 18:04
To: 'Drasko DRASKOVIC'; edgex-devel@...; edgex-
golang@...
Subject: RE: [Edgex-golang] Coupling Between Microservices

Drasko,

You have a valid point, but there is a limit to it all. I'm taking this quote from
https://blog.philipphauer.de/dont-share-libraries-among-microservices/:

"It's okay to have libraries for technical concerns (e.g. for logging or
monitoring), because it's not likely for a business requirement to affect these
concerns. But never move business and domain logic to libraries, because
this will lead to frequently updates and deployments of all microservices. For
instance, if the domain model classes are placed in a library and a new
business requirement demands a change in this model we have to update all
microservices using this model. Besides, in a microservice architecture, every
microservice should be a bounded context anyway (see domain-driven
design). Therefore, a microservice should have its own domain model. So
there should be no reason for another microservice to use exactly the same
domain classes."

And I completely agree with it. At Thales e-Security we're trying to prepare a
template building block for microservices and have these aspect bits for
logging and monitoring injected from a shared library. I'd say treat it as you
would Aspect Oriented Programming and it's not a black and white approach.
If two microservices of different kinds share the same business logic, that's
better but that's also a potential refactor/redesign in the future, but aspects
should be shared IMHO, with the ability to inject different aspect providers.

As for the database, I perfectly agree with you and have seen the concept
breaking over eventually. Your solution with creating a data access API is
sound, but we need to take some pragmatism. This data access thing may
eventually become a shared aspect, too, and get injected. I don't know
enough to recommend or take either side, but can present the case of Istio
(https://istio.io/), which is a mesh network solution and it gets injected as a
side-car (it's possibly the only side-car approach I like so far :) ) if it inspires
anyone to take either side.

Regards,
Boran

-----Original Message-----
From: edgex-golang-bounces@...
[mailto:edgex-golang- bounces@...] On Behalf Of
Drasko DRASKOVIC
Sent: 19 October 2017 16:08
To: edgex-devel@...; edgex-
golang@...; White, James (Dell);
Tyler.Cox@...; espy; dejan.mjc; Janko Isidorovic;
darko@...; Nikola Marcetic; manuel@...
Subject: [Edgex-golang] Coupling Between Microservices

Hi all,
on last Go meeting we mentioned two problems:
- shared DB instances between microservices
- shared libs (data models, Java clases) between microservices

IMHO both are wrong. While almost everybody agrees that DBs should be
separated (duplicated), we did not have unison agreement on shared libs.

I would kindly like to remind you that I have sent a (long) e-mail of
my research on the subject:
https://lists.edgexfoundry.org/pipermail/edgex-golang/2017-
October/000001.html,
and I would like some feedback on this. Please follow the links in the
e-mail, I tried to select only the articles that look credible to me.

Dejan, Nikola,
as more experienced architects than me, can you please give some more
information why libraries (data models) should not be shared between
microservices, and also how is this problem solved in practice - is it
by data duplication in each of the services?

Best regards,
Drasko DRASKOVIC
Mainflux Author and Technical Advisor

www.mainflux.com | Industrial IoT Cloud
-------------------------------------------------------------------
Engineering Division | Paris, France

LinkedIn: https://www.linkedin.com/in/draskodraskovic
Twitter: @draskodraskovic

_______________________________________________
EdgeX-GoLang mailing list
EdgeX-GoLang@...
https://lists.edgexfoundry.org/mailman/listinfo/edgex-golang

_______________________________________________
EdgeX-GoLang mailing list
EdgeX-GoLang@...
https://lists.edgexfoundry.org/mailman/listinfo/edgex-golang

espy
 

On 10/19/2017 11:07 AM, Drasko DRASKOVIC wrote:
Hi all,
on last Go meeting we mentioned two problems:
- shared DB instances between microservices
- shared libs (data models, Java clases) between microservices
IMHO both are wrong. While almost everybody agrees that DBs should be
separated (duplicated), we did not have unison agreement on shared
libs.
Drasko --

Thanks for bringing this up again! Good timing, as we had a discussion earlier this week about what we think a C Device Services SDK should look like. The question about shared libraries is pretty central to how we should think about our SDKs, and what they contain.

No argument about shared db instances, but as databases aren't my forte, I'll let others take the lead there on that topic.

That said, I spent a good chunk of yesterday afternoon doing some research on microservice architecture and in particular, whether the use of shared libraries is considered good practice.

There seem to be pretty strong feelings both for and against their use, with the primary reason against being that they introduce tighter coupling between microservices and their clients. What does this mean though when the microservices are all clients of one another?

There's also a basic principal that's drilled into every software engineers' head called "Don't Repeat Yourself" (DRY) which is mentioned in many of the articles I ran across. This is a principal which has been core to my career for a long time, so call me skeptical when someone suggests that multiple implementations of the same logic is necessarily a good idea (although I understand the counter arguments).

A quick survey of blogs that address this subject seem to range from:

* "don't ever use shared libraries" [1]
* "why don't use shared libraries microservices is bad advice" [2]
* "shared libraries are OK as long as they're minimal, especially with respect to dependencies" [3]
* "shared client libraries/frameworks can be benefical" [4]

It's clear to me the answer isn't binary...

Looking at the existing architecture and in particular the existing Java implementation, there's shared library usage across *all* of the EdgeX microservices. In particular, these shared libraries can be broken into three groups:

* EdgeX Core Domain (Objects) - these classes represent the core EdgeX objects (eg. Addressable, Event, Reading, DeviceService, ...). They're used by the different microservices (including the Device Service SDK template code) to interact with the REST APIs of other microservices. In addition these classes handle JSON marshalling/unmarshalling (ie. the current language of our REST APIs).

[Note - with regards to the domain objects. As these are tied to our REST APIs, we should disallow changes which break existing code. If an object needs to be changed in an incompatible manner, then a new name should be used, new REST endpoints introduced, or existing endpoints should bump their version numbers.]

* EdgeX Client Libraries - these are helper classes for interacting with a set of object specific REST API endpoints exposed by a service. The Java code leverages Spring Frameworks, whereas the Go code (unreleased) actually implements the HTTP logic for each REST API method.

* EdgeX Support Libraries - these are helper classes that provide a support services such as support-logging.

Do we really want every microservice to implement their own versions of these libraries? I could see an argument for someone wanting to implement their own client libraries, but re-implementation of the core domain objects seems like a big task for anyone developing a new service. The general consensus also seems to be that libraries that provide helper/support code (eg. support-logging) don't result in tighter coupling, and therefore are OK.

This discussion also is relevant to the re-design of the Java Device Services SDK. In addition to using all of the above shared libraries, the Device Services SDK currently includes ~40 templated classes that are copied into a new DS project. There's about 3k lines of code in these classes. Currently, this code is based on Spring Frameworks, which handles a lot of the heavy lifting, so without Spring, I imagine the amount of code required to bootstrap a new DS to be even maybe 2x the existing code size.

When I first reviewed the SDK, my biggest concern was that any bugs fixed in the template classes would not be not picked up by an existing DS that was created using the SDK. This means DS developers would need to keep any eye on changes to the SDK code, and manually apply patches as they see fit. Think about what this would mean for patches that address security vulnerabilities like the recent KRACK CVE.

The Device Services SDK code can be broken up into the following areas:

* application / daemon - code which handles configuration, startup/shutdown, config/consul support, and interactions with the host OS

* metadata registration - code that handles registration of the device service and its objects (device profiles, devices, ...) to the metadata service

* controller - code that handles HTTP configuration of the REST API endpoints

* handler - code that handles processing REST API endpoint requests; calls out to the Protocol* specific code to handle device-specific logic

* data - code to handle caching of devices, device profiles, ...

[There's a few more areas, but this should convey the breadth of code required to build a DS.]

My original goal for the Go Device Services SDK was to provide a set of packages which complement the core domain and client packages, which could be used ala carte to build a new DS. Someone should have the freedom to write a DS from the ground up, however perhaps use just our core domain library/package. Having multiple DS implementations share the boilerplate daemon and metadata registration code also doesn't result in a more tightly coupled system. A DS by default is already tightly coupled to core data and metadata, so why not provide working code that someone can choose to leverage?

Regards,
/tony

[1] https://blog.philipphauer.de/dont-share-libraries-among-microservices/
[2] http://www.grahamlea.com/2016/04/shared-libraries-in-microservices-bad-advice/
[3] http://www.vinaysahni.com/best-practices-for-building-a-microservice-architecture
[4] http://blog.scottlogic.com/2016/06/13/code-reuse-in-microservices-architecture.html

Car, Boran <Boran.Car@...>
 

I think it's time for a Jim moment: "So what I'm hearing is..." etc... to bring some conclusions :). Possibly around the line that it's not all black and white, but I'm not going to even try it - I'd probably be a bad replacement.

Tony,

The extra research is quite useful. I would maybe add that strong opinions on either side of the fence meant that someone got burned in the past. Going back to late 90s, early 2000s where the consensus was you create 3 packages, common, client and server and common is shared by both the client and the server in an DRY attempt. I've actually seen that perverted at one of the companies I worked for that had an embedded device connected to PCI/PCIe, the driver and the host side software, and they were all sharing some marshall/unmarshall common C code making it almost impossible to split these 3 things into separate repos (and upstream the driver). Nowadays, we're now more into spec files and generation in order to separate and decouple. But, I digress...

What are your specific opinions on things like the data types, e.g. https://github.com/edgexfoundry/export-domain/blob/master/src/main/java/org/edgexfoundry/domain/export/ExportRegistration.java and https://github.com/edgexfoundry/core-domain/blob/master/src/main/java/org/edgexfoundry/domain/meta/Addressable.java. I was seeing Drasko's point here and raising it by one perhaps - if they're part of the external API, then I'd recommend them generated from a centralized specification and injected or copied or whatever, but also add versioning spice on top. If they're never visible externally, I'd just bluntly duplicate them and let each microservice evolve its own thing from it. And I think newcomer developers might just appreciate that more, knowing that it's only internal to them and they get to change whatever they'd like. It would also send a strong message if they wanted to have that change replicated across multiple microservices that they should probably go to specification and then generation.

Helping new developers doesn't necessarily mean getting them to link with a shared library. E.g. at Thales e-Security we have that building block template that gives you a nice starting point for writing your business logic by injecting things inside. I would say think of Dependency Injection the Docker/habitus way.

Regards,
Boran

-----Original Message-----
From: edgex-golang-bounces@... [mailto:edgex-golang-
bounces@...] On Behalf Of espy
Sent: 20 October 2017 01:13
To: Drasko DRASKOVIC; edgex-devel@...; edgex-
golang@...; White, James (Dell); Tyler.Cox@...;
dejan.mjc; Janko Isidorovic; darko@...; Nikola Marcetic;
manuel@...
Subject: Re: [Edgex-golang] Coupling Between Microservices

On 10/19/2017 11:07 AM, Drasko DRASKOVIC wrote:
Hi all,
on last Go meeting we mentioned two problems:
- shared DB instances between microservices
- shared libs (data models, Java clases) between microservices

IMHO both are wrong. While almost everybody agrees that DBs should be
separated (duplicated), we did not have unison agreement on shared
libs.
Drasko --

Thanks for bringing this up again! Good timing, as we had a discussion earlier
this week about what we think a C Device Services SDK should look like. The
question about shared libraries is pretty central to how we should think
about our SDKs, and what they contain.

No argument about shared db instances, but as databases aren't my forte,
I'll let others take the lead there on that topic.

That said, I spent a good chunk of yesterday afternoon doing some research
on microservice architecture and in particular, whether the use of shared
libraries is considered good practice.

There seem to be pretty strong feelings both for and against their use, with
the primary reason against being that they introduce tighter coupling
between microservices and their clients. What does this mean though when
the microservices are all clients of one another?

There's also a basic principal that's drilled into every software engineers'
head called "Don't Repeat Yourself" (DRY) which is mentioned in many of the
articles I ran across. This is a principal which has been core to my career for a
long time, so call me skeptical when someone suggests that multiple
implementations of the same logic is necessarily a good idea (although I
understand the counter arguments).

A quick survey of blogs that address this subject seem to range from:

* "don't ever use shared libraries" [1]
* "why don't use shared libraries microservices is bad advice" [2]
* "shared libraries are OK as long as they're minimal, especially with respect
to dependencies" [3]
* "shared client libraries/frameworks can be benefical" [4]

It's clear to me the answer isn't binary...

Looking at the existing architecture and in particular the existing Java
implementation, there's shared library usage across *all* of the EdgeX
microservices. In particular, these shared libraries can be broken into three
groups:

* EdgeX Core Domain (Objects) - these classes represent the core EdgeX
objects (eg. Addressable, Event, Reading, DeviceService, ...). They're used
by the different microservices (including the Device Service SDK template
code) to interact with the REST APIs of other microservices.
In addition these classes handle JSON marshalling/unmarshalling (ie. the
current language of our REST APIs).

[Note - with regards to the domain objects. As these are tied to our REST
APIs, we should disallow changes which break existing code. If an object
needs to be changed in an incompatible manner, then a new name should be
used, new REST endpoints introduced, or existing endpoints should bump
their version numbers.]

* EdgeX Client Libraries - these are helper classes for interacting with a set
of object specific REST API endpoints exposed by a service.
The Java code leverages Spring Frameworks, whereas the Go code
(unreleased) actually implements the HTTP logic for each REST API method.

* EdgeX Support Libraries - these are helper classes that provide a support
services such as support-logging.

Do we really want every microservice to implement their own versions of
these libraries? I could see an argument for someone wanting to implement
their own client libraries, but re-implementation of the core domain objects
seems like a big task for anyone developing a new service. The general
consensus also seems to be that libraries that provide helper/support code
(eg. support-logging) don't result in tighter coupling, and therefore are OK.

This discussion also is relevant to the re-design of the Java Device Services
SDK. In addition to using all of the above shared libraries, the Device Services
SDK currently includes ~40 templated classes that are copied into a new DS
project. There's about 3k lines of code in these classes. Currently, this code
is based on Spring Frameworks, which handles a lot of the heavy lifting, so
without Spring, I imagine the amount of code required to bootstrap a new DS
to be even maybe 2x the existing code size.

When I first reviewed the SDK, my biggest concern was that any bugs fixed in
the template classes would not be not picked up by an existing DS that was
created using the SDK. This means DS developers would need to keep any
eye on changes to the SDK code, and manually apply patches as they see fit.
Think about what this would mean for patches that address security
vulnerabilities like the recent KRACK CVE.

The Device Services SDK code can be broken up into the following areas:

* application / daemon - code which handles configuration,
startup/shutdown, config/consul support, and interactions with the host OS

* metadata registration - code that handles registration of the device
service and its objects (device profiles, devices, ...) to the metadata service

* controller - code that handles HTTP configuration of the REST API
endpoints

* handler - code that handles processing REST API endpoint requests; calls
out to the Protocol* specific code to handle device-specific logic

* data - code to handle caching of devices, device profiles, ...

[There's a few more areas, but this should convey the breadth of code
required to build a DS.]

My original goal for the Go Device Services SDK was to provide a set of
packages which complement the core domain and client packages, which
could be used ala carte to build a new DS. Someone should have the
freedom to write a DS from the ground up, however perhaps use just our
core domain library/package. Having multiple DS implementations share the
boilerplate daemon and metadata registration code also doesn't result in a
more tightly coupled system. A DS by default is already tightly coupled to
core data and metadata, so why not provide working code that someone can
choose to leverage?

Regards,
/tony

[1] https://blog.philipphauer.de/dont-share-libraries-among-microservices/
[2]
http://www.grahamlea.com/2016/04/shared-libraries-in-microservices-bad-
advice/
[3]
http://www.vinaysahni.com/best-practices-for-building-a-microservice-
architecture
[4]
http://blog.scottlogic.com/2016/06/13/code-reuse-in-microservices-
architecture.html

_______________________________________________
EdgeX-GoLang mailing list
EdgeX-GoLang@...
https://lists.edgexfoundry.org/mailman/listinfo/edgex-golang

James.White2@...
 

All,

I have been following the "conversation" in these emails with great interest - along with a few others that are occurring on related topics. I also really appreciate the time, research and thoughtfulness in the responses. Tony - you in particular earn hi praise for laying out the black, white and the grays. This week, the team has been busy trying to get the Barcelona release out the door (hopefully that happens today). I don't know if I can provide the "Jim moment" that Boran describes (I didn't realize that was a thing :) ), but I will try to provide a thoughtful response to this question over the weekend.

I do think we need to start to draw some conclusions lest we try to carry on into analysis paralysis.
________________________________________
From: edgex-golang-bounces@... <edgex-golang-bounces@...> on behalf of Car, Boran <Boran.Car@...>
Sent: Friday, October 20, 2017 6:35 AM
To: espy
Cc: edgex-devel@...; edgex-golang@...
Subject: Re: [Edgex-golang] Coupling Between Microservices

I think it's time for a Jim moment: "So what I'm hearing is..." etc... to bring some conclusions :). Possibly around the line that it's not all black and white, but I'm not going to even try it - I'd probably be a bad replacement.

Tony,

The extra research is quite useful. I would maybe add that strong opinions on either side of the fence meant that someone got burned in the past. Going back to late 90s, early 2000s where the consensus was you create 3 packages, common, client and server and common is shared by both the client and the server in an DRY attempt. I've actually seen that perverted at one of the companies I worked for that had an embedded device connected to PCI/PCIe, the driver and the host side software, and they were all sharing some marshall/unmarshall common C code making it almost impossible to split these 3 things into separate repos (and upstream the driver). Nowadays, we're now more into spec files and generation in order to separate and decouple. But, I digress...

What are your specific opinions on things like the data types, e.g. https://github.com/edgexfoundry/export-domain/blob/master/src/main/java/org/edgexfoundry/domain/export/ExportRegistration.java and https://github.com/edgexfoundry/core-domain/blob/master/src/main/java/org/edgexfoundry/domain/meta/Addressable.java. I was seeing Drasko's point here and raising it by one perhaps - if they're part of the external API, then I'd recommend them generated from a centralized specification and injected or copied or whatever, but also add versioning spice on top. If they're never visible externally, I'd just bluntly duplicate them and let each microservice evolve its own thing from it. And I think newcomer developers might just appreciate that more, knowing that it's only internal to them and they get to change whatever they'd like. It would also send a strong message if they wanted to have that change replicated across multiple microservices that they should probably go to specificatio
n and then generation.

Helping new developers doesn't necessarily mean getting them to link with a shared library. E.g. at Thales e-Security we have that building block template that gives you a nice starting point for writing your business logic by injecting things inside. I would say think of Dependency Injection the Docker/habitus way.

Regards,
Boran

-----Original Message-----
From: edgex-golang-bounces@... [mailto:edgex-golang-
bounces@...] On Behalf Of espy
Sent: 20 October 2017 01:13
To: Drasko DRASKOVIC; edgex-devel@...; edgex-
golang@...; White, James (Dell); Tyler.Cox@...;
dejan.mjc; Janko Isidorovic; darko@...; Nikola Marcetic;
manuel@...
Subject: Re: [Edgex-golang] Coupling Between Microservices

On 10/19/2017 11:07 AM, Drasko DRASKOVIC wrote:
Hi all,
on last Go meeting we mentioned two problems:
- shared DB instances between microservices
- shared libs (data models, Java clases) between microservices

IMHO both are wrong. While almost everybody agrees that DBs should be
separated (duplicated), we did not have unison agreement on shared
libs.
Drasko --

Thanks for bringing this up again! Good timing, as we had a discussion earlier
this week about what we think a C Device Services SDK should look like. The
question about shared libraries is pretty central to how we should think
about our SDKs, and what they contain.

No argument about shared db instances, but as databases aren't my forte,
I'll let others take the lead there on that topic.

That said, I spent a good chunk of yesterday afternoon doing some research
on microservice architecture and in particular, whether the use of shared
libraries is considered good practice.

There seem to be pretty strong feelings both for and against their use, with
the primary reason against being that they introduce tighter coupling
between microservices and their clients. What does this mean though when
the microservices are all clients of one another?

There's also a basic principal that's drilled into every software engineers'
head called "Don't Repeat Yourself" (DRY) which is mentioned in many of the
articles I ran across. This is a principal which has been core to my career for a
long time, so call me skeptical when someone suggests that multiple
implementations of the same logic is necessarily a good idea (although I
understand the counter arguments).

A quick survey of blogs that address this subject seem to range from:

* "don't ever use shared libraries" [1]
* "why don't use shared libraries microservices is bad advice" [2]
* "shared libraries are OK as long as they're minimal, especially with respect
to dependencies" [3]
* "shared client libraries/frameworks can be benefical" [4]

It's clear to me the answer isn't binary...

Looking at the existing architecture and in particular the existing Java
implementation, there's shared library usage across *all* of the EdgeX
microservices. In particular, these shared libraries can be broken into three
groups:

* EdgeX Core Domain (Objects) - these classes represent the core EdgeX
objects (eg. Addressable, Event, Reading, DeviceService, ...). They're used
by the different microservices (including the Device Service SDK template
code) to interact with the REST APIs of other microservices.
In addition these classes handle JSON marshalling/unmarshalling (ie. the
current language of our REST APIs).

[Note - with regards to the domain objects. As these are tied to our REST
APIs, we should disallow changes which break existing code. If an object
needs to be changed in an incompatible manner, then a new name should be
used, new REST endpoints introduced, or existing endpoints should bump
their version numbers.]

* EdgeX Client Libraries - these are helper classes for interacting with a set
of object specific REST API endpoints exposed by a service.
The Java code leverages Spring Frameworks, whereas the Go code
(unreleased) actually implements the HTTP logic for each REST API method.

* EdgeX Support Libraries - these are helper classes that provide a support
services such as support-logging.

Do we really want every microservice to implement their own versions of
these libraries? I could see an argument for someone wanting to implement
their own client libraries, but re-implementation of the core domain objects
seems like a big task for anyone developing a new service. The general
consensus also seems to be that libraries that provide helper/support code
(eg. support-logging) don't result in tighter coupling, and therefore are OK.

This discussion also is relevant to the re-design of the Java Device Services
SDK. In addition to using all of the above shared libraries, the Device Services
SDK currently includes ~40 templated classes that are copied into a new DS
project. There's about 3k lines of code in these classes. Currently, this code
is based on Spring Frameworks, which handles a lot of the heavy lifting, so
without Spring, I imagine the amount of code required to bootstrap a new DS
to be even maybe 2x the existing code size.

When I first reviewed the SDK, my biggest concern was that any bugs fixed in
the template classes would not be not picked up by an existing DS that was
created using the SDK. This means DS developers would need to keep any
eye on changes to the SDK code, and manually apply patches as they see fit.
Think about what this would mean for patches that address security
vulnerabilities like the recent KRACK CVE.

The Device Services SDK code can be broken up into the following areas:

* application / daemon - code which handles configuration,
startup/shutdown, config/consul support, and interactions with the host OS

* metadata registration - code that handles registration of the device
service and its objects (device profiles, devices, ...) to the metadata service

* controller - code that handles HTTP configuration of the REST API
endpoints

* handler - code that handles processing REST API endpoint requests; calls
out to the Protocol* specific code to handle device-specific logic

* data - code to handle caching of devices, device profiles, ...

[There's a few more areas, but this should convey the breadth of code
required to build a DS.]

My original goal for the Go Device Services SDK was to provide a set of
packages which complement the core domain and client packages, which
could be used ala carte to build a new DS. Someone should have the
freedom to write a DS from the ground up, however perhaps use just our
core domain library/package. Having multiple DS implementations share the
boilerplate daemon and metadata registration code also doesn't result in a
more tightly coupled system. A DS by default is already tightly coupled to
core data and metadata, so why not provide working code that someone can
choose to leverage?

Regards,
/tony

[1] https://blog.philipphauer.de/dont-share-libraries-among-microservices/
[2]
http://www.grahamlea.com/2016/04/shared-libraries-in-microservices-bad-
advice/
[3]
http://www.vinaysahni.com/best-practices-for-building-a-microservice-
architecture
[4]
http://blog.scottlogic.com/2016/06/13/code-reuse-in-microservices-
architecture.html

_______________________________________________
EdgeX-GoLang mailing list
EdgeX-GoLang@...
https://lists.edgexfoundry.org/mailman/listinfo/edgex-golang
_______________________________________________
EdgeX-GoLang mailing list
EdgeX-GoLang@...
https://lists.edgexfoundry.org/mailman/listinfo/edgex-golang