This is a documentation for Board Game Arena: play board games online !

User:SwHawk/Create Modular Code: Difference between revisions

From Board Game Arena
Jump to navigation Jump to search
No edit summary
No edit summary
Line 8: Line 8:


=== <code>include</code> vs <code>require</code> ===
=== <code>include</code> vs <code>require</code> ===
Throughout this section, I'll make heavy use of PHP's <code>require_once</code> control structure. Why am I using <code>require(_once)</code> instead of <code>include_once</code>? Because if an error exists in a PHP file that you try to <code>include</code>, only a warning will be thrown, but the script will continue in spite of the error. Using <code>require</code> if the included file has an error, the script dies when the inclusion takes places, throwing a fatal error (E_COMPILE_ERROR).
Throughout this section, I'll make heavy use of PHP's <code>require_once</code> control structure. Why am I using <code>require(_once)</code> instead of <code>include_once</code>? Because if an error exists in a PHP file that you try to <code>include</code>, only a warning will be thrown, but the script will continue in spite of the error. Using <code>require</code> if the included file has an error, the script dies when the inclusion takes places, throwing a fatal error (<code>E_COMPILE_ERROR</code>).


That way, I'm sure the classes, traits or interfaces I'm including are syntax error free.
That way, I'm sure the classes, traits or interfaces I'm including are syntax error free.


=== Game logic methods ===
=== Game logic methods ===
The way the framework is implemented, your game logic is gathered inside a class (`YourProjectName`) extending the [[Table|`Table` class]]. You define your methods there so that they may be called from other parts of the framework (as long as they're public methods obviously).
The way the framework is implemented, your game logic is gathered inside a class (<code>YourProjectName</code>) extending the [[Table|<code>Table</code> class]]. You define your methods there so that they may be called from other parts of the framework (as long as they're public methods obviously).


But you can take advantage of [https://www.php.net/manual/en/language.oop5.traits.php PHP Traits]. In a nutshell, Traits are a collection of methods that can be reused in different classes, to avoid code duplication. Here we're not going to reuse them anywhere else than in the game class, but this little trick allows us to put methods definitions in other files, and in so doing to avoid monolithic code.
But you can take advantage of [https://www.php.net/manual/en/language.oop5.traits.php PHP Traits]. In a nutshell, Traits are a collection of methods that can be reused in different classes, to avoid code duplication. Here we're not going to reuse them anywhere else than in the game class, but this little trick allows us to put methods definitions in other files, and in so doing to avoid monolithic code.
Line 33: Line 33:
</pre>
</pre>


Then you can include it in you project's `game.php` file like so:
Then you can include it in you project's <code>X.game.php</code> file like so:
<pre><nowiki>[[X_game.php]]</nowiki>
<pre><nowiki>[[X_game.php]]</nowiki>
<?php
<?php
Line 39: Line 39:
   *------
   *------
   * BGA framework: © Gregory Isabelli <gisabelli@boardgamearena.com> & Emmanuel Colin <ecolin@boardgamearena.com>
   * BGA framework: © Gregory Isabelli <gisabelli@boardgamearena.com> & Emmanuel Colin <ecolin@boardgamearena.com>
   * ProgressEvolutionTechnologySwH implementation : © <Your name here> <Your email address here>
   * X implementation : © <Your name here> <Your email address here>
   *  
   *  
   * This code has been produced on the BGA studio platform for use on http://boardgamearena.com.
   * This code has been produced on the BGA studio platform for use on http://boardgamearena.com.
Line 45: Line 45:
   * -----
   * -----
   *  
   *  
   * progressevolutiontechnologyswh.game.php
   * X.game.php
   *
   *
   * This is the main file for your game logic.
   * This is the main file for your game logic.
Line 99: Line 99:


==== Autoloader function for development ====
==== Autoloader function for development ====
While your project is under development, you usually create, move and remove classes as part of the development process. So you usually need an autoloading function that can handle a lot of flexibility. Basically once you import a class using the <code>use</code>, the autoloading function will determine which file to <code>require</code> using its fully qualified class name, and then <code>require</code>. Such a function would have the following code (borrowed and adapted from [https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-4-autoloader-examples.md]):
While your project is under development, you usually create, move and remove classes as part of the development process. So you usually need an autoloading function that can handle a lot of flexibility. Basically once you import a class using the <code>use</code> keyword, the autoloading function will determine which file to <code>require</code> using its fully qualified class name, and then <code>require</code>. Such a function would have the following code (borrowed and adapted from [https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-4-autoloader-examples.md this repository]):


<pre>
<pre>
spl_autoload_register(function ($class) {
spl_autoload_register(function ($class) {


     // project-specific namespace prefix, adapt to your needs
     // project-specific namespace prefix, adapt to your needs, remember that you must escape \ characters in double-quoted strings (hence the \\)
     $prefix = 'SwHawk\\X\\';
     $prefix = 'SwHawk\\X\\';


Line 148: Line 148:
</pre>
</pre>


This autoloader is better suited to production since it won't use expensive calls like <code>file_exists($filename)</code>.
This autoloader is better suited to production since it won't use expensive calls like <code>file_exists($filename)</code>. You can write the classmap by yourself, but it can be quite cumbersome, there is some tools like [https://github.com/hanneskod/classtools this project], or [https://github.com/gnugat/nomo-spaco this one], or even scripts detailed in this [https://stackoverflow.com/questions/22761554/how-to-get-all-class-names-inside-a-particular-namespace StackOverflow topic]


== On the JS side ==
== On the JS side ==


BGA uses the dojo toolkit framework for most of its javascript code. Dojo comes with its own way of loading modules, which you can read about in more detail [https://dojotoolkit.org/documentation/tutorials/1.10/modules/ here] and [https://dojotoolkit.org/documentation/tutorials/1.10/modules_advanced/ here]. To put it simply, there are two ways you can go about this
=== Write plain javascript ===
Should you wan to write plain javascript, you can easily do so. What you need to do is actually load the file like so in <code>X.js</code>:
<pre>
<nowiki>[[X.js]]</nowiki>
/**
*------
* BGA framework: © Gregory Isabelli <gisabelli@boardgamearena.com> & Emmanuel Colin <ecolin@boardgamearena.com>
* X implementation : © <Your name here> <Your email address here>
*
* This code has been produced on the BGA studio platform for use on http://boardgamearena.com.
* See http://en.boardgamearena.com/#!doc/Studio for more information.
* -----
*
* X.js
*
* X user interface script
*
* In this file, you are describing the logic of your user interface, in Javascript language.
*
*/
define([
    "dojo","dojo/_base/declare",
    "ebg/core/gamegui",
    "ebg/counter",
    "./modules/path/to/firstfile.js",        //The first file with your JS code
    "./modules/path/to/secondfile.js",      //The second file with another part of your JS code
    ...
],
function (dojo, declare) {
    return declare("bgagame.X", ebg.core.gamegui, {
        constructor: function(){
            ...
        }
</pre>
According to the dojo toolkit documentation, you will then need to directly access what you defined in the files.
=== Write an AMD module ===
You can take advantage of the toolkit's module system to declare dependencies between the differents files you'll be writing (modules in the toolkit's language). To be identified as modules, your Javascript files will need to have the following structure:
==== Create a named new class ====
<pre>
<nowiki>[[modules/js/FirstModule.js]]</nowiki>
define([
    "dojo",
    "dojo/_base/declare",
    other dependencies...
],function(dojo, declare){
    return declare("className", /*Parent classes that this class inherits, optional*/, {
        /* static properties */
        let property1 = "value;
        let property2 = 5;
        constructor: function (args) {
            /* instance properties */
            let property3 = 8;
            let property4 = [ "arrayValue", "arrayValue2" ];
        }
        method1: function (args) {
            /* your code here */
        }
        ...
    });
});
</pre>
Then in the X.js file, you can use your newly created module like so:
<pre>
<nowiki>[[X.js]]</nowiki>
/**
*------
* BGA framework: © Gregory Isabelli <gisabelli@boardgamearena.com> & Emmanuel Colin <ecolin@boardgamearena.com>
* X implementation : © <Your name here> <Your email address here>
*
* This code has been produced on the BGA studio platform for use on http://boardgamearena.com.
* See http://en.boardgamearena.com/#!doc/Studio for more information.
* -----
*
* X.js
*
* X user interface script
*
* In this file, you are describing the logic of your user interface, in Javascript language.
*
*/
define([
    "dojo","dojo/_base/declare",
    "ebg/core/gamegui",
    "ebg/counter",
    "./modules/js/Firstmodule",
],
function (dojo, declare) {
    return declare("bgagame.X", ebg.core.gamegui, {
    ...
    }
}
</pre>
In your code, you can access your module's class and methods by doing so:
<pre>
    let object = new className();
    object.method1();
    ...
</pre>
This can lead to namespace collisions if you don't choose a namespace correctly, so you might want to take the same approach as described earlier for the PHP files for using a namespace.
==== Create an anonymous class ====
This is the recommended way according to the dojo toolkit documentation, but it requires a bit more modification than the previous method:
<pre>
<nowiki>[[modules/js/SecondModule.js]]</nowiki>
define([
    "dojo",
    "dojo/_base/declare",
    other dependencies...
],function(dojo, declare){
    return declare(null, /*Parent classes that this class inherits, optional*/, {
        /* static properties */
        let property1 = "value;
        let property2 = 5;
        constructor: function (args) {
            /* instance properties */
            let property3 = 8;
            let property4 = [ "arrayValue", "arrayValue2" ];
        }
        method1: function (args) {
            /* your code here */
        }
        ...
    });
});
</pre>
Then in the X.js file, you can use your newly created module like so:
<pre>
<nowiki>[[X.js]]</nowiki>
/**
*------
* BGA framework: © Gregory Isabelli <gisabelli@boardgamearena.com> & Emmanuel Colin <ecolin@boardgamearena.com>
* X implementation : © <Your name here> <Your email address here>
*
* This code has been produced on the BGA studio platform for use on http://boardgamearena.com.
* See http://en.boardgamearena.com/#!doc/Studio for more information.
* -----
*
* X.js
*
* X user interface script
*
* In this file, you are describing the logic of your user interface, in Javascript language.
*
*/
define([
    "dojo","dojo/_base/declare",
    "./modules/js/SecondModule",        //Has to be inserted in the third position as we'll need an identifier later, and the other modules don't need it, see code in the preceding subsection.
    "ebg/core/gamegui",
    "ebg/counter",
    "./modules/js/Firstmodule",
],
function (dojo, declare, SecondModule /* insert a reference here that you'll use throughout the JS file for this module */) {
    return declare("bgagame.X", ebg.core.gamegui, {
    ...
    }
}
</pre>
In your code, you can then access your module's class and methods by doing so:
<pre>
    let someValue = SecondModule.property3
    SecondModule.method1();
    ...
</pre>
==== Create a singleton object ====
You can also create singleton objects by creating a module this way:
<pre>
[[modules/js/singletonObject.js]]
define([
    "dojo",
    ...
], function (dojo) {
    // Methods and variables defined in this part will not be available anywhere else than in this file
    let privateVariable = "someValue";
    let privateFunction = function (args) {
        //some code here
    }
    return {
        firstMethod: function (args) {
            privateFunction(args);
            //some other code here
        }
    };
});
</pre>
To be used in the <code>X.js</code> file, you must use the same method as in the [[#Create an anonymous class|previous section]]:
<pre>
<nowiki>[[X.js]]</nowiki>
/**
*------
* BGA framework: © Gregory Isabelli <gisabelli@boardgamearena.com> & Emmanuel Colin <ecolin@boardgamearena.com>
* X implementation : © <Your name here> <Your email address here>
*
* This code has been produced on the BGA studio platform for use on http://boardgamearena.com.
* See http://en.boardgamearena.com/#!doc/Studio for more information.
* -----
*
* X.js
*
* X user interface script
*
* In this file, you are describing the logic of your user interface, in Javascript language.
*
*/
define([
    "dojo","dojo/_base/declare",
    "./modules/js/SecondModule",        //Has to be inserted in the third position as we'll need an identifier later, and the other modules don't need it, see code in the preceding subsection.
    "./modules/js/sigletonObject",
    "ebg/core/gamegui",
    "ebg/counter",
    "./modules/js/Firstmodule",
],
function (dojo, declare, SecondModule /* insert a reference here that you'll use throughout the JS file for this module */, singletonObject) {
    return declare("bgagame.X", ebg.core.gamegui, {
    ...
    }
}
</pre>
Then you can access your code the same way as described in the [[#Create an anonymous class|previous section]]:
<pre>
    singletonObject.firstMethod();
    ...
</pre>


== Putting it all together ==
== Putting it all together ==

Revision as of 16:20, 14 June 2022

WIP
This article is a Work In Progress, please do not refer to it for production purposes

This page will cover steps you can take as a BGA developer to make your code more modular and better organized. The way the framework is implemented makes the game logic and the interface logic files very monolithic. While this is not a problem in itself, even simple to moderately complex game may require this files to be over 5k lines of code. Thus you can quickly become lost in all the functions you need to declare, where they are declared, and where they are called.

But there are steps that you can follow to take advantage of PHP's Object Oriented Code and the dojo toolkit's AMD loader to organize your code in separate files. Let's see what's available:

On the PHP side

include vs require

Throughout this section, I'll make heavy use of PHP's require_once control structure. Why am I using require(_once) instead of include_once? Because if an error exists in a PHP file that you try to include, only a warning will be thrown, but the script will continue in spite of the error. Using require if the included file has an error, the script dies when the inclusion takes places, throwing a fatal error (E_COMPILE_ERROR).

That way, I'm sure the classes, traits or interfaces I'm including are syntax error free.

Game logic methods

The way the framework is implemented, your game logic is gathered inside a class (YourProjectName) extending the Table class. You define your methods there so that they may be called from other parts of the framework (as long as they're public methods obviously).

But you can take advantage of PHP Traits. In a nutshell, Traits are a collection of methods that can be reused in different classes, to avoid code duplication. Here we're not going to reuse them anywhere else than in the game class, but this little trick allows us to put methods definitions in other files, and in so doing to avoid monolithic code.

Basically you create a Trait in th /modules/ directory, for instance:

[[modules/UtiltityFunctionsTrait.php]]
<?php
namespace YourProjectNamespace\Modules;

trait UtilityFunctionsTrait {

    public function myFirstUtilityFunction($args)
    {
        //Your code here
    }

}

Then you can include it in you project's X.game.php file like so:

[[X_game.php]]
<?php
 /**
  *------
  * BGA framework: © Gregory Isabelli <gisabelli@boardgamearena.com> & Emmanuel Colin <ecolin@boardgamearena.com>
  * X implementation : © <Your name here> <Your email address here>
  * 
  * This code has been produced on the BGA studio platform for use on http://boardgamearena.com.
  * See http://en.boardgamearena.com/#!doc/Studio for more information.
  * -----
  * 
  * X.game.php
  *
  * This is the main file for your game logic.
  *
  * In this PHP file, you are going to defines the rules of the game.
  *
  */

require_once 'modules/UtilityFunctionsTrait.php'; //Here we require the trait to be loaded when the class is loaded

use YourProjectNamespace\Modules\UtilityFunctionsTrait; //We import the trait to be used directly as UtilityFunctionsTraits, otherwise we would have to use the Fully qualified class name (YourProjectNamespace\Modules\UtilityFunctionsTrait)

class YourProjectName extends Table
{
//...

//////////////////////////////////////////////////////////////////////////////
//////////// Utility functions
////////////    

    /*
        In this space, you can put any utility methods useful for your game logic
    */

    use UtilityFunctionsTrait; //Here we actually include the trait inside the class, making all the trait's methods available as class methods, keeping their visibility scope (so a private method is still private)
}

Support classes

Basically, the same as traits, you put your classes definitions into files that live under the /modules/ directory (don't forget to namespace your classes), and then require them at the top of X_game.php, and voilà, you're done

Adding autoloader support

Coding standards

Even for simple games, you might end up having a dozen of traits and support classes. You can require them all in your X_game.php. Or you can use an autoloader, which will load the necessary classes and traits at runtime. There are two PSRs dealing with autloading standards (namely PSR-0 which is marked as deprecated and PSR-4) which state that your namespaces should be a reflection of the directory structure of your project.

Basically, when creating namespaces, you choose a namespace prefix. For example, you could use your BGA handle and the project name as a namespace prefix (would result in \SwHawk\X in my case), and then the rest of the namespace would be the directory the file is in. I usually group classes and traits by the function they have in my project, so my /modules/ directory looks like that:

modules/
    php/
        Factory/                      //Holds my factory classes
            AFactoryClass.php         //The namespace for this file would be \SwHawk\X\Factory, and the fully qualified class name would be \SwHawk\X\Factory\AFactoryClass
            ...
        Object/                       //Holds my support classes
            ObjectA.php               //The namespace for this file would be \SwHawk\X\Object, and the fully qualified class name would be \SwHawk\X\Object\ObjectA
            ...
        Traits/                       //Holds my traits
            UtilityFunctionsTrait.php //The namespace for this file would be \SwHawk\X\Traits, and the fully qualified class name would be \SwHawk\X\Traits\UtilityFunctionsTrait
            ...
        ...
    ...

Autoloader function for development

While your project is under development, you usually create, move and remove classes as part of the development process. So you usually need an autoloading function that can handle a lot of flexibility. Basically once you import a class using the use keyword, the autoloading function will determine which file to require using its fully qualified class name, and then require. Such a function would have the following code (borrowed and adapted from this repository):

spl_autoload_register(function ($class) {

    // project-specific namespace prefix, adapt to your needs, remember that you must escape \ characters in double-quoted strings (hence the \\)
    $prefix = 'SwHawk\\X\\';

    // base directory for the namespace prefix, this file would usually reside in the modules/php/includes/ directory, so the base directory for all my classes would be a level higher
    $base_dir = __DIR__ . '/../';

    // does the class use the namespace prefix?
    $len = strlen($prefix);
    if (strncmp($prefix, $class, $len) !== 0) {
        // no, move to the next registered autoloader
        return;
    }

    // get the relative class name
    $relative_class = substr($class, $len);

    // replace the namespace prefix with the base directory, replace namespace
    // separators with directory separators in the relative class name, append
    // with .php
    $file = $base_dir . str_replace('\\', '/', $relative_class) . '.php';

    // if the file exists, require it
    if (file_exists($file)) {
        require $file;
    }
});

Autoloader function for production

Once you're moving your game to production, the autoloader function provided before isn't optimized. Once in production, the directory tree should not be modified, so you can change the earlier autoloader to a classmap based one. Basically, you build an associative array with the fully qualified classes names as keys and the filepath as the value. An example would look like so:

spl_autoload_register(function ($class) {
    static $classmap = array(
        "SwHawk\\X\\Factory\\AFactoryClass" => __DIR__ . "/../Factory/AFactoryClass.php",
        ...
    );
    if(array_key_exists($class)) {
        require $classmap[$class];
    } else {
        return;
    }
}

This autoloader is better suited to production since it won't use expensive calls like file_exists($filename). You can write the classmap by yourself, but it can be quite cumbersome, there is some tools like this project, or this one, or even scripts detailed in this StackOverflow topic

On the JS side

BGA uses the dojo toolkit framework for most of its javascript code. Dojo comes with its own way of loading modules, which you can read about in more detail here and here. To put it simply, there are two ways you can go about this

Write plain javascript

Should you wan to write plain javascript, you can easily do so. What you need to do is actually load the file like so in X.js:

[[X.js]]
/**
 *------
 * BGA framework: © Gregory Isabelli <gisabelli@boardgamearena.com> & Emmanuel Colin <ecolin@boardgamearena.com>
 * X implementation : © <Your name here> <Your email address here>
 *
 * This code has been produced on the BGA studio platform for use on http://boardgamearena.com.
 * See http://en.boardgamearena.com/#!doc/Studio for more information.
 * -----
 *
 * X.js
 *
 * X user interface script
 * 
 * In this file, you are describing the logic of your user interface, in Javascript language.
 *
 */

define([
    "dojo","dojo/_base/declare",
    "ebg/core/gamegui",
    "ebg/counter",
    "./modules/path/to/firstfile.js",        //The first file with your JS code
    "./modules/path/to/secondfile.js",       //The second file with another part of your JS code
    ...
],
function (dojo, declare) {
    return declare("bgagame.X", ebg.core.gamegui, {
        constructor: function(){
            ...
        }

According to the dojo toolkit documentation, you will then need to directly access what you defined in the files.

Write an AMD module

You can take advantage of the toolkit's module system to declare dependencies between the differents files you'll be writing (modules in the toolkit's language). To be identified as modules, your Javascript files will need to have the following structure:

Create a named new class

[[modules/js/FirstModule.js]]
define([
    "dojo",
    "dojo/_base/declare",
    other dependencies...
],function(dojo, declare){
    return declare("className", /*Parent classes that this class inherits, optional*/, {
        /* static properties */
        let property1 = "value;
        let property2 = 5;
        constructor: function (args) {
            /* instance properties */
            let property3 = 8;
            let property4 = [ "arrayValue", "arrayValue2" ]; 
        }
        method1: function (args) {
            /* your code here */
        }
        ...
    });
});

Then in the X.js file, you can use your newly created module like so:

[[X.js]]
/**
 *------
 * BGA framework: © Gregory Isabelli <gisabelli@boardgamearena.com> & Emmanuel Colin <ecolin@boardgamearena.com>
 * X implementation : © <Your name here> <Your email address here>
 *
 * This code has been produced on the BGA studio platform for use on http://boardgamearena.com.
 * See http://en.boardgamearena.com/#!doc/Studio for more information.
 * -----
 *
 * X.js
 *
 * X user interface script
 * 
 * In this file, you are describing the logic of your user interface, in Javascript language.
 *
 */

define([
    "dojo","dojo/_base/declare",
    "ebg/core/gamegui",
    "ebg/counter",
    "./modules/js/Firstmodule",
],
function (dojo, declare) {
    return declare("bgagame.X", ebg.core.gamegui, {
    ...
    }
}

In your code, you can access your module's class and methods by doing so:

    let object = new className();
    object.method1();
    ...

This can lead to namespace collisions if you don't choose a namespace correctly, so you might want to take the same approach as described earlier for the PHP files for using a namespace.

Create an anonymous class

This is the recommended way according to the dojo toolkit documentation, but it requires a bit more modification than the previous method:

[[modules/js/SecondModule.js]]
define([
    "dojo",
    "dojo/_base/declare",
    other dependencies...
],function(dojo, declare){
    return declare(null, /*Parent classes that this class inherits, optional*/, {
        /* static properties */
        let property1 = "value;
        let property2 = 5;
        constructor: function (args) {
            /* instance properties */
            let property3 = 8;
            let property4 = [ "arrayValue", "arrayValue2" ]; 
        }
        method1: function (args) {
            /* your code here */
        }
        ...
    });
});

Then in the X.js file, you can use your newly created module like so:

[[X.js]]
/**
 *------
 * BGA framework: © Gregory Isabelli <gisabelli@boardgamearena.com> & Emmanuel Colin <ecolin@boardgamearena.com>
 * X implementation : © <Your name here> <Your email address here>
 *
 * This code has been produced on the BGA studio platform for use on http://boardgamearena.com.
 * See http://en.boardgamearena.com/#!doc/Studio for more information.
 * -----
 *
 * X.js
 *
 * X user interface script
 * 
 * In this file, you are describing the logic of your user interface, in Javascript language.
 *
 */

define([
    "dojo","dojo/_base/declare",
    "./modules/js/SecondModule",         //Has to be inserted in the third position as we'll need an identifier later, and the other modules don't need it, see code in the preceding subsection. 
    "ebg/core/gamegui",
    "ebg/counter",
    "./modules/js/Firstmodule",
],
function (dojo, declare, SecondModule /* insert a reference here that you'll use throughout the JS file for this module */) {
    return declare("bgagame.X", ebg.core.gamegui, {
    ...
    }
}

In your code, you can then access your module's class and methods by doing so:

    let someValue = SecondModule.property3
    SecondModule.method1();
    ...

Create a singleton object

You can also create singleton objects by creating a module this way:

[[modules/js/singletonObject.js]]
define([
    "dojo",
    ...
], function (dojo) {
    // Methods and variables defined in this part will not be available anywhere else than in this file
    let privateVariable = "someValue";
    let privateFunction = function (args) {
        //some code here
    }
    return {
        firstMethod: function (args) {
            privateFunction(args);
            //some other code here
        }
    };
});

To be used in the X.js file, you must use the same method as in the previous section:

[[X.js]]
/**
 *------
 * BGA framework: © Gregory Isabelli <gisabelli@boardgamearena.com> & Emmanuel Colin <ecolin@boardgamearena.com>
 * X implementation : © <Your name here> <Your email address here>
 *
 * This code has been produced on the BGA studio platform for use on http://boardgamearena.com.
 * See http://en.boardgamearena.com/#!doc/Studio for more information.
 * -----
 *
 * X.js
 *
 * X user interface script
 * 
 * In this file, you are describing the logic of your user interface, in Javascript language.
 *
 */

define([
    "dojo","dojo/_base/declare",
    "./modules/js/SecondModule",         //Has to be inserted in the third position as we'll need an identifier later, and the other modules don't need it, see code in the preceding subsection.
    "./modules/js/sigletonObject", 
    "ebg/core/gamegui",
    "ebg/counter",
    "./modules/js/Firstmodule",
],
function (dojo, declare, SecondModule /* insert a reference here that you'll use throughout the JS file for this module */, singletonObject) {
    return declare("bgagame.X", ebg.core.gamegui, {
    ...
    }
}

Then you can access your code the same way as described in the previous section:

    singletonObject.firstMethod();
    ...

Putting it all together