2
\$\begingroup\$

Overview

I am attempting to learn Node JS with Express by creating a project.

I have seen many examples of setting up an express.js application with functional based programming, like so:

// app.js

"use strict";

const express = require("express");
const path = require("path");
const mongoose = require("mongoose");
const router = require("./routes/index");
const config = require("../config/config");
const app = express();

// Connect to the database.
let dbUser = encodeURIComponent(config.db.username);
let dbPass = encodeURIComponent(config.db.password);
let dbDatabase = encodeURIComponent(config.db.database);
let mongoUri = `mongodb://${dbUser}:${dbPass}@${config.db.host}:${config.db.port}/${dbDatabase}`;
mongoose.connect(mongoUri, { useNewUrlParser: true });

app.use(router); // Use the router location.

// Set up the views.
app.set("views", path.join(__dirname, "views"));
app.set("view engine", "ejs");
app.use(express.static(path.join(__dirname, "public"))); // Set the static file location.

app.listen(config.server.port); // Start the application on specified port.

Code

Below is the OOP code I have implemented to initialize the express application. The entire project can be found here: https://github.com/youkergav/MagicConchShellBot

Please note: While many techniques used in this project are overkill, the overall objective was to better learn Node JS. For all of my questions, please take them as if this were a large scale project, rather than the actual project size.

App File

// app.js

"use strict";

const express = require("express");
const Server = require("./lib/server");

let server = new Server;

server.initDb(); // Connect to the database.
server.initRoutes(); // Use the router location.
server.initViews(); // Set up the server views.

server.run();

Sever File

// lib/server.js

"use strict";

class Server {
    constructor(express) {
        this.express = express;
        this.app = this.express();
        this.config = require("../../config/config");
    }

    initDb() {
        const Database = require("./database");
        let database = new Database();

        database.connect();
    }

    initRoutes() {
        const Route = require("./route");
        const route = new Route(this.app);

        route.setRoute("../routes/general");

        return true;
    }

    initViews() {
        const View = require("./view");
        const view = new View(this.express, this.app);

        view.setViewsLocation("../views");
        view.setViewEngine("ejs");
        view.setStaticLocation("../public");

        return true;
    }

    run() {
        this.app.listen(this.config.server.port);
    }
}

module.exports = Server;

Database File

// lib/database.js

"use strict";

class Database {
    constructor() {
        this.mongoose = require("mongoose");
        this.config = require("../../config/config");
    }

    connect() {
        let dbUser = encodeURIComponent(this.config.db.username);
        let dbPass = encodeURIComponent(this.config.db.password);
        let dbHost = this.config.db.host;
        let dbPort = this.config.db.port;
        let dbDatabase = encodeURIComponent(this.config.db.database);

        let mongoUri = `mongodb://${dbUser}:${dbPass}@${dbHost}:${dbPort}/${dbDatabase}`;
        this.mongoose.connect(mongoUri, { useNewUrlParser: true }, function(error) {
            if(error) {
                console.error(error);
                return false;
            }

            return true;
        });
    }

    disconnect() {
        this.mongoose.connection.close(function(error) {
            if(error) {
                console.error(error);
                return false;
            }

            return true;
        });
    }
}

module.exports = Database;

Route File

// lib/route.js

"use strict";

class Routes {
    constructor(app) {
        this.app = app;
    }

    setRoute(location) {
        let route = require(location);

        this.app.use(route);

        return true;
    }
}

module.exports = Routes;

View File

// lib/view.js

"use strict";

class Views {
    constructor(express, app) {
        this.express = express;
        this.app = app;
        this.path = require("path");
    }

    setViewsLocation(location) {
        let fullLocation = this.path.join(__dirname, location);

        this.app.set("views", fullLocation);

        return true;
    }

    setViewEngine(engine) {
        this.app.set("view engine", engine);

        return true;
    }

    setStaticLocation(location) {
        let fullLocation = this.path.join(__dirname, location);
        let staticLocation = this.express.static(fullLocation);

        this.app.use(staticLocation);

        return true;
    }
}

module.exports = Views;

Questions

I am uncertain if I should be using OOP here. Here are my thoughts and questions...

Pros:

  • Scalable application: What are some common JS scalability issues? Is this an adequate solution?
  • Cleaner code: Does this implementation of OOP offer a more obvious way on how the code should function?
  • Ability to implement JSDocs
  • Ability to perform unit tests

Cons:

  • JavaScript is a functional based language: What advantages does a functional implementation have to offer?
  • Added a layer of complexity: In your opinion, is this code better abstracted, or did I just make it harder to understand?
  • I have not found any online examples of initializing express applications with OOP. Are there disadvantages to using OOP that I am missing?
\$\endgroup\$
9
  • \$\begingroup\$ Welcome to Code Review! The current question title, which states your concerns about the code, is too general to be useful here. Please edit to the site standard, which is for the title to simply state the task accomplished by the code. Please see How to get the best value out of Code Review: Asking Questions for guidance on writing good question titles. \$\endgroup\$ Commented Jul 9, 2019 at 7:43
  • \$\begingroup\$ @TobySpeight I have updated the title. Though, I am struggling to make a good title. \$\endgroup\$ Commented Jul 9, 2019 at 12:28
  • \$\begingroup\$ A good title says something about the purpose of the code - what it does for its users. "Node JS + Express App" only tells us about how/where it runs, not about what it's intended to do; the same is true for "Implementing OOP". What problem does the code solve for the user? \$\endgroup\$ Commented Jul 9, 2019 at 13:26
  • \$\begingroup\$ @TobySpeight By user I'm assuming you mean whoever is looking at the question on this site, and not the user of this specific application. I did not post anything relevant to what the application is doing because my problem can be applied to many applications, not a single application. I guess my actual question would be: Should I be using OOP like this in a node application? Am I over complicating the logic? Or: Am I using OOP in a correct fasion? Why is no one else implement OOP in node like this? Sorry, I don't know how to word this question any better. Am I am the right place here? \$\endgroup\$ Commented Jul 9, 2019 at 16:13
  • \$\begingroup\$ No, I meant the person using the program or library. If we have no information about the real-world purpose of the program, the question is likely to be closed as having "insufficient context" - it appears to be stub or example code rather than a real project. Your specific questions are good ones, and I'd like to see them get answered (that's why I'm trying to help improve it and avoid closure); to achieve that, you need to help reviewers with the context of the code. BTW, sorry my Javascript is too poor to review it myself! \$\endgroup\$ Commented Jul 9, 2019 at 16:24

0

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.