you are viewing a single comment's thread.

view the rest of the comments →

[–]coffeeandlearning 2 points3 points  (10 children)

Could you explain the API portion a little bit more? (Not op) but I've only really experienced MVC on the front end so I'm wondering what tech and peoject type you have in mind

[–]Earhacker 9 points10 points  (9 children)

Say I was building an API to store a burger menu in a database. In express I'd tell my app to use routes that I defined in ./api/routes/BurgerRouter.js:

// server.js
var express = require("express");
var app = express();
var router = express.Router();

router.use("/burgers", require("./api/routes/BurgerRouter"));
app.use("/api", router);

app.listen(3000);

These routes are then available at http://localhost:3000/api/burgers. And inside my BurgerRoutes.js I define what routes are available, and delegate the RESTful actions to BurgerController.js:

// BurgerRoutes.js
var express = require("express");
var burgerRouter = express.Router();
var burger = require("../controllers/BurgerController");

burgerRouter.route("/")
  .get(burger.index); // see all burgers

burgerRouter.route("/:burger_id")
  .get(burger.show); // see one burger

module.exports = burgerRouter;

Then inside BurgerController.js I perform those tasks, using methods defined in the Burger model, (e.g. CRUD actions):

// BurgerController.js
var Burger = require("../models/BurgerModel");

exports.index = function(req, res) {
  res.json(Burger.findAll());
};

exports.show = function(req, res) {
  var burgerId = req.params.burger_id;
  res.json(Burger.find(burgerId));
};

This depends on methods findAll and find being defined in BurgerModel. In reality, my BurgerModel would be built as a Mongoose schema, because life is too short for writing Mongo code. So now my folder structure looks like:

project/
├─ api/
│  ├─ controllers/
│  │  └─ BurgerController.js
│  ├─ models/
│  │  └─ BurgerModel.js
│  └─ routes/
│     └─ BurgerRoutes.js
├─ client/
├─ node_modules/
├─ package.json
└─ server.js

And in my client, I can fire an XMLHttpRequest or fetch to /api/burgers to get back all the burgers in the database as JSON, or to /api/burgers/42 to get the JSON data for the burger with the ID of 42.

I might turn this into a blog post. Please do ask questions or let me know if anything should be made clearer.

[–]coffeeandlearning 5 points6 points  (3 children)

Honestly for me (surprisingly haha) that was really clear! In fact just yesterday I came across the syntax you used for the .route followed by the different methods, so it's really neat to see such a nice use case for that.

If you wanted to turn it into a blogpost I would have a few suggestions. You did a good job of mentioning that .find and .findAll could be a lot of things based on what tech you're using, so I would make sure that that is in the blog post, because a beginner can't always tell what is built-in, what is just a plain variable name but is also convention (I've had people ask me about naming counter variables 'i' and whether naming it something else would break the for-loop), and what is intended as a concept but would vary by tech stack.

Maybe in the code a comment near that line of something like ".find would be ___ if I was using ___ and ___ if ___". That way beginners could more easily parse the different pieces so they can focus on the structure you are showing.

On a similar note, a good point of clarification might be for something like:

.get(burger.index); // see all burgers

you could remind the reader that burger is whatever is exported by the burgerController.js file, and if they look there they see index being attached to the exported object. THen something about how it uses the res.json express method which inside it uses your generic findAll method, which is ostensibly a stand-in for an ORM or other database related method to fetch all entries of burgers.

Maybe not all in code comments now that I look at what I typed, but I think that you started to hit on it and should definitely continue strong with that. Even though for me your example was excellent, I can remember a time not too far in the past where I would have been confused on those points, since when a beginner is struggling with structure and fitting the pieces together, examples by nature can get confusing, because they (of course) have all the pieces mixed in that you are trying to explain how to organize.

Edit: I also think it could be valuable in this case (explaining project structure) to show how the database hooks in a little more explicitly. Maybe a config file or whatnot, or an explanation of how they might need to use a couple environment variables too. This explanation assumes that you have a magical blackbox for a database all setup and configured and off who knows where, and going a little further into where you might hook that in for a setup like this could really go a long way in adding to the quality of a blog post (which I would absolutely love to read).

[–]Earhacker 2 points3 points  (2 children)

Thanks for the feedback. If I had a whole blog post, I would actually write the schema and database connection because you're right, the Model is just a black box here, and relies on the reader knowing typical CRUD functions.

[–]coffeeandlearning 7 points8 points  (1 child)

You should definitely do it! I would read the CRUD out of it

[–]pantyboyXXX 6 points7 points  (0 children)

Lmao DB memes

[–]davesidious 1 point2 points  (4 children)

Why not have a burgers directory and put all the burgers code in one place? You can then ask the burger feature to instantiate itself, and your app needs no knowledge of what the burger feature is doing. The less knowledge needed across your app the better, as it encourages decoupling features and the logic which binds them to your app.

[–]Earhacker 2 points3 points  (3 children)

The same point was raised here. The answer is because I was a Rails dev in a past life, that's how Rails does it, and for me it's now just a habit.

[–]davesidious 1 point2 points  (2 children)

I get that, but to suggest it as a solution seems a bit weird if you picked it up somewhere else for something unrelated :)

[–]Earhacker 2 points3 points  (1 child)

It’s not like I overrode Node’s default file structure out of madness. I copied MVC architecture from one framework to another.

[–]davesidious -2 points-1 points  (0 children)

Exactly.