Shaun Xu

The Sheep-Pen of the Shaun


News

logo

Shaun, the author of this blog is a semi-geek, clumsy developer, passionate speaker and incapable architect with about 10 years’ experience in .NET and JavaScript. He hopes to prove that software development is art rather than manufacturing. He's into cloud computing platform and technologies (Windows Azure, Amazon and Aliyun) and right now, Shaun is being attracted by JavaScript (Angular.js and Node.js) and he likes it.

Shaun is working at Worktile Inc. as the chief architect for overall design and develop worktile, a web-based collaboration and task management tool, and lesschat, a real-time communication aggregation tool.

MVP

My Stats

  • Posts - 122
  • Comments - 549
  • Trackbacks - 0

Tag Cloud


Recent Comments


Recent Posts


Archives


Post Categories


Image Galleries


.NET



Features always grows much faster than we expect. When I am build Worktile Pro I created a JavaScript file contains all business logic in class for the task module. But after several months development it became over 7000 lines of code, which is horrible. Last week I decided to split it into multiple files.

It may not be a big problem to split one JavaScript file into multiple, especially in Node.js environment. We can put functions and variables into many files as we wanted and "require" them in the "main" file. But if we want to split a class definition into multiple files that might not work. In JavaScript a class is a function in essential, and it can be defined only in one file. For example, in the code below I defined a class named "MissionService" with some method in file "mission.js".

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
(function () {
    'use strict';

    var MissionService = function ()  {
    };

    MissionService.prototype.createTask = function (taskName) {
        console.log('Task: "' + taskName + '" was created.');
    };

    MissionService.prototype.loadTask = function (taskId) {
        console.log('Task (' + taskId + ') was loaded.');
    };

    MissionService.prototype.updateTask = function (taskId, taskName) {
        console.log('Task (' + taskId + ') was changed to "' + taskName + '".');
    };

    MissionService.prototype.removeTask = function (taskId) {
        console.log('Task (' + taskId + ') was removed.');
    };

    MissionService.prototype.restoreTask = function (taskId) {
        console.log('Task (' + taskId + ') was restoreTask.');
    };

    exports = module.exports = MissionService;

})();

 

First step is to move the class definition into an "index" file, which will "require" all following files later. As you can see this "index.js" file only contains the class definition and exports it.

1
2
3
4
5
6
7
8
9
(function () {
    'use strict';

    var MissionService = function ()  {
    };

    exports = module.exports = MissionService;

})();

 

Now we can create a "partial" class definition file based on the "index" I created. Just exports a function which allow the class can be passed so that I can define its methods through "PartialClass.prototype".

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
// mission.create.js
(function () {
    'use strict';

    exports = module.exports = function (MissionService) {

        MissionService.prototype.createTask = function (taskName) {
            console.log('Task: "' + taskName + '" was created.');
        };

    };
})();

// mission.update.js
(function () {
    'use strict';

    exports = module.exports = function (MissionService) {

        MissionService.prototype.updateTask = function (taskId, taskName) {
            console.log('Task (' + taskId + ') was changed to "' + taskName + '".');
        };

        MissionService.prototype.removeTask = function (taskId) {
            console.log('Task (' + taskId + ') was removed.');
        };

        MissionService.prototype.restoreTask = function (taskId) {
            console.log('Task (' + taskId + ') was restoreTask.');
        };

    };
})();

// mission.find.js
(function () {
    'use strict';

    exports = module.exports = function (MissionService) {

        MissionService.prototype.loadTask = function (taskId) {
            console.log('Task (' + taskId + ') was loaded.');
        };

    };
})();

 

Now back to the "index" file, what we need to do is to "require" this partial class file, put the class we defined into the parameter so that it will attach methods.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
(function () {
    'use strict';

    var MissionService = function ()  {
    };

    require('./mission.create.js')(MissionService);
    require('./mission.update.js')(MissionService);
    require('./mission.find.js')(MissionService);

    exports = module.exports = MissionService;

})();

 

Finally when we want to use this class, just "require" the "index" file and "new" an instance as below.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
(function () {
    'use strict';

    var MissionService = require('./index.js');
    var mission = new MissionService();

    mission.createTask('Shaun\'s task.');
    mission.loadTask(1);
    mission.updateTask(1, 'Shaun\'s new task.');
    mission.removeTask(1);
    mission.updateTask(1);

})();

 

Screen Shot 2016-03-07 at 10.34.23

If we have some internal helper functions or variants we can put them into some "shared" files. 

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
(function () {
    'use strict';

    exports = module.exports = function (MissionService) {

        MissionService.prototype._log = function (message) {
            console.log(message);
        };

    };
})();

 

Just ensure we "require" them before we "require" PartialClass files that are using them.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
// index.js
(function () {
    'use strict';

    var MissionService = function ()  {
    };

    require('./mission.shared.js')(MissionService);

    require('./mission.create.js')(MissionService);
    require('./mission.update.js')(MissionService);
    require('./mission.find.js')(MissionService);

    exports = module.exports = MissionService;

})();

// mission.create.js
(function () {
    'use strict';

    exports = module.exports = function (MissionService) {

        MissionService.prototype.createTask = function (taskName) {
            this._log('Task: "' + taskName + '" was created.');
        };

    };
})();

// mission.update.js
(function () {
    'use strict';

    exports = module.exports = function (MissionService) {

        MissionService.prototype.updateTask = function (taskId, taskName) {
            this._log('Task (' + taskId + ') was changed to "' + taskName + '".');
        };

        MissionService.prototype.removeTask = function (taskId) {
            this._log('Task (' + taskId + ') was removed.');
        };

        MissionService.prototype.restoreTask = function (taskId) {
            this._log('Task (' + taskId + ') was restoreTask.');
        };

    };
})();

// mission.find.js
(function () {
    'use strict';

    exports = module.exports = function (MissionService) {

        MissionService.prototype.loadTask = function (taskId) {
            this._log('Task (' + taskId + ') was loaded.');
        };

    };
})();

 

At the end, we can put all files into a folder and rename the "index" as "index.js". Now we could require our class by the folder name, which is more friendly.
Screen Shot 2016-03-07 at 10.40.50

 

Hope this helps,

Shaun

All documents and related graphics, codes are provided "AS IS" without warranty of any kind.
Copyright © Shaun Xu. This work is licensed under the Creative Commons License.

Comments

Gravatar # Centrifugal Pump Manufacturers, Centrifugal Pump Distributors, Traders Dencil Pumps
Posted by Dencil Pumps on 3/7/2016 3:28 PM
centrifugal pump mumbai, dosing pump, agitator, centrifugal pump manufacturers, centrifugal pump distributors, centrifugal pump india
Post A Comment
Title:
Name:
Email:
Comment:
Verification: