we have a situation where there is one event that needs to update multiple projections, and we kinda duplicate the logic: for example, we have different projections and they are interested in different pieces of information, but they all interested also in the same information for the users like (email, city, country for example), so we have some duplicated logic to update this information each time they change in all different projections, but we kinda do exactly the same logic, such issue maybe could have been solved that we put this shared piece of information(user info) in its own table/collection, and when we do the query, we do a join with this user table. but as far as I understand that this is not a good practice in CQRS. and the projection should be built and stored in the same record and we shouldn’t do such joints. What do you think? is there another way to achieve that?
In my opinion, this is not an issue. You are in a situation where each of your projections owns its data, for the price of copying/sharing some code.
This will keep your projections independent and in the optimal state(design appropriate DB schema for each specific
projection application to match requirements) all the time. This can enable individual and independent deployment of these projections, which is a big deal actually. I would do it
If you choose to share some common data (user info), you would couple your projections more. In this case, you would have some
common projection application/component that is persisting this common data in the same schema where you keep data of other projection applications. This implies that your projection applications will tend to use the same DB schemas/instances in the future. I would not do this.
The thing that you can consider doing is to create this
common projection application/module, but you persist this data in a dedicated/separate schema (as you do for other projection apps/modules I suppose). Then, you provide Axon Query API on top of this projection (you should do the same for other projection apps/modules). Your Web component(s) now can use this Query API (over the query gateway/bus) to connect this data on the API level, which will prevent tight coupling. Please mind that Axon Server is able to route Queries as well (Commands and Events can be routed), and there is no formal open-source Axon Extension that can distribute Queries at the moment.