Page 2 of 3

Posted: Sun Jul 08, 2007 11:29 am
by Z3RO21
I use super global arrays such as $_GET and $_POST, but as for implementing my own globals I prefer to use a registry class.

Posted: Sun Jul 08, 2007 11:32 am
by alex.barylski
stereofrog wrote:
Oren wrote:I'm sorry, but that's a stupid answer - simply because there is no good answer.
Please don't lower the level of the discussion with arguments like this.
Doing that as opposed to doing what is in Application's constructor cannot be justified, it's pretty much like taking everything in the index.php file and throw it into some other file and then include this other file from index.php - this will take the same time as without doing it at best, and will probably be slower at worst.
I'm not sure what you're trying to say here. Can you provide an example of your approach?
I'm not sure I follow the argument with keeping functionality inside a constructor or directly inside index.php, but I agree with your statement above.

Is Application just a moniker for application engine, etc?

In either case, I think it depends on the architecture of your application.

For example, index.php I usually reserve for application specifics. An easy way to allow users to customize the application (authentication checks, output filtering, etc). Application objects would be considered a core part of the system. Basically, index.php is where I keep most "truely" global operations.

Posted: Sun Jul 08, 2007 12:15 pm
by Christopher
stereofrog wrote:
oren wrote:Doing that as opposed to doing what is in Application's constructor cannot be justified, it's pretty much like taking everything in the index.php file and throw it into some other file and then include this other file from index.php - this will take the same time as without doing it at best, and will probably be slower at worst.
I'm not sure what you're trying to say here. Can you provide an example of your approach?
The question is: What are the security, design and maintenance differences between::

Code: Select all

//Application.php:
class Application {
function __construct() {
     $this->a();
     $this->b();
}
function a() {}
function b() {}
}

//index.php:
include 'Application.php';     // here or in autoprepend -- same effect
new Application();     // run __construct();
And:

Code: Select all

//Application.php:
class Application {
function a() {}
function b() {}
}

//index.php:
include 'Application.php';
$app = new Application();
$app->a();
$app->b();
Considerations might be things like exploitablity, memory usage, extra method call overhead, obviousness to other programmers, etc.

Posted: Sun Jul 08, 2007 12:37 pm
by alex.barylski
There is no difference in the two examples you show, except that in one, the ctor() calls the methods so the object is self-initializing whereas the second example, requires explicit initialization...

I fail to see any benefits, security problems, etc...

What approach you use would depend on the problem :?

If Application requires a() & b() to be called before object use then yea...calling them in ctor() is kind of good practice. Otherwise, they are optional and probably best left in the hands of the client programmer...

One thing I did notice in your example, was that #1 would be a usability nightmare because Application() instance isn't assigned to variable so it would be mighty difficult to use anywhere. :P

I assume that was for the sake of brevity or was that part of the problem? :)

Posted: Sun Jul 08, 2007 12:52 pm
by Ollie Saunders
Well it's probably quite dangerous to do anything more than required for construction of the object in the constructor. Personally I would opt for

Code: Select all

$fooBar = FooBar_Application();
$fooBar->run();
1 single variable really presents no problems as it is easy to find and change or wrap in a function.

Although what I'm actually doing at the moment is

Code: Select all

FooBar_Application::init();
which isn't actually a very good idea, say if you need to manage multiple applications. The constructor approach suffers from the same problems but is more confusing to the reader.

For the same reason why I avoid globals I wouldn't actually use a class called "Application", all classes should have at least a three letter prefix to prevent the risk of name clashing.

Posted: Sun Jul 08, 2007 1:02 pm
by Oren
stereofrog wrote:Please don't lower the level of the discussion with arguments like this.
I'm sorry, but there isn't much to say here, it's pretty much straight forward.

Posted: Sun Jul 08, 2007 1:09 pm
by alex.barylski
ole wrote:Well it's probably quite dangerous to do anything more than required for construction of the object in the constructor. Personally I would opt for
Why is it dangerous to use a constructor for object construction? The name alone implies it's very use. :)
ole wrote:For the same reason why I avoid globals I wouldn't actually use a class called "Application", all classes should have at least a three letter prefix to prevent the risk of name clashing.
Admittedly I am not following this thread very closely and have no idea where that came from... :P

I agree, at least in adding extra namespace to each class name until namespaces are standard part of PHP. Whether three characters or not. I usually prefix my classes with the code name of the project.

class Omaha_Application

Each major version gets a new codename so version 2:

class Juno_Application

As a war film junkie I use code names that pay homage to that amazing time in our world history. I also use airplanes, stars or anything else I consider "cool". :P

What was the point of this topic? :roll:

Posted: Sun Jul 08, 2007 1:10 pm
by Chris Corbyn
In other languages you'll often see a static method call as the dispatcher.

C(#/++) uses a statically called main() method.
Java/Desktop/CLI uses a static main() method.

PHP doesn't enforce anything which is arguably flexible, or messy.
Java Servlets use doGet(), doPost(), doPut() etc methods, called on an instance of HttpServlet.

I'm not sure what the internals of a Java servlet being dispatched are, but the instance of HttpServlet needs to come from somewhere.

I like to do something a bit like what ~ole just did, albeit selecting an approriate controller first.

Code: Select all

define("FRAMEWORK_ROOT", "/somewhere/in/here");
require_once FRAMEWORK_ROOT . "/lib/Core/Context.php";
Core_Context::getInstance()->getController()->dispatch();
I don't think it's bad to use globals just as a launch point though. It's only down to preference that I dispatch in this way.

Posted: Sun Jul 08, 2007 1:33 pm
by stereofrog
arborint wrote: The question is: What are the security, design and maintenance differences between::

Code: Select all

//Application.php:
class Application {
function __construct() {
     $this->a();
     $this->b();
}
function a() {}
function b() {}
}

//index.php:
include 'Application.php';     // here or in autoprepend -- same effect
new Application();     // run __construct();
And:

Code: Select all

//Application.php:
class Application {
function a() {}
function b() {}
}

//index.php:
include 'Application.php';
$app = new Application();
$app->a();
$app->b();
Considerations might be things like exploitablity, memory usage, extra method call overhead, obviousness to other programmers, etc.
Let's consider the more realistic yet still simplified example:

Code: Select all

class Application
{
	function __construct() {
		$lc = new LocalConfig();
		if($lc->rewrite_method == '404') {
			$router = $lc->get('router_404');
		} else {
			$router = $lc->get('router');
		}
		$request = $lc->get('request');
		list($ac_name, $action) = $router->map($request);
		$ac = $lc->get('ac_name');
		if(!$ac) {
			$ac = $lc->get('error_controller');
			$action = 'controller_not_found';
		}
		$html = $ac->run($lc, $action, $request);
		$html = $router->url_rewrite($html);
		echo $html;
	}
}
Add persistence, plugin support, CLI support and anything else to your taste. Would it be practical to put all this into global scope? I don't think so.

Posted: Sun Jul 08, 2007 1:52 pm
by stereofrog
ole wrote:Well it's probably quite dangerous to do anything more than required for construction of the object in the constructor. Personally I would opt for

Code: Select all

$fooBar = FooBar_Application();
$fooBar->run();
Good approach, however there are two problems with it. First, it's often hard to separate "what is required for construction" (strictly speaking, nothing) from "what is required for running" (strictly speaking, everything). Requiring the constructor to have absolutely no side effects doesn't seem practical to me. Second, if the constructor fails, where would you handle an exception: in __construct() or in run()?
For the same reason why I avoid globals I wouldn't actually use a class called "Application", all classes should have at least a three letter prefix to prevent the risk of name clashing.
From my POV, prefixing (aka "poor man's namespaces") is useful for common library classes, not for the application ones, especially the main Application class, which is unique by definition.

Posted: Sun Jul 08, 2007 3:17 pm
by Christopher
stereofrog wrote: Let's consider the more realistic yet still simplified example:

Add persistence, plugin support, CLI support and anything else to your taste. Would it be practical to put all this into global scope? I don't think so.
Again the question is not if you think so. It is whether there are some sort of reasonable security, performance or maintainablity reasons to do so. I think this is a very worthwhile subject PHP developers to think through. I think use of the global scope is something that we ought to have so best practice guidelines for. Certainly in the past with register_globals defaulting to ON there were security concerns regarding uninitialized variables in the global scope. But register_globals has defaulted to OFF for several years now.

So what are the real differences related to security, design and maintenance between the following index.php scripts?

Code: Select all

class Application
{
	function __construct() {
		$lc = new LocalConfig();
		if($lc->rewrite_method == '404') {
			$router = $lc->get('router_404');
		} else {
			$router = $lc->get('router');
		}
		$request = $lc->get('request');
		list($ac_name, $action) = $router->map($request);
		$ac = $lc->get('ac_name');
		if(!$ac) {
			$ac = $lc->get('error_controller');
			$action = 'controller_not_found';
		}
		$html = $ac->run($lc, $action, $request);
		$html = $router->url_rewrite($html);
		echo $html;
	}
}
new Application();
And:

Code: Select all

$lc = new LocalConfig();
if($lc->rewrite_method == '404') {
	$router = $lc->get('router_404');
} else {
	$router = $lc->get('router');
}
$request = $lc->get('request');
list($ac_name, $action) = $router->map($request);
$ac = $lc->get('ac_name');
if(!$ac) {
	$ac = $lc->get('error_controller');
	$action = 'controller_not_found';
}
$html = $ac->run($lc, $action, $request);
$html = $router->url_rewrite($html);
echo $html;
For example, a simple difference is that the first example adds the overhead of an object instantiation and function call every request. So that is a slight performance negative. What are the security, design, maintainablity and other issues.

Posted: Sun Jul 08, 2007 3:41 pm
by Chris Corbyn
If you dump all code in a procedural fashion in the index.php file then say for example you decide to allow elements of your application to be interacted with using CLI you'd have to write a new equivalent of index.php with CLI specific launch settings. If you encapsulate that code into a class somewhere then you can extend that class and override selected parts for CLI.

Another consideration is that if you're going to start writing code in your index.php file like that, where do you draw the line between what's allowed in the global scope and what isn't? Is it perhaps keeping the tin open to ad-hoc elements of code being dumped into the file?

I agree that it's worth discussing the nitty-gritty of what exactly is wrong with using globals during the dispatch process though... when you think about it, most of the considerations you come up with are not particularly relevant.

Posted: Sun Jul 08, 2007 3:46 pm
by stereofrog
arborint wrote: Again the question is not if you think so.
Of course it is. ;) We are here to share our personal opinions. Nobody claims to possess the absolute truth.
So what are the real differences related to security, design and maintenance between the following index.php scripts?
Sorry, I don't see your point. Are you advocating a procedural approach? You can not be serious. ;)

Posted: Sun Jul 08, 2007 3:53 pm
by Chris Corbyn
stereofrog wrote:Sorry, I don't see your point. Are you advocating a procedural approach? You can not be serious. ;)
I think ~arborint is trying to encourage a discussion that gets right down to the core principals surrounding why *not* to use globals. Nobody's saying you should, or should not, but without being able to answer *why* it's bad to use them you have ton wonder why ;)

I can think of another reason though. Unit Testing is easier if it's done my method invocation.

Posted: Sun Jul 08, 2007 4:09 pm
by Christopher
stereofrog wrote:Of course it is. ;) We are here to share our personal opinions. Nobody claims to possess the absolute truth.
Yes we express our opinions, but the validity of those opinions are based on the facts that back them up.
stereofrog wrote:Sorry, I don't see your point. Are you advocating a procedural approach? You can not be serious. ;)
But it is your exact code! Your code is procedural within the constructor. So that is not really and argument. That is why I asked what the real difference is. I am honestly not trying to be an ass. I think this is an important discussion that can help us understand the current best practice.