Jump to content

Modular Systems?


Nolongerused3921

Recommended Posts

Well I've decided to take the plunge and rewrite my base code I use in all my projects, and I want to make sure to get it right this time and make sure its completely modular. But, quite honestly, I don't fully understand the allure, need, or what a modular system truly entails.

I'm open for advice on what features a modular system needs, and any articles you can point out for me :)

Thanks
Link to comment
Share on other sites

A Modular system doesn't 'need' anything :)

Before you even begin - I highly suggest you read up on Design Patterns, Test Driven Design and that you start completely from scratch with any project. Get some Use Cases together, then schematics, interface designs, then class diagrams, etc. etc.

When developing a system, very little time is actually spent coding. The bulk is designing.
Link to comment
Share on other sites

For starters, I would extend any classes you can. For example, update the query method in mysqli to throw custom exceptions instead of placing an[tt] or die (...); [/tt] (or what have you) after each query.

Use constants (short cuts), e.g.:

[code]
<?php

### General.
define('SELF', $_SERVER['PHP_SELF']);
define('INC', 'includes/');
define('GUI', INC . 'gui/');

### Database.
define('MYSQL_HOST', '...');
define('MYSQL_USER', '...');
define('MYSQL_PASS', '...');
define('MYSQL_DB', '...');

?>
[/code]

Use naming schemes.
Link to comment
Share on other sites

When going for a modular design, try to avoid 'hard coding' options.

Personally I use a file 'config.xml' to store all my options, that way the configuration (like installed modules) can be altered without changing the actual php code.

Given that you would have an class called 'config' to store/get configuration options, you could use that class to populate constants, or you could make a global instantiation of the class and assign the stored options to it's properties.

Example:
[code]<?php
global $config;
$config = new Config('config.xml');
mysql_connect($config->MySQLHost,$config->MySQLUser,$config->MySQLPass);
?>[/code]
[code]<?php
$config = new Config('config.xml');
define('MYSQL_HOST', $config->get('MYSQL_HOST'));
define('MYSQL_USER', $config->get('MYSQL_USER'));
define('MYSQL_PASS', $config->get('MYSQL_PASS'));
define('MYSQL_DB', $config->get('MYSQL_DB'));
mysql_connect(MYSQL_HOST,MYSQL_USER,MYSQL_PASS,MYSQL_DB);
?>[/code]
or:
[code]<?php
//Upon construction, put all options in $options porperty
$config = new Config('config.xml');
foreach($config->options as $option=>$value){
define($option, $value);
}
mysql_connect(MYSQL_HOST,MYSQL_USER,MYSQL_PASS,MYSQL_DB);
?>[/code]
Link to comment
Share on other sites

For the loading, what I was thinking about doing is making the "main file" (All the module loading stuff), read a list of modules from a modules.php file (Which includes where they're located), and loading up ones that are important automatically (A priority system in modules.php?), and allowing each module to include other modules on its own.

Now this could lead to problems, but I have solved it (In theory :p), by making the module loading function (Which 'automatic loading' calls) add the module loaded into an array, and checking this array every time it loads a new module into memory - this way modules that need to access the mysql module, can call it in case they are called before MySQL is loaded automatically.

Its a bit confusing, but it sounds good... At least to me.


This is just a small portion of it, and I'd like to get some comments and suggestions and hear more ideas before I actually plan this all out in full :)
Link to comment
Share on other sites

[quote author=Sykoi link=topic=107752.msg432815#msg432815 date=1158076097]
For the loading, what I was thinking about doing is making the "main file" (All the module loading stuff), read a list of modules from a modules.php file (Which includes where they're located), and loading up ones that are important automatically (A priority system in modules.php?), and allowing each module to include other modules on its own.

Now this could lead to problems, but I have solved it (In theory :p), by making the module loading function (Which 'automatic loading' calls) add the module loaded into an array, and checking this array every time it loads a new module into memory - this way modules that need to access the mysql module, can call it in case they are called before MySQL is loaded automatically.

Its a bit confusing, but it sounds good... At least to me.


This is just a small portion of it, and I'd like to get some comments and suggestions and hear more ideas before I actually plan this all out in full :)
[/quote]

Just to make sure we're on the level here: with loading modules into an array you mean loading instances of classes representing modules into an array? If so, how do you propose to access the objects from other modules (objects)? You could of course make the array global. One of the things I run into often, is that when I load a diff class from one class from the constructor, I cannot operate on the global instance of the first class from the second class, because the object is not yet constucted. Be carefull what you put in constructors, watch your extends.

Or are you using procedural code, and are the files with functions simply included, and does the array hold the names of modules loaded? If so, you could do without the array and just check function_exists().
Link to comment
Share on other sites

[quote author=448191 link=topic=107752.msg432836#msg432836 date=1158077066]
[quote author=Sykoi link=topic=107752.msg432815#msg432815 date=1158076097]
For the loading, what I was thinking about doing is making the "main file" (All the module loading stuff), read a list of modules from a modules.php file (Which includes where they're located), and loading up ones that are important automatically (A priority system in modules.php?), and allowing each module to include other modules on its own.

Now this could lead to problems, but I have solved it (In theory :p), by making the module loading function (Which 'automatic loading' calls) add the module loaded into an array, and checking this array every time it loads a new module into memory - this way modules that need to access the mysql module, can call it in case they are called before MySQL is loaded automatically.

Its a bit confusing, but it sounds good... At least to me.


This is just a small portion of it, and I'd like to get some comments and suggestions and hear more ideas before I actually plan this all out in full :)
[/quote]

Just to make sure we're on the level here: with loading modules into an array you mean loading instances of classes representing modules into an array? If so, how do you propose to access the objects from other modules (objects)? You could of course make the array global. One of the things I run into often, is that when I load a diff class from one class from the constructor, I cannot operate on the global instance of the first class from the second class, because the object is not yet constucted. Be carefull what you put in constructors, watch your extends.

Or are you using procedural code, and are the files with functions simply included, and does the array hold the names of modules loaded? If so, you could do without the array and just check function_exists().
[/quote]

Errr no you're completely misunderstanding me, what I meant is that it would load the module's NAME into an array... The function itself would load a module based on an alias, then add that alias to a list of modules loaded... It would be solely used to keep track of what is loaded.

And yes, your second statement is correct... However, I'd rather not use function_exists() as it would kind of defeat the purpose in my opinion, as it would require you to know a function from that module.
Link to comment
Share on other sites

one of the biggest unofficial no-no's in OOP is the use of globals :)

'good' OOP practice is pass values around as parameters when and where needed, not to blanket label something for all to see :)

[code]<?php

$config = new XMLConfig('config.xml');

$db = new DataBaseClass;

$db->connect($config->db_host, $config->db_user, $config->db_pass);

//etc.
?>[/code]

For what you have posted above re: loading, I suggest your read up on the Service Locator pattern, Dependancy Injection and also the use of a Registry.
Link to comment
Share on other sites

[quote author=Jenk link=topic=107752.msg432847#msg432847 date=1158077476]
one of the biggest unofficial no-no's in OOP is the use of globals :)

'good' OOP practice is pass values around as parameters when and where needed, not to blanket label something for all to see :)

[code]<?php

$config = new XMLConfig('config.xml');

$db = new DataBaseClass;

$db->connect($config->db_host, $config->db_user, $config->db_pass);

//etc.
?>[/code]
[/quote]

I know use of globals is generally considered risky (although if you have a link to an article that explains the risks in depth it would be appreciated), but one has to consider performance.

If I create a new Config instance every time I need a configuration option, the class has to initialize equal those times. Meaning it has to read from the XML file at least a dozen times instead of once. So maybe it's better to use the class to define constants?

Furthermore, if you would want to avoid an object to become global, you have to take serious precautions!

For example, if I would put your code example in my index, both $config and $db would become global variables.
Link to comment
Share on other sites

[quote author=Sykoi link=topic=107752.msg432843#msg432843 date=1158077362]
... However, I'd rather not use function_exists() as it would kind of defeat the purpose in my opinion, as it would require you to know a function from that module.
[/quote]

But you intend to use the function, right? Wouldn't you need to know the name of the function in order to use it?  ;D

Just check for the first function you want to use, if it exists, you know the 'module' is loaded and it is safe to use the other functions in that module.
Link to comment
Share on other sites

[quote author=448191 link=topic=107752.msg432868#msg432868 date=1158079436]
[quote author=Sykoi link=topic=107752.msg432843#msg432843 date=1158077362]
... However, I'd rather not use function_exists() as it would kind of defeat the purpose in my opinion, as it would require you to know a function from that module.
[/quote]

But you intend to use the function, right? Wouldn't you need to know the name of the function in order to use it?  ;D

Just check for the first function you want to use, if it exists, you know the 'module' is loaded and it is safe to use the other functions in that module.
[/quote]

Yes but I was kind of going for a no hassle, automatic, "just call the load function" functionality :p
Link to comment
Share on other sites

[quote author=Jenk link=topic=107752.msg432847#msg432847 date=1158077476]
For what you have posted above re: loading, I suggest your read up on the Service Locator pattern, Dependancy Injection and also the use of a Registry.
[/quote]

Hey, thanks, that was of great use to me, especially the Registry pattern.  :)
Link to comment
Share on other sites

I've been planning my engine out, but I've run into a bit of a problem... How should I handle permissions?
I was thinking having an internal module (Automatically loaded regardless) set to do permissions checks, and have each module set its own permission tables (Defines), but this leads to the (Nearly impossible but potential) problem of... What will I do when I want to access certain permissions from other modules?

My other idea was to put a SET permission table in the permission checker... But this kind of scares me, since I'd have to have a LARGE number of defines and could potentially run out of bitwise numbers.

Although, after a bit of thought... I suppose the latter would make more sense as the bitwise number would be stored in the database, in the same column...
Anyone have comments or suggestions on this?
Link to comment
Share on other sites

[quote author=Sykoi link=topic=107752.msg433530#msg433530 date=1158162860]
I've been planning my engine out, but I've run into a bit of a problem... How should I handle permissions?
I was thinking having an internal module (Automatically loaded regardless) set to do permissions checks, and have each module set its own permission tables (Defines), but this leads to the (Nearly impossible but potential) problem of... What will I do when I want to access certain permissions from other modules?

My other idea was to put a SET permission table in the permission checker... But this kind of scares me, since I'd have to have a LARGE number of defines and could potentially run out of bitwise numbers.

Although, after a bit of thought... I suppose the latter would make more sense as the bitwise number would be stored in the database, in the same column...
Anyone have comments or suggestions on this?
[/quote]

I'm kinda confused by this... Who (or what) exactly are you permitting (or not) to do what?
Link to comment
Share on other sites

I've been thinking about designing a modular site as well and here are my thoughts on permissions.  I've not yet put it into practice and the coding would be tricky, but I think it would offer the most robust solution.

Each module installed on the site should export privileges relating to that module.  For instance, a forums module should provide privileges to edit, moderate, delete, move, etc. posts.  A gallery module should allow for the deletion of images.  Each module would be required to provide a privileges.php with a function export_privileges().

Every account to the site should have a user type associated with it and the user types [b]should not[/b] be hard coded (with the possible exception being the administrator)!  They should exist in a table.  The admin should be able to log in and dynamically create new user types.  As each type is created, the site should get a list of the exported privileges from each module and allow the admin to configure those privileges for the new user type.

With this method, when the site is accessing a module for a user, it can pass in the user's privileges for that module and the module can behave accordingly.
Link to comment
Share on other sites

I was thinking about a much easier, messier but yet just as robust system... Each module is self contained in a single file, in a single class... You include it by defining a complex array filled with various information in a singular file used by the modular system.
One of the array variables would be the name of the permission list, along with a list of possible permissions.

This way, you can store permissions for each module in a single column, in a setup like this:
main:64;gallery:96;etc:112
(Obviously those numbers aren't bitwise)

Its a bit sloppy... But it allows for you to plug and play modules, quickly search for permissions on a module by module basis, etc.
Link to comment
Share on other sites

do not store multiple components of data within the same column, separate them.

If using bitwise, you only need to store one number for all of your permissions.

If you need a name/description of all permissions, create a new table for it.
[code]CREATE TABLE `permissions` {
  `id` INT NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(20) NOT NULL,
  `description` TEXT,
  `level` BIGINT NOT NULL DEFAULT 0
} PRIMARY KEY `id`;[/code]

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.