1

I am the team lead of a group of ~8 developers. We look after a large website which is split into many 'components' (a component could be a gallery for example - with libraries aside, these 'components' are standalone). We are in the process of splitting things up and part of that task is creating Gulp code to handle the various stages of processing for each of these components (SCSS processing, concatenation, image optimisation etc).

So, I need to come up with a pattern that the team can follow when creating Gulp code for a new 'component'. I need to keep this as simple as possible as many of the developers are new to Gulp. The general idea I want to get to is that we have a base Gulp 'component', which will have all code required to process a standard 'component', but I expect there will be some 'components' that need special gulp code. So, I would like to be able to extend the base Gulp 'component' compilation code in these cases.

In an attempt to learn and to set up a strong foundation for the team have been doing some reading on best approaches to inheritance in JavaScript. I have come across quite a rift in the way people feel about this. What approaches I have considered and what I've gathered:

  1. There are classes in ES6 which I can use in node.js. These classes are shunned by a lot of the big names in the JavaScript world as well as big names from the past (when using classical style languages) for reasons such as it encourages brittle code. Also, you cant do classic style public and private properties/functions, so I struggle to see any real reason why I should go with this.

    If I did go this route, I feel I would end up with something like this (code is untested / probably not correct, i'm just dumping my thoughts):

    class Component {
        constructor(options) {
    
        },
        build() {
    
        },
        dev() {
    
        }
        test() {
    
        },
    
        // Should be private, but wont be
        _processStyles() {
    
        },
        _processScripts() {
    
        }
    }
    
  2. Factory functions. We're used to using these with the revealing module pattern, and generally I like them. I also believe that Douglas Crockford is a fan of factory functions, so I feel I'm on good ground with this. Now, if I create public and private methods (by returning an object with references only to my public functions) and then I want to extend 'component', in the new factory I would create an instance of 'component' and then extend that. The problem is that I can't override (or even call) the private functions of my 'component' instance, because they are in a different scope that I have no access to. I did read that one way to get around this is to use an object to create a reference to all of the private methods, but then they're not private anymore, so it defeats the object (no pun intended).

    var component = function(options) {
    
        var init = function() {
    
        };
        var build = function() {
    
        };
        var dev = function() {
    
        };
        var test = function() {
    
        };
        var _processStyles = function() {
    
        };
        var _processScripts = function() {
    
        };
    
        return {
            init: init,
            build: build,
            dev: dev,
            test: test
        };
    };
    
    var specialComponent = function(options) {
        // Create instance of component
        var cmp = component(options);
    
        // Extend it
        cmp.extraFunction = function() {
            // This will throw an error as this function is not in scope
            _processStyles();  
        }
    
        // Private functions are available if I need them
        var _extraPrivateFunction = function() {
    
        }
    
        return cmp;
    }
    

So, I feel like I've missed something somewhere, like I need someone to point me in the right direction. Am I getting too hung up about private functions (feels like it)? Are there better approaches? How would something like this, which seems to lend itself to classical inheritance be best tackled in a DRY (don't repeat yourself) manner?

Thanks in advance, Alex.

MegaVolt
  • 11
  • 1
  • 2
    FWIW, child classes are not supposed to be able to access private members of their parent classes, so that doesn't seem to be an issue after all then. *"Am I getting too hung up about private functions (feels like it)?"* Yes. Instead of looking for complex patterns that might get you 99% where you are trying to get, accept what JavaScript offers and keep it simple. It will likely be easier to maintain, evolve and understand the code in the long run. Why do you think a simple naming convention wouldn't suffice? – Felix Kling Nov 09 '15 at 02:09
  • Have you tried a closure approach like this? http://stackoverflow.com/questions/8580540/javascript-calling-private-method-from-prototype-method – Tim Sheehan Nov 09 '15 at 02:14
  • 2
    You are horribly overthinking this. Go for plain old objects as configuration, and use a simple runner function that they are passed to. No "class" or anything. – Bergi Nov 09 '15 at 02:24
  • Idk why you wanna know about all this stuff for a gulp script...but anyways here's a book that I read and refer to constantly: http://addyosmani.com/resources/essentialjsdesignpatterns/book/ It covers all the fundamentals of JavaScript design patterns with code examples. – Shashank Nov 09 '15 at 02:27
  • 1
    Treating JavaScript like C++ is a bad idea as you are gonna end up with a code base that no self-respecting JS developer is going to be willing to touch. Treat JavaScript like what it is (Functions, Prototypes and Objects) and you'll benefit from the productivity. – Schahriar SaffarShargh Nov 09 '15 at 03:52
  • @Felix Kling, You are correct, id missed that entirely. I wish I hadn't, I think I wouldn't have asked this question if Id have had that piece of info. Keeping it simple is the way forward. The naming convention will probably serve me well (and I do plan to use one), so thats a good tip, thanks! – MegaVolt Nov 10 '15 at 22:10
  • @Dontfeedthecode - thanks, but I think that leaves me in the same situation. – MegaVolt Nov 10 '15 at 22:10
  • @Bergi - Too many assumptions here for my liking. The build script is going to be quite complicated, as we have multiple repos, many different libraries and compilation rules (we have a lot of legacy code to cater for unfortunately) and a lot of other functionality to add that I didn't feel the need to list. Also, I don't like to assume developers wont shoot themselves in the foot as I've been burnt by that in the past. You're right about keeping things simple, thank you for that. – MegaVolt Nov 10 '15 at 22:13
  • @SchahriarSaffarShargh - Thanks, I wasn't intending to use classes due to all of the backlash i've read about, but thought id add it for discussion. Its easy to get too excited about new functionality it seems. You're obviously on the 'against' panel, which I think I am too. Thanks for your response. – MegaVolt Nov 10 '15 at 22:19
  • @Shashank - Brilliant, thank you! I will definitely be reading through this. – MegaVolt Nov 10 '15 at 22:20

0 Answers0