Domain Driven Design - Services should know about other services ? Or should know multiple repositories? - javascript

I'm creating a backend application and I'm trying to implement the Domain Driven Design.
However, I had a question regarding my data structure that I intend to clarify.
Database Structure
Users
Id (PK 🔑)
First Name
Last Name
Email
Password
Customers Profile
User Id (PK / FK 🔑)
Height
Weight
Personal Trainers Profile
User Id (PK / FK 🔑)
Specialties
Taking into account the database represented above, I have some doubts on how to structure the Controllers, Services and Repositories of my application.
Let's imagine, that I want to update a Customer Profile and their User:
I call the Customer Controller (update endpoint)
The Customer Controller calls the Customer Service (update customer method)
The Customer Service calls the Customer Repository to update the Customer Profile
And to update their respective User on Users table?
Should the Customer Service call an update method from the User Service?
Or should the Customer Service call the User Repository directly?
I'm very confused, not knowing if it's correct, services know about other services, or services know repositories that theoretically belong to other services.
I will be very gratefully if someone could help me clarifying my doubts 🙂

I think the Database structure can be improved.
Rather than naming the table as Customer Profile and Personal Trainer Profile, name it as Customers and Personal Trainers.
As A Customer is a User
&
A Personal Trainer is a user
Updated Database Structure
Users
Id (PK 🔑)
First Name
Last Name
Email
Password
Customers
Id (PK 🔑)
User Id (FK 🔑)
Height
Weight
Personal Trainers
Id (PK 🔑)
User Id (FK 🔑)
Specialties
The Aggregate Roots are Customers & PersonalTrainers.
Now the Controllers and Services will be for Customers & personal trainers.
And any update to fields for users table for customers will be done via Customer Controller.
The class definition
public class Customers extends Users
&
public class PersonalTrainers extends Users

Sorry if I'll be a bit 'crude', but in your approach there's no real clue about DDD. I mean: Controllers, Services and Repositories are the 'the facto' way to develop an application with Spring. But this is not really DDD. To implement it with DDD you have to forget the database, focus on the entities of the domain, identify their functionalities and start to think how to translate this into code.
With this preface, I can say you that also within this 'the facto' approach is possible to adopt a DDD, at the price to rethink all the process that produces the code.
Hence, in your model, I would do something like this:
identify the entities of the domain that you want to model (here you have to find the root entities, aggregates and value objects -link 1, link 2);
given that the DDD is an object oriented approach, once you've identified your entities (and this is not so simple as it looks, believe me), you need to identify the functions that each entity offers. So, for example, for the PersonalTrainer entity, one possible function could be acceptTrainee(Course course, Person trainee), that add a new Person to a Course (remember, it's a sample, I have no idea about your domain).
Once you know your entities, or at least you start to identify them and some functions, you can think about the code. Here you can choose between several architectures: clean, ports & adapters, onion, 3-Layers architecture (the default and classic approach with Spring: controllers, services and repositories with entities). My personal approach is more or less what is described here.
I would suggest you to search and read a lot about how to do the things. There's no silver bullet, unfortunately: sometimes the domain is really simple and the extra overhead of a DDD and an 'unsual' architecture are totally useless; sometimes the domain is complex and big, hence a DDD approach with a more refined architecture are a much better choice.
Finally, to give you a concrete answer to work on your case, after identifying the entities and their functions I would put the model that you have produced into a domain package. Here I would also define the Repository interfaces, that you use to persist the entities (but you'll implement later). Once you have this, you can develop the services, where you put all the things together using what you have into the domain. I would put this code into an application package (but, remember, it's not a law: if you think is better, place them in a different place, or with a different name - take a look here, I really like this approach). Finally, I would start to implement the code of the infrastructure layer, where all the interfaces defined into the domain and the application layers will be implemented. Here I would put also the Controllers.
Remember: this approach allows only connections in one direction (domain -> application -> infrastructure), but never the opposite.
Finally, if you think about how to manage the domain entities with some ORM frameworks, I would suggest you to read this links: domain vs persistence model; stackoverflow question about this; domain and persistence separated.

Aggregates are independent objects that ensure consistency within the aggregate. A User represents a specific concept and a CustomerProfile another. The CustomerProfile should rather have its own Id (not necessarily UserId). Nothing stops you from modelling it as you have but keeping state changes on the two aggregate separate is going to make your life a lot easier.
That being said, whenever I do find that I have application services that make use of one another in some way I apply the good old "All problems in computer science can be solved by another level of indirection". I take the common bits and make a Task of sorts and use that in each.

Related

Best practices for refetching part of a GraphQL query with Apollo?

I have the following react-apollo-wrapped GraphQL query:
user(id: 1) {
name
friends {
id
name
}
}
As semantically represented, it fetches the user with ID 1, returns its name, and returns the id and name of all of its friends.
I then render this in a component structure like the following:
graphql(ParentComponent)
-> UserInfo
-> ListOfFriends (with the list of friends passed in)
This is all working for me. However, I wish to be able to refetch the list of friends for the current user.
I can do this.props.data.refetch() on the parent component and updates will be propagated; however, I'm not sure this is the best practice, given that my GraphQL query looks something more like this,
user(id: 1) {
name
foo1
foo2
foo3
foo4
foo5
...
friends {
id
name
}
}
Whilst the only thing I wish to refetch is the list of friends.
What is the best way to cleanly architect this? I'm thinking along the lines of binding an initially skipped GraphQL fetcher to the ListOfFriends component, which can be triggered as necessary, but would like some guidance on how this should be best done.
Thanks in advance.
I don't know why you question is downvoted because I think it is a very valid question to ask. One of GraphQL's selling points is "fetch less and more at once". A client can decide very granually what it needs from the backend. Using deeply nested graphlike queries that previously required multiple endpoints can now be expressed in a single query. At the same time over-fetching can be avoided. Now you find yourself with a big query, everything loads at once and there are no n+1 query waterfalls. But now you know that a few fields in your big query are subject to change from now and then and you want to actively update the cache with new data from the server. Apollo offers the refetch field but it loads the whole query which clearly is overfetching that was sold to me as not being a concern anymore in GraphQL. Let me offer some solutions:
Premature Optimisation?
The real problem is that programmers have spent far too much time worrying about efficiency in the wrong places and at the wrong times; premature optimization is the root of all evil (or at least most of it) in programming. - Donald Knuth
Sometimes we try to optimise too much without measuring first. Write it the easy way first and then see if it is really an issue. What exactly is slow? The network? A particular field in the query? The sheer size of the query?
After you analized what exactly is slow we can start looking into improving:
Refetch and include/skip directives
Using directives you can exclude fields from a query depending on variables. The refetch function can specify different variables than the initial query. This way you can exclude fields when you refetch the query.
Splitting up Queries
Single page apps are a great idea. The HTML is generated client side and the page does not have to make expensive trips to the server to render a new page. But soon SPAs got to big and code splitting became an issue. And now we are basically back to server side rendering and splitting the app into pages. The same might apply to GraphQL. Sometimes queries are too big and should be split. You could split up the queries for UserInfo and ListOfFriends. Inside of the cache the fields will be merged. With query batching both queries will be send in the same request and a GraphQL server that implements per request resource caching correctly (e.g. with Dataloader) will barely notice a difference.
Subscriptions
Maybe you are ready to use subscriptions already. Subscriptions send updates from the server for fields that have changed. This way you could subscribe to a user's friends and get updates in real time. The good news is that Apollo Client, Relay and many server implementations offer support for subscriptions already. The bad news is that it needs websockets that usually put different requirements on your technology stack than pure HTTP.
withApollo() -> this.client.query
This should only be your last resort! Using react-apollo's withApollo higher order component you can directly inject the ApolloClient instance. You can now execute queries using this.client.query(). { user(id: 1) { friendlist { ... } } } can be used to just fetch the friend list and update the cache which will lead to an update of your component. This might look like what you want but can haunt you in later stages of the app.

JHipster - add a relationship to jhi_user_authority

I'm acutually trying to make a one-to-many relationship between the auto generated table "jhi_user_authority" and my own table called socialMediaFilter.
My situation is the following:
On the one side I have users, these are saved in the table "jhi_user" these users have roles and the roles for themselves are saved in a table called "jhi_authority". Between users and roles is a many-to-many relation, that means that many users can have many roles. These relationships are saved in a join-table called "jhi_user_authority". All these 3 tables are auto-generated by Jhipster when I created the project.
In my project I need to add some filters for filtering data from social media networks, twitter, fb and so on. A filter belongs to a role and a role can have many filters. So between these two tables is a one-to-many relationship and I'm struggling implementing this in my project.
I cannot access these auto-generated tables with the jhipster:entity generator. When I'm using for example yo jhipster:entity authority jhipster tries to generate a new entity. And as far as I know - these auto-generated tables are not meant to be accessed by the entity-generator. So when I want to edit them I need to edit them manually, so I can not follow the instructions in the tutorial.
Is there maybe someone who can pushes me to right direction? :D
thanks,
Alex
EDIT:
okay...after thinking for a while i figured out that i need to do it different
the relationships i need to implement should be like this uml
but i still have problems realizing it
Good morning, you have to do an n-m relation with the "Authority" class, in which you must specify that the relationship table is "jhi_user_authority"

Should I use one publish per collection or several?

I am working on a user group system. Each group has several features and I want to make the interaction with the group collection as secure and simple as it can be since it is still at an early stage.
Right now, I have a group section in my website where I use several nested pages. The purpose of the section is to allow the user to get in a group, request membership if the group is private, browse one group objects, etc.
For example, within my group section, I can load in the yield a "see all groups" page, a "create a new group" page or "see only my groups" (the ones I am member of) or a "view group" to get a group details.
My first approach was to create one controller.js file for each subpage, which call one subscription tailored for the subpage needs. For instance, I have an 'all_group' publication/subscription for the "see all groups" subpage and a "my_groups" one for the "see only my groups" subpage.
But this is becoming really messy. Additionally, I declared my "group" collection in the both folder, so I am not sure to follow where the data available to the client comes from.
Now that I explained the situation, here are my questions:
when I do a console.table(Groups.find().fetch()); on client, I see fields that shouldn't be there (i.e. not returned by my current publication or any other). Is that because I declared the "group" collection on client side? How to fix that?
Should I get rid of all these publications and create only one with everything the client is allowed to see? I would then subscribe to it from the group section page controller and work with a single set of data.
Should I simply block any insert/update/remove from client with allow/deny rules and make these using methods only?
Would it be safe/advised to put my methods in both folder so I don't lose the latency compensation feature?
EDIT
Ok, I was freaking out because I had all my collection data on client-side but it was just a bad query in the publish (I was using both field:1 and field:0 projections).
Two questions remain:
If I use methods, I assume I don't have to deny everything in the native driver, I just have to be more restrictive than what method allow, right?
If I put my methods in the both folder, it will be executed both on client and server, so in "client offline" context, even if the client mess with my methods, the server should roll back the changes if the client result is different than his (assuming that the changes couldn't be done using the allow-deny rules)? And I will have latency compensation working even with the methods?
To better control and visualize your subscriptions, you can use msavin:mongol.
Creating one catch-all publication is not a good idea performance-wise (sending all data to all clients will be a pain to everyone involved).
If you use methods and have removed autopublish, then yes everything is denied... Except for updates on the user's own profile. You may want to manually deny that too.
With methods and collection rules you should share the validation code. This way, client and server validate the same way (and should always come up with the same results), so unless your client is screwing up with the console there should be no issue and lag compensation should remain.
If your server method does something the client should not know about, you can also define the method once on the server, and once on the client. Same effect.

Meteor.js - Should you denormalize data?

This question has been driving me crazy and I can't get my head around it. I come from a MySQL relational background and have been using Meteorjs and Mongo. For the purposes of this question take the example of posts and authors. One Author to Many Posts. I have come up with two ways in which to do this:
Have a single collection of posts - Each post has the author information embedded into the document. This of course leads to denormalization and issues such as if the author name changes how do you keep the data correct.
Have two collections: posts and authors - Each post has an author ID which references the authors collection. I then attempt to do a "join" on a non relational database while trying to maintain reactivity.
It seems to me with MongoDB degrees of denormalization is acceptable and I am tempted to embed as implementing joins really does feel like going against the ideals of Mongo.
Can anyone shed any light on what is the right approach especially in terms of wanting my app data to scale well and be manageable?
Thanks
Denormalisation is useful when you're scaling your application and you notice that some queries are taking too much time to complete. I also noticed that most Mongodb developers tend to forget about data normalisation but that's another topic.
Some developers say things like: "Don't use observe and observeChanges because it's slow". We're building real-time applications so that a normal thing to happen, it's a CPU intensive app design.
In my opinion, you should always aim for a normalised database design and then you have to decide, try and test which fields, that duplicated/denormalised, could improve your app's performance. Example: You remove 1 query per user. The UI need an extra field and it's fast to duplicated it, etc.
With the denormalisation you've an extra price to pay. You've to update the denormalised fields according to the main collection.
Example:
Let's say that you Authors and Articles collections. On each article you have the author name. The author might change his name. With a normalised scenario, it works fine. With a denormalised scenario you have to update the Author document name AND every single article, owned by this author, with the new name.
Keeping a normalised design makes you life easier but denormalisation, eventually, becomes necessary.
From a MeteorJs perspective: With the normalised scenario you're sending data from 2 Collections to the client. With the denormalised scenario, you only send 1 collection. You can also reactively join on the server and send 1 collection to the client, although it increases the RAM usage because of MergeBox on the server.
Denormalisation is something that it's very specify for you application needs. You can use Kadira to find ways of making your application faster. The database design is only 1 factor out of many that you play with when trying to improve performance.

Controller and View for creating one-to-many object, both "container" and unlimited number of "content" objects?

Users will be able to write some documents. Those documents will consists of chapters (one-to-many relation).
Normally I would do this by creating separate views for creating chapter and document.
How to implement web page that allow to edit "composite" view? Where I can edit document details, but also create chapters, without visiting different pages? Also how can I ensure that I pass order of chapter user have arranged (by moving chapters freely up and down)?
(Sorry if that question already have be asked&answered but I do not even know how to search for it :| since I do not know proper keywords beyond "AJAX", so help in naming my requirement would also be welcomed!)
Backend servers applications based on REST principles work nicely with Ajax client-side implementations.
For example, your URLs could be:
/book/1
/book/1/chapters
/book/1/chapter/1
You could set it up so that a POST to /book/1/chapters would add a chapter. A GET on that same URL would return all chapters. A GET on /book/1/chapter/1/ would only return chapter 1. A PUT on /book/1/chapter/1/ would update an existing chapter. This is a "RESTful" architecture:
http://en.wikipedia.org/wiki/Representational_state_transfer
This is an interesting introduction: http://tomayko.com/writings/rest-to-my-wife
This is a big subject, but if you create the right backend server architecture you will find your job a lot easier. Hope this helps answer your question.
Ok Partial solution.
Just google Nested Forms Ruby on Rails. Plenty of examples, all in ajax, all easy.

Categories