I work in a Haskell project, which consists of several microservices. There are certain types that are needed by several services at the same time and therefore are defined in separate libraries that are imported depending on what they need (each type is versioned). But there are things that make me feel uncomfortable, and I was wondering which ones are best for this topic. In particular:
- I do not know how to handle instances of generic types. To avoid orphans, instances must be defined in the type module for each type. But then there are instances that are not needed by all microservices that import the package and must be included independently, which potentially adds redundant dependencies to the microservice. An example would be the data type T , which is shared by an interface and a backend. It has a Store instance to be stored in a database that is not needed by the interface, but still makes the interface dependent on the storage package.
- To avoid the previous problem, I could introduce a shell every time a type needs to “leave” a microservice to represent this type passing through a wire. In the previous example, I would have Storable T , which would have an instance for the Store . This adds quite a bit of overhead to the overall development process, though.
- Is it even a good idea to share these types, or does each microservice determine its own representation of each type, so nothing needs to be shared? Thus, for type T, the microservice MA will have an AT representation and an instance for its serialization to send data to microservice B , which decrypts this data in the MB.T representation .
And finally, regarding the material and technical side of the matter,
- What is the most convenient way to structure a project? Would monorepo be a better choice than single repositions / submodules?
- , , , , , ?