Архитектура NodeJs MVC, это макаронный код? - PullRequest
1 голос
/ 08 мая 2019

Я младший разработчик NodeJS, в настоящее время работаю над платформой обмена криптовалютой.Вот структура папок проекта.

/app
    /controllers
        /user
        /order
        /settings
        ...
        index.js
    /middlewares
    /models
    /routes
        user.js
        order.js
    /services
        user.js
        order.js
        ...
    /views
    index.js
/config
/migrations
/public
/utils
server.js
.env
...

Поначалу это было немного ошеломляюще, но позже мне стало удобно перемещаться по приложению.
за исключением одного конкретного файла!index.js в каталоге контроллеров, вот как он настроен.

const { readdirSync, lstatSync } = require('fs');
const { validationSchema } = require('../../utils/validator');

module.exports = readdirSync('app/controllers')
  .filter(name => lstatSync(`app/controllers/${name}`).isDirectory())
  .reduce((controllersAccumulator, dir) => Object.assign(
    controllersAccumulator,
    {
      [`${dir}Controller`]: readdirSync(`app/controllers/${dir}`)
        .map(fileName => require(`./${dir}/${fileName}`))
        .reduce((accum, controllerFile) => Object.assign(
          accum,
          Object.keys(controllerFile).reduce(validationSchema.bind(null, dir, controllerFile), {}),
        ), {}),
    },
  ), {});

Должен признать, мне всегда было страшно, просто посмотреть на это!так, что он делает простыми словами, он сопоставляет запросы маршрутов с обработчиками в каталоге контроллеров.

например, если пользователь хочет сделать запрос на публикацию для регистрации новой учетной записи: путь маршрутабудет так:

// in the routes dir, user.js 
const { userCOntroller } = require('../controllers/');

router.post('/registration', userController.registration);


// in the /controllers, then /user, there will be a registration.js that includes:
const UserService = require('../../services/user');

exports.registration = async (req, res) => await UserService.create(req.body);


//then in the /services directory, user.js
...
class UserService {
  static create(body) { ... }
  ...
}

module.exports = UserService

так что я до сих пор не могу понять, как мы получили userController, который импортируется в пользовательские маршруты в последнем фрагменте?так вот что создал файл index.js в /controllers!
когда я спросил старших ребят в команде, они сказали: да, это трудно читать, но его кода меньше.хорошо, хорошо: \

Итак, что можно было сделать по-другому, чтобы сделать этот файл более читабельным, другими словами, есть ли способ его реорганизовать?заранее спасибо!

1 Ответ

1 голос
/ 08 мая 2019

Самый простой способ объяснить первый фрагмент кода - это переписать его и добавить соответствующие комментарии:

//Get all file names inside the controllers directory
const fileList = readdirSync('app/controllers');
//Get only directories from the file list
const onlyDirectories = fileList.filter(name => lstatSync(`app/controllers/${name}`).isDirectory());
//Create an empty object that will be exported from this module. Properties of this object will be assigned in the "for of" loop
const objectToExport = {};
//Import all files from the given directory and assign them to objectToExport
for (let directoryName of onlyDirectories){
    //First get all file names
    const controllerFiles = readdirSync(`app/controllers/${directoryName}`);
    //Then require each of these files
    const controllerModules = controllerFiles.map(fileName => require(`./${directoryName}/${fileName}`));
    //Assign the imported modules to `objectToExport`
    controllerModules.forEach((controllerModule) => {
        //Validate each module and assign it only if it passes validation
        if (validationSchema(directoryName, controllerModule)){
            objectToExport[`${directoryName}Controller`] = controllerModule;
        }
    });
}

module.exports = objectToExport;

Ниже я отвечу на ваши последующие вопросы из комментариев.Результирующий объект теперь выглядит следующим образом:

{
    userController: {
        registration: [Function],
        ...
    },
    orderController: {
        ...
    },
    ...
}

Функция регистрации оказалась в свойстве userController, поскольку она была экспортирована на registration.js, которая затем была импортирована оператором require в моем первом фрагменте кода.Чтобы использовать эту функцию непосредственно в других файлах, вы должны деструктурировать ее следующим образом:

const { userController: {registration} } = require('../controllers/');
//now you can use it like this:
router.post('/registration', registration);

Ваш последний вопрос о req.body.Как видите, функция принимает два параметра: req и res :

exports.registration = async (req, res) => await UserService.create(req.body);

Затем она передается вашему маршрутизатору в качестве промежуточного программного обеспечения.Я предполагаю, что вы используете Express.js в качестве основы.Если это так, то req и res автоматически передаются маршрутизатором в функцию registration.Вот как они могут использоваться UserService внутри этой функции.Свойство body создается Express автоматически, как описано здесь .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...