admin管理员组文章数量:1390192
I have been trying to learn NodeJS for quite some time now. All the books and tutorials seems to follow similar pattern of structuring their code. Example -
const express = require('express');
const app = express();
app.set('view engine','hbs');
app.get('/', (req, res) =>{
res.render('index');
});
app.get('/getName', (req, res) =>{
// Mock DB call to fetch Name
res.render('displayName');
});
app.listen(3000, () => {
console.log("Started server on port : 3000");
});
As you can see above, the /getName controller is performing DB call as well as returning the view. So the business logic as well as the CRUD operation is being done at the same place.
I e from the world of JAVA
and there we do it slightly differently. For example, a Spring Boot
application would contain the following structure -
- DTO
- Repository
- Service
- Controller
So, controller
classes are the actual endpoints which do not perform any business logic but call the underlying service
class to handle all that. The service
classes implement the business logic and persist/fetch data required for it with the help of the repository
classes. The repository on the other hand handles the CRUD
operations.
This seemed like a sane way to develop software. Given that each class has their defined roles, it bees really easy to handle any change.
I understand the NodeJs
is a dynamic but -
1. Is there a way to separate out the functionality like we do in Spring
? If not,
2. How to structure large projects having multiple endpoints and DB transactions.
Regards
EDIT -
Consider the following scenario -
I have a requirement, where I need to fetch a list of users from the database whose status is True ( assume status is a boolean field in the model ).
In Java -
@Service
public class UserService {
@Autowired
UserDetailRepository userDetailRepository;
@Override
public UserDetail getUserDetail (boolean status) {
UserDetail userDetail = UserDetailRepository .findUserDetailByStatus(status);
return userDetail ;
}
Controller.java -
@GetMapping("/getUserDetails")
public ArrayList<UserDetail> getUserDetail(){
return UserService.getUserDetail(true);
}
Now, if the requirement changes and there needs to be a new endpoint that returns only top 10 user details whose status is true. In that case, we can add a new controller and just limit the returned results to 10. We can make use of the same business logic/ service class.
Controller.java
@GetMapping("/getUserDetailsTop10")
public ArrayList<UserDetail> getUserDetail(){
List<UserDetails> users = UserService.getUserDetail(true);
// Filter the list to send top 10
// return users .
}
If I have to implement the same use case in NodeJS, I'll have to write the business logic to fetch the user twice -
const express = require('express');
const app = express();
app.set('view engine','hbs');
app.get('/getUserDetails', (req, res) =>{
// Call DB and get users whose status is True
res.send(userdetails);
});
app.get('/getUserDetailsTop10', (req, res) =>{
// Call DB and get users whose status is True
// Filter the returned results and limit the result to 10 values only
res.send(userdetails);
});
app.listen(3000, () => {
console.log("Started server on port : 3000");
});
At best, I can abstract away this logic into a function, that will return a list of users with status True but then again this approach is not very scalable. There has to be a plete separation of Business logic from controller.
I have been trying to learn NodeJS for quite some time now. All the books and tutorials seems to follow similar pattern of structuring their code. Example -
const express = require('express');
const app = express();
app.set('view engine','hbs');
app.get('/', (req, res) =>{
res.render('index');
});
app.get('/getName', (req, res) =>{
// Mock DB call to fetch Name
res.render('displayName');
});
app.listen(3000, () => {
console.log("Started server on port : 3000");
});
As you can see above, the /getName controller is performing DB call as well as returning the view. So the business logic as well as the CRUD operation is being done at the same place.
I e from the world of JAVA
and there we do it slightly differently. For example, a Spring Boot
application would contain the following structure -
- DTO
- Repository
- Service
- Controller
So, controller
classes are the actual endpoints which do not perform any business logic but call the underlying service
class to handle all that. The service
classes implement the business logic and persist/fetch data required for it with the help of the repository
classes. The repository on the other hand handles the CRUD
operations.
This seemed like a sane way to develop software. Given that each class has their defined roles, it bees really easy to handle any change.
I understand the NodeJs
is a dynamic but -
1. Is there a way to separate out the functionality like we do in Spring
? If not,
2. How to structure large projects having multiple endpoints and DB transactions.
Regards
EDIT -
Consider the following scenario -
I have a requirement, where I need to fetch a list of users from the database whose status is True ( assume status is a boolean field in the model ).
In Java -
@Service
public class UserService {
@Autowired
UserDetailRepository userDetailRepository;
@Override
public UserDetail getUserDetail (boolean status) {
UserDetail userDetail = UserDetailRepository .findUserDetailByStatus(status);
return userDetail ;
}
Controller.java -
@GetMapping("/getUserDetails")
public ArrayList<UserDetail> getUserDetail(){
return UserService.getUserDetail(true);
}
Now, if the requirement changes and there needs to be a new endpoint that returns only top 10 user details whose status is true. In that case, we can add a new controller and just limit the returned results to 10. We can make use of the same business logic/ service class.
Controller.java
@GetMapping("/getUserDetailsTop10")
public ArrayList<UserDetail> getUserDetail(){
List<UserDetails> users = UserService.getUserDetail(true);
// Filter the list to send top 10
// return users .
}
If I have to implement the same use case in NodeJS, I'll have to write the business logic to fetch the user twice -
const express = require('express');
const app = express();
app.set('view engine','hbs');
app.get('/getUserDetails', (req, res) =>{
// Call DB and get users whose status is True
res.send(userdetails);
});
app.get('/getUserDetailsTop10', (req, res) =>{
// Call DB and get users whose status is True
// Filter the returned results and limit the result to 10 values only
res.send(userdetails);
});
app.listen(3000, () => {
console.log("Started server on port : 3000");
});
At best, I can abstract away this logic into a function, that will return a list of users with status True but then again this approach is not very scalable. There has to be a plete separation of Business logic from controller.
Share Improve this question edited Apr 9, 2019 at 17:34 Boudhayan Dev asked Apr 9, 2019 at 16:28 Boudhayan DevBoudhayan Dev 1,0296 gold badges22 silver badges44 bronze badges 23- 2 The format of the question isn't the problem, the content of the question is. There are hundreds of different possible equally-valid answers. The Node.js ecosystem is rich and varied, there's no one way you do this. Please do see the links above, in particular this one. It's not that it's not a perfectly reasonable question to ask, it's just not suited to the format of this site. – T.J. Crowder Commented Apr 9, 2019 at 16:37
- 1 similar question is discussed to some extent here stackoverflow./questions/5178334/… – 1565986223 Commented Apr 9, 2019 at 16:54
- 1 Hmm, I'm not the best guy to answer your question. Not that experienced in backend js, but I'll try. Js munity embrace things that's light-weighted. We got runtime that has native support for first class function, event loop and such. This way we tend to naturally seek solution in patterns like pipeline chaining, observable stream, pub/sub. We too have separation of concern, but just not like java style. – hackape Commented Apr 9, 2019 at 17:03
- 1 "Only way is to create a function which can be referenced by multiple endpoints." - yes, that's precisely what you would do. (When need arises, otherwise YAGNI). You can put such functions in their own modules, files, or even write them as classes if you prefer that. I don't understand why you think this is not sufficient or scalable, or why you don't consider it to separate concerns. – Bergi Commented Apr 9, 2019 at 17:56
- 2 I think you are feeling conceptual disfort facing multi-paradigm goodness in js land. Java does have some burden going functional programming, but not in js. FP or OOP, I just go with whichever fits, depending on use case. – hackape Commented Apr 10, 2019 at 4:17
5 Answers
Reset to default 3Not really an answer... but some thoughts, as I e from C# and started as a NodeJs developer 3 years ago.
Dependency Injection
This is (sadly) rarely used in many NodeJs projects that I see. There are some npm modules that provide this feature, but none of them have convinced me with a proper approach and API. Dependency Injection is still perfectly possible, only, a bit uglier because of some boilerplate code you have to write. So sadly no easy @autowire
approaches. So yes you can do Dependency Injection like with Spring, but not as convenient. But let my opinion not stop you from researching Dependency Injection libraries for node.
Architecture
You can still use the concepts of DTOs, Repositories, Services and Controllers. Only for some (odd) reason, the majority of tutorials and guides out there forget about mon sense architecture and just throw everything within a single controller. Don't let them seduce you in forgetting about the concepts you learned in Java. Not that OOP and Java doesn't have flaws, but there is a difference in "writing JavaScript style code" and "let's forget about proper architecture all together".
Do note that you might see some more "functional programming" patterns rise in the NodeJs munity, which is not bad (but neither is OOP).
How to structure large projects having multiple endpoints and DB transactions.
Ignore the bad examples you see out there, just follow your gut feeling from your Java experience how to structure your code, with the right layers, responsibilities and Design Patterns. Only keep in mind that you don't have interfaces and there is no easy alternative to that. So you'll have to learn to work your way around that, but you can still write elegant code without them.
Middleware
Middleware is a mon concept for NodeJs applications, they are similary-ish to the proxy/aspect oriented programming style. You might find example projects with excessive amount of middleware, don't let yourself be tempted by that either. Middleware is good for auth/serialisation/headers/security but not for business logic. I've seen middleware hell and middleware driven development, it ain't pretty.
Repository
A lot of people use directly the MongoDb/Mongoose/SQL client without using the adapter pattern like Repository, leaking MongoDb queries all over their solution.
My advice for you would be, just use the same structure and approach you are familiar with, but with the tools that JavaScript gives you. I genuinely love JavaScript, but it makes me cringe when I look at the lack of design and architecture that I see in the mainstream resources, sure small projects and PoC's don't need extensive design, but often when project grow, they don't clean up. How you structure a project should be agnostic to the language and framework you are writing in.
Happy coding
本文标签: javascriptHow to apply layered architecture of JavaSpring in NodeJsStack Overflow
版权声明:本文标题:javascript - How to apply layered architecture of JavaSpring in NodeJs? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744658780a2618117.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论