Difference between revisions of "User:Mark Johnson/Namespaces"

Jump to: navigation, search
(Steps for conversion)
(Steps for conversion)
Line 42: Line 42:
 
Functions from the namespace, such as print_tabs, can now be called thusly:
 
Functions from the namespace, such as print_tabs, can now be called thusly:
 
<code php>tg\print_tabs();</code>
 
<code php>tg\print_tabs();</code>
 +
 +
===Conclusions===
 +
* Using namespaces achieves the stated goal of improving readability and ease of writing code by shortening function names.
 +
* Using existing naming conventions for the namespaces is logical and eases the transition for developers not used to namespaces.
 +
* Namespaces will not be suitable for all libraries due to some plugins requiring the current naming conventions for some functions. However, even in these cases all non-standard functions could be namespaced to achieve the same advantages.
 +
 +
===Code===
 +
Once completed, the plugin will be published on GitHub as an example of a Moodle plugin using namespaces.

Revision as of 11:10, 24 May 2011

Note: This page is a work-in-progress. Feedback and suggested improvements are welcome. Please join the discussion on moodle.org or use the page comments.


Notes about using PHP namespaces in Moodle plugin development

Goal: To take advantage of namespace features in PHP 5.3 to allow plugins to be written with less verbose function names, while still avoiding name collisions

About this document

For the purposes of this document, the term "function" will be used to refer to any PHP function, constant or class defined in a Moodle plugin library (unless explicitly indicated otherwise), since namespaces apply to all 3 in the same way.

The exemplar plugin used for this exercise is an admin report used for calculating Target Grades.

Current Issue

When writing a plugin, one creates a lib.php or locallib.php containing a set of functions for use within that plugin. Each function name must currently be prefixed in the format {plugintype}_{pluginname}_, to avoid a function that performs a similar task in a separate plugin having the same name, thus causing a name collision.

This can result in overly verbose function names which inhibits both readability and ease of writing of code. For example, a function for printing tabs in an admin report named targetgrades would need to be called report_targetgrades_print_tabs() since there is already a global function called print_tabs(). The majority of this name is only there to avoid name collisions, and it otherwise redundant.

Proposal

I am going to upgrade one of my Moodle 1.9 blocks for use in Moodle 2.x. During this process I will alter the libraries to use namespaces, allowing functions, classes and constants to have shorter names while still avoiding name collisions. In files including these libraries, I will use namespace aliases to allow the functions to be called using much shorter notation.

Naming convention

As mentioned above, the current naming convention for prefixing functions is plugintype_pluginname. It makes logical sense to use a similar convention in the namespace hierachy - each plugin having a namespace of plugintype\pluginame. For example, all admin reports would have their functions the report namespace, and the Target Grades report would have it's own sub-namespace, report\targetgrades.

Potential issues

This may cause issues with some plugin types. For example, Activity modules require certain functions following the current naming convention to exist in lib.php. Placing these functions within a namespace would prevent them from working properly.

Most plugin types will include lib.php and its functions automatically. While this should not cause a problem for the majority of plugin types since the functions shouldn't be accessed unless explicitly requested in the code, it's a potential source of problems to be aware of.

Steps for conversion

All libraries used by the plugin needed to be put inside the plugin's namespace. This was achieved by placing the following line at the top of the library files

namespace report\targetgrades;

Note that the report namespace does not already have to have been defined for this to work.

Next, the report_targetgrade_ prefix was removed from all function and class names in the libraries, as it is now redundant.

Any functions in the global namespace (i.e. built in PHP functions or Moodle functions) that are used in the library functions were prefixed with a backslash. This doesn't appear to be strictly necessary with actual functions (as opposed to constants or classes, where it's definitely necessary), but was done for consistency.

In any documents that used the libraries, the files were included as usual using require_once at the start of the file. This includes the functions within their namespace, and makes that namespace available in the file. This was followed immediately by

use report\targetgrades as tg;

Which allows tg to be used an alias for the report\targetgrades namespace when calling functions.

Functions from the namespace, such as print_tabs, can now be called thusly:

tg\print_tabs();

Conclusions

  • Using namespaces achieves the stated goal of improving readability and ease of writing code by shortening function names.
  • Using existing naming conventions for the namespaces is logical and eases the transition for developers not used to namespaces.
  • Namespaces will not be suitable for all libraries due to some plugins requiring the current naming conventions for some functions. However, even in these cases all non-standard functions could be namespaced to achieve the same advantages.

Code

Once completed, the plugin will be published on GitHub as an example of a Moodle plugin using namespaces.