.NET Fest: полная программа конференции на сайте. Присоединяйся к самому большому .NET ивенту
×Закрыть

Повторяющиеся require в Node JS, нормально ли это?

Здравствуйте. На досуге изучаю Node JS и Express, сгенерировал каркас приложения expressjs.com/...​ru/starter/generator.html и вижу, что в нем дважды в разных файлах есть такая строка:

var express = require('express');

Погуглив я узнал, что повторяющиеся require’ы — это нормально, так как модули кешируются, НО по мере роста приложения, не замахаешься ли копипастить кучу реквайров? Можно ли их всех выносить в отдельный файл и вообще, где можно посмотреть лучшие практики организации NodeJS-проекта?

LinkedIn
Допустимые теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Допустимые теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

Вообще для базы в express имеет смысл написать middleware, которое будет создавать соединение с базой и добавлять его к req. Пример для koa, в express похоже будет github.com/...​ddleware/db-middleware.js

Вот это похоже и есть решение (подозреваю). Dependency Injection конечно тоже рассмотрю

Нет, их нельзя выносить. И как раз это лучшая практика.

Це про код що виконує якусь функцію яка використовується в декількох місцях, а не про базові конструкції мови і фреймворку. В іншому випадку можна і «if» заборонити використовувати більше одного разу) У всьому має бути міра.

«if» заборонити

если то, иначе — всё

В вікі якось мутно описаний термін DRY. Рекомендую цей сайт:

deviq.com/don-t-repeat-yourself

Там і є інші принципи, і патерни і ще щось. Хоча сайт більше під класичне ООП, що там за особливий шлях в джс я не дуже в курсі. Але принципи вони загальні.

Вчити по вікі лише заплутає вас. І так заплутаєтесь. Тут потрібно на практиці закріпляти теорію, і змінювати свої підходи разом з ростом розуміння теорії. Прочитав і одразу почав правильно розуміти і застосовувати теорію не вийде.

DRY не распространяется на импорты

Это и есть «don’t repeat». Вы не повторяете СВОЙ код, вы ссылаетесь на чужой. И чем прямее вы это делаете — тем проще в вашем коде разобраться.

Кстати, с точки зрения поведенческой психологии, удобочитаемым будет код с повторением, притом 9:1 в пользу повторений. Правда в этой цифре учитывается всё, включая язык, стилистику, именование, и т.п., но сам факт — код должен быть предсказуемым для читателя. Никто не будет читать ВЕСЬ код, и тем более весь его помнить. Даже ты.

Як тільки логіка продублювалася — починається відлік до наростання багів. Просто копіпастити? — так. Але це тієї ж категорії простота що і загальний кодинг з запашком. На перших порах буде працювати, недовго.

А це не логіка. Це ЗАЛЕЖНІСТЬ. І що б там не змінювалося в інших схожих ділянках, в тебе не має виникати потреби відслідковувати зміни по всіх залежностях. Навпаки: там де треба залежності змінити, ти зміниш, а все інше МАЄ ПРАЦЮВАТИ. Аж до того, що ти робиш залежність на конкретну версію, або декілька версій власного коду з іншими залежностями — наприклад для різних операційних систем.

В жс, в модуль, принято передавать только то что нужно. Потом замахаешся удалять мусор при модификиции кода, это не пхп ведь.

Потом замахаешся удалять мусор

sudo rm -rf /

Ну да, всё что есть в общем файле — это всё нужно. Если в каком-то модуле будет не всё нужно из общего файла, то этот файл сократиться, а другие модули дополнятся еще одной строчкой require

Будете переписувати файли?

The Open-Closed Principle (OCP) states that software entities (classes, modules, methods, etc.) should be open for extension, but closed for modification.

Не закладайте заздалегідь те, що прийдеться виправляти.

Придется переписывать, но это маловероятно, потому что это уже смена архитектуры приложения, а такое бывает только при резкой смене ТЗ. Ну вот хотя бы эти строки кода:

var mongoose = require('mongoose'); /
var config = require('../config');
mongoose.connect('mongodb://'+config.get('dbuser')+':'+config.get('dbpass')+'@'+config.get('dbhost')+':'+config.get('dbport')+'/'+config.get('db'), 
	{ useNewUrlParser: true });
почему нельзя вынести в отдельный файл? Автоимпорт же не вставит вам mongoose.connect...

Жесть)) Підключати базу руками в кожному файлі. Нагадує старий дофреймворковий пхп. Хз, хз, я вже звик до депенденсі інджекшинів і за мене все фреймворк збирає. Тут потрібен ноджс досвідчений дев.

Зависит от фреймворка, используемых библиотек и нужд приложения. Вообще можно конечно инициализировать соединение в одном месте

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

Я відмінне і не писав. Перечитайте ще раз.

Придется переписывать, но это маловероятно, потому что это уже смена архитектуры приложения, а такое бывает только при резкой смене ТЗ

Такое бывает каждый день. В хорошем случае — раз в неделю. Никто вам в 2019 не даст ТЗ, высеченное в камне и которое 100% никогда не поменяется.

Касаемо вашего вопроса — вынести соединение с базой можно, если нужно одно соединение везде

Окей, допустим вы использовали needle в своих модулях, вы этого не знаете, в скольких модулях и зачем он использовался, но допустим он используется в трех модулях. Один из модулей вы удаляете за ненадобностью, в этот момент вы не знаете есть ли он в других модулях. Почему не знаете? вы могли забыть о нем давно или этот код и вовсе писали не вы, по идее сейчас вам надо просмотреть все файлы проекта на предмет того встречается ли там этот модуль, причем включая ситуации где его подключение может быть неявным, это бывает редко, но вы не можете этого исключать и если вы будете работать в команде, то явно найдутся люди что и вовсе будут на это забивать.

Теперь представим что вы подключили все это в одном файле, первом.
— во первых удаленный модуль будет висеть в памяти, что плохо во всех отношениях,
— во вторых гит, чтобы добавить модуль вы будете модифицировать один файл с другими людьми что равно перманентным гит конфликтам
— в третьих название модулей, перед тем как завести любую переменную, вам будет придется проверять не занято ли это имя где-то, а это запросто, например библиотека request. Сделать такой вариант рационально только глобальными переменными, если сделать иначе, то количество букв что вы набираете при require будет примерно тем же что и при любом другом способе кроме глобальных переменных.

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

А как ты без рекваера будешь к переменным обращаться? Всё в глобал писать? Или в объект и его всегда рекваерить? Зачем?

Или в объект и его всегда рекваерить? Зачем?

Да, общее — в объект, чтоб писать один require в каждом файле. Это же проще (ИМХО), DRY principle типа. Ну и там же не только require’ы будут, подключение к БД например тоже и другие одинаковые куски кода. ХЗ, может я не прав, тогда скажите как правильно

Правильно — разбивать программу на маленькие куски и require только то, что нужно в данном куске программы. Кусок — логически завершення единица.

Dependency injection можешь использовать, если стандартный подход не нравится

НО по мере роста приложения, не замахаешься ли копипастить кучу реквайров?

Webstorm и редакторы с плагинами импортируют сами. Если вам нужна куча реквайров в каждом файле, может у вас шото не так с приложением?

Можно ли их всех выносить в отдельный файл

Нафига?

где можно посмотреть лучшие практики организации NodeJS-проекта?

В этом плане лучшая практика — таки тащить только нужные модули.

чому ви не любите автоімпорт?

не замахаешься ли копипастить кучу реквайров?

Не замахаешься ли копипастить кучу #include в C?

Не замахаешься ли копипастить кучу import в Java или Python?

Не замахаешься ли копипастить кучу using в C#?

Почему-то обычно не замахиваются. Наверно, в модульности и включению только нужного есть польза, чи нет?

Не замахаешься ли копипастить кучу #include в C?
Не замахаешься ли копипастить кучу import в Java или Python?
Не замахаешься ли копипастить кучу using в C#?

Хз, я этих языков не знаю, но по-идее должен быть какой-то способ вынести одинаковое отдельно и потом только подключать его. Вот у меня в двух файлах в проекте Node JS были одинаковые куски кода, которые я вынес в файл bootstrap.js:

var express = require('express');
var router = express.Router();
var jwt = require('jsonwebtoken');
var mongoose = require('mongoose');
var bodyParser = require('body-parser');
var config = require('../config');
var userSchema = require('../models/users');

mongoose.connect('mongodb://'+config.get('dbuser')+':'+config.get('dbpass')+'@'+config.get('dbhost')+':'+config.get('dbport')+'/'+config.get('db'), 
	{ useNewUrlParser: true });

router.use(bodyParser.urlencoded({ extended: false }));
router.use(bodyParser.json());

module.exports = {
	router: router,
	jwt: jwt,
	mongoose: mongoose,
	config: config,
	userSchema: userSchema
};

МОЖНО ЛИ так делать в NodeJS ?

Да это разве куча? Развёл тут песни лебединые. Ты в Java энтерпрайз-приложения не видел, особенно где разные внутрикорпоративные огрызки кода за один нэймспейс воюют, а то и вовсе без такового объявлены. А уж если бы ты видел что творят Java-приложения с горячей перезагрузкой классов и вовсе бы прослезился.

Короче, не жадничай. Хотя это давно считается неправильным, но говномэнеджеры иначе не умеют: ценят тебя тем больше, чем больше кода ты пишешь. Так что не будь букой, и докинь побольше явных импортов и прочей бюрократии, благо концентрации смысла в коде оно не мешает, и лапками писать не надо, всё за тебя IDE делает.

тебе нужен Dependency Injection

А разве using и require это не разные вещи? Потому как ты либу же поключил и она по любому грузится, хоть пишешь ты это using или не пишешь, это просто упрощение, чтобы не писать название сборки и пространства имен перед классом, а вот если require не вызвать то этот модуль вроде как и не загрузится вовсе.

ну в контексте того, что спрашивает автор, это неважно

Тру! Проблема заключається в відсутності неймспейсів, що коли щось треба то треба тягти весь файл. В пхп було до появи неймспейсів те саме з require. От загуглив і була навіть проблема що коли двічі пишеш require то файл грузиться 2 раза. Тобто using і require це взагалі різні штуки, одне працює з фізичними файлами а інше з абстракцією(боже храни неймспейси).

Але не в цьому суть. Суть в тому що лінуватися підгрузити необхідні модулі і пихати все в один файл це макакокодинг. Може десь воно і має сенс, в рідких випадках, ну як є темплейт енжіни з автоматичним інжектом штук в всі файли що привязуються до лайоту. Але загалом це погано. Істина гласить — кожному модулю по потребностям.

И еще, какие сейчас стандарты-де-факто для Node JS?

лучшая практика в жабоскриптизме — все приложение в одном файле.
не слушай тех, кто говорит промодульность
один файл всегда проще удалять

Также искать легко в одном файле. И ненадо навигировать по сотням файлов чтоб понять что от чего зависит.

щас тебя жуны послушаются и потом «прощай целое поколение программистов»

вы что не слышали? новый модный подход у формошлепов: SFA — Single File Application

один файл всегда проще удалять

Распространять тоже проще. Т.н. «amalgamation» для небольших исходников (до лимона строк кода) — пока никто не отменял.

да, и зип компрессия на большом файле лучше работает

Подписаться на комментарии