> It may be the sloppiest, crappiest definition every, with dynamic types
Funny you said that since a microservice API is always dynamically typed and its usage cannot be checked by compiler. And the more microservices you use the more dynamically typed the whole project gets overall.
While you can opt into a free for all everything importing everything, all languages do also support creating modules which define APIs for consumer and maintain compile time type checking.
> Funny you said that since a microservice API is always dynamically typed and its usage cannot be checked by compiler.
Not true at all, I have a build system in place that when changes are made to Typescript, the JSON Schema on the endpoints is updated, and client libraries are updated.
Types are validated at both compile time and runtime.
This is just one of many solutions to the problem, there are a lot of ways to get type safety for service endpoints, at both runtime and compile time.
Except each service scales independently, can be updated independently (e.g. pri0 security bugs that require a breaking change can be applied to public IP facing services first), can be written in a different programming language, and can be rolled back/deployed independently.
Working in a microservice environment is nice, newly created services get the latest version of whatever tools are needed, older services can be upgraded as needed. Avoids the problem of being stuck on some ancient version of the JVM or Node.
Although true to some extent, this is also a tooling issue. We use OpenAPI and generate clients. Strictly speaking the interoperability layer doesn't know the truth on the other side, but when generated correctly, the developer doesn't need to worry about it.
When you change function signature it doesn't compile until you fix all the call sites. Maybe after you see all the broken call sites you think that's too much work maybe there is some other way to do what I want.
When you change anything about an endpoint, it compiles just fine no matter what clients there are or what they are doing. You proceed with the change without worry. Yes, you can have some self-discipline to also generate the open api documents, generate the clients and then check all clients but self-discipline like that is not reliable.
So while tooling can help it's still not the same thing.
> When you change function signature it doesn't compile until you fix all the call sites. Maybe after you see all the broken call sites you think that's too much work maybe there is some other way to do what I want.
Improperly versioned dynamic libraries want a word with you!
Perfectly possible to foot gun yourself with compiled code and broken API boundaries.
> When you change anything about an endpoint, it compiles just fine no matter what clients there are or what they are doing.
If I am exporting a DLL, same thing happens. Working on a true monolith, the entire app is compiled as one giant executable, sure, then I get compile errors.
If you use semantic versioning correctly, then you shouldn't need to worry about api<->implementation inconsistency. Or rather, when you need to, you know which parts you have to deal with.
> Funny you said that since a microservice API is always dynamically typed and its usage cannot be checked by compiler. And the more microservices you use the more dynamically typed the whole project gets overall.
I mean this is just not true in the general sense. I've setup plenty of microservices with various typed APIs. Protobufs are an example of an extremely easy to implement, strongly typed, API tool.
I don't think you have to define a microservice by http requets with JSON.
Until you want to update a protobuf definition and then tear your hair out because you cannot atomically ship changes to clients and servers. Even if the code in your source tree says everything is a-okay that one service that hasn't been updated shits the bed when handed a proto with mismatched types.
Thus, proto definitions become an "only add, never modify or remove" thing. Not ideal.
Funny you said that since a microservice API is always dynamically typed and its usage cannot be checked by compiler. And the more microservices you use the more dynamically typed the whole project gets overall.
While you can opt into a free for all everything importing everything, all languages do also support creating modules which define APIs for consumer and maintain compile time type checking.