I am using my own home grown PHP framework and it is heavily based on components mostly from pear and Zend but lately there are some better components coming up at Composer
As my apps are growing it becomes harder to switch between components, and I am wondering if there is a way I can design my programs differently. In a way that would allow me to use components like the opposite of abstract classes.
I am thinking there should be a way for me to create my own classes, which in turn just hook in to pear or zend and use those classes like as if they wore interfaces or abstract classes. Of course they would be doing the actual work and I would just link to them.
Hypothetically if I have been using pear Config/Lite, which can only work with ini and array files, and now I like to switch to pear config or Zend config to get the benefit of saving the data in a database then there should be an easy way to switch without changing all my code since what they implement is exactly the same thing.
I am asking because I been using pears Net/URL/Mapper, which isn't bad but I found something that would also take care of the dispatching, and is being actively developed. Also I am sure that this kind of situation will come up again and again.
You want to look for something like the facade design pattern, or just use delegation / composition. However beware, using something like a facade can lead to a lot of unneeded complexity as you add layers of abstraction. I recommend you read some php design patterns, especially delegation / composition of objects to get a feel for how that might fit your case.
You should use composition for this IMO. Have the classes in your library expose their own public interface, which the rest of your code depends on. If you ever change the underpinnings of a component from say PEAR to Zend, just ensure all the original public methods still honor the previous version and you should be golden. You can formalize these interfaces with the interface keyword if you wish, but that is beyond the scope of this answer ;)
Related
In Java EE, I would use Spring to instantiate and reuse my services. Now I've created a small framework in PHP to support my application, using services, repositories and DAOs.
However, how can I instantiate, but more importantly, re-use these objects, without having to instantiate a new object every time?
It's tempting to just start using singletons, but then my code would turn into a mess pretty quickly.
In fact, I'm having trouble with using good OO practices and design patterns with PHP in general. Is there any good resource on this?
I personally use the Singleton approach in PHP all the time and in my opinion, my code isn't a mess - yet. A lot of other projects (e.g. Typo3) use global arrays to store objects. I don't like that approach, as an array item can be easily overwritten.
But if you are using namespaces and order your project files in folders (like in Java), the Singleton approach is pretty clean. And with a getInstance() method, you're much more on the safe side than with $globalArray['myInstance'].
I believe that what You're looking for is the Service container (IoC container). There are some PHP implementations out there that You can use in Your application. The one I've used so far is called the Dependency Injection component provided by the Symfony framework. The documentation can be found here.
There is another implementation available in PHP I'm aware of called Zend DI. It's provided by another big PHP framework since version 2.0, which is still in the beta stage though. Some examples on the Zend DI component can be found here.
In php we use the lazy loading technique used also by important framewokr
You need to build an autoload strategy, because in php you should always include the file in which the class is written to instantiate an object
Symfony uses the namespaces so for example
\DB\Repository\Classes\Product
for example is registered in a
/DB/Repository/Classes/Product.php file
and you make directly a
$product = new Product()
Without taking care of including file and other kind of operations like this.
I'm currently developing a framework which uses an object of a Core class (this class has huge functionality & makes the framework working). The framework follows MVC architecture & has loosely coupled Model, Control, View classes. Theses classes need a reference to the Core class heavily. What I've done so far is: creating single object of the Core class & referencing to it by PHP keyword global in Model, Control, View classes.
I don't like using this approach mainly because:
This way is not true object oriented way in my sense
The IDE (netbeans) can't provide documentation to the object of the Core class - a pain for developers who will be using this framework.
I'm really worried about performance issues - have no idea whether global is slower or whatever.
I've searched & did not find any information regarding performance issue. I've also searched stackoverflow & found Does using global create any overhead? & The advantage / disadvantage between global variables and function parameters in PHP? etc links but they don't contain much information. Right now my main concern is performance, so please help.
I must agree with NevilleK, that you Core` class sounds line an God Object antipattern.
And for anyone dumb enough to suggest use of singletons/registries i would suggest to do a little research on the subject. They create the same global state as your classical global variables.
Global state is not so much matter of performance ( though in php it has some minor impact ), but it created untestable and tightly coupled code.
You really should look into the Dependency Injection. That might show you another way , which does not require to have such a Core class in your code.
Some additional videos for you:
Global State and Singletons
Don't Look For Things!
Advanced OO Patterns
Cake is a Lie
Clean Code: Arguments
I've solved a similar problem in Agile Toolkit by creating a different pattern for adding object and using it system-wide. This passes a property to a newly created objects called "api" which always references Application class.
Application class is not really a God class but it delegates all sorts of functionality to system controllers, pages etc. This screencast explains how the very basic objects are structured, it might be something you are also looking for:
http://www.youtube.com/watch?v=bUNEHqYVOYs
Firstly, whilst you are concerned with performance, you may want to read http://en.wikipedia.org/wiki/God_object first - your "core" class sounds like a "God object", which is a fairly well-established anti pattern.
In terms of performance - the best way to find out is to test it. If you're writing a framework, I'm assuming you're writing unit tests to validate it's behaviour; it's not hard to extend that unit testing to include simple performance metrics. You might also invest in test scripts using JMeter or similar to exercise a "reference implementation" of a few pages built using the framework. You'll get far better information on your specific situation from doing this than by trying to optimize the design based on Stack Overflow's collective knowledge of the general way things work.
In general, I'd say that having a global class shouldn't impact performance too much, as long as it isn't doing much work. Simply loading the class into memory, parsing it, etc. does have a performance impact - but it's not likely to be measurably slower than any other routes you might take.
If, however, your "core" class does lots of initialization logic when it's accessed by the page, it's obviously going to impact performance.
whenever i use a open source library eg. Doctrine i always ending up coding a class (so called Facade) to use the Doctrine library.
so next time i want to create a user i just type:
$fields = array('name' => 'peter', 'email' => 'peter#gmail.com');
Doctrine_Facade::create_entity($entity, $fields);
then it creates an entity with the provided information.
so i guess, all coders will create their own "Facade".
i wonder how usual it is with open source Facades to download and interact with the open source libraries? is this rare cause i haven't seen any of these. in some frameworks i have seen them called plugins, eg. plugins for twitter api or facebook api.
so whenever you download a library, should you search for plugins/facades on the net, or is it better to just try coding your own? i just thought it would be great for everyone not to reinvent the wheel.
thanks.
Let us say it is not just about Factories, let us say, you really often write Facades for libraries you use. What is the point? Why are you doing it? The point is, that you use the library in a specific way. If the Facade you write was universal and everybody tended to write something like that, the Facade would be surely part of the library. So the reason why it is not and why you want to write it is, that you use it in a very specific way, which is specific to you application of the library. So you transition from the abstraction of the library to the abstraction of your application. This can remove much of the complexity of the library from your application, but it also restricts the way in which you use the library. So, if you understood my point, you might be convinced, that there is no point in releasing each Facade for certain way in which the library can be used. However, sometimes, when we talk about a big influential library, which is combined with some other libraries and together comprise abstraction, which can be widely used, it may happend that new library will be created.
The aim of a Facade is to (quoting)
Provide a unified interface to a set of interfaces in a subsystem. Facade defines a higher-level interface that makes the subsystem easier to use.
Wrap a complicated subsystem with a simpler interface.
While the above can be said to apply to your example, it feels much more like an AbstractFactory to me. You might want to rename it to EntityFactory without the Doctrine part, because the fact that it uses Doctrine internally is an implementation detail. For the public facing API of the Factory, it doesn't matter. Maybe you want to change from Doctrine to Propel at a later time and then you just have to change the code inside the class, but not the API.
You might also be interested in the Gateway pattern.
But to answer your question whether this is a common approach: yes, I think so. Abstraction makes code easier to understand and easier to maintain. But since the API of the facade/gateway - whatever applies - is usually determined by what the application does, it rarely can be reused, so I doubt you will find readymade facades/gateways on the web.
I've been using the CodeIgniter framework, however after learning Java and awesome features like Interfaces, Abstract classes, packages, and that PHP 5 also supports most of these features, I'm ready to graduate and build a real OO framework in PHP which uses all of these features (including namespaces), so I can build much more elegant designs.
What I'm thinking of is that rather than everything in the system sharing a single $this-> object like its done in CodeIgniter, e.g:
$this->load->model('box');
$this->box->something();
You would do the following to load the Box model and to call its something() method.
$box = new Framework\Models\Box();
$box->something();
Or the following
abstract class BaseController
{
public function getModel($name)
{
$model = new Framework\Models\$model(); //Is this valid code?
return $model;
}
}
class MyController extends BaseController
{
public function index()
{
$box = $this->getModel('box');
$box->something();
}
}
Are there any suggestions/pointers for building this, such as which minimum system classes I would need for the framework, what namespaces I should have, or any other features?
One thing I've noticed is that a framework is usually built for a specific purpose. Generic frameworks (like CodeIgniter) are good for smaller sites and getting things up and running quickly. However once you have specific things, which fall outside of the generic framework building your own does become a reality.
The only thing I would suggest is to be consistent. That is relentlessly consistent. If you decide to name things in camelCase then don't deviate from that. Or if you decide to use the NounVerb convention of naming methods i.e. spaceJump then don't switch to jumpSpace even if it 'sounds' better at the time.
Choose how you'll accept parameters and be consistent on that. Will you accept only parameters or associative arrays of parameters? Choose and stick with it.
I would also not over-engineer before you've written anything. The consistency thing will take you pretty far before you'll need to refactor... but I wouldn't be afraid to do that as well. (A unit test or two should ease those fears).
Yup, there's usually no right or wrong way to do things as long as you're consistent. Did I mention...
Be Consistent!
A lot of experience is needed to build a technical framework (no offense) and there are already 1'000's of CMS/basic objects (session management, ORM, etc.) framworks/libraries.
Instead of wasting precious time (no offense again), you better have to:
Evaluate and select the framework that better suits your needs (some have a really good OO architecture).
Learn will using this good framework.
Build your own OO business/application framework. (This is where you can learn, differentiate and create value).
You can build your own but why not make use of the vast libraries included with frameworks available and if required extend their functionality.
Why don't you take a look at the Zend framework.
It's fairly quick to get started and includes a lot of useful libraries and classes as standard. It's good for personal projects if your just looking to gain more experience with OOP.
http://framework.zend.com/
I would look at Kohana. It came out of CodeIgnitor, and loading Models etc is done just the way you proposed.
Check out their core features, many of which relate directly to your question (I've highlighted those):
How is Kohana Different?
Although Kohana reuses many common design patterns and concepts, there are some things that make Kohana stand out:
Community, not company, driven. Kohana development is driven by a team of dedicated people that need a framework for fast, powerful solutions.
Strict PHP 5 OOP. Offers many benefits: visibility protection, automatic class loading, overloading, interfaces, abstracts, and singletons.
Extremely lightweight. Kohana has no dependencies on PECL extensions or PEAR libraries. Large, monolithic libraries are avoided in favor of optimized solutions.
GET, POST, COOKIE, and SESSION arrays all work as expected. Kohana does not limit your access to global data, but offers filtering and XSS protection.
True auto-loading of classes. True on-demand loading of classes, as they are requested in your application.
No namespace conflicts. All classes are suffixed to allow similar names between components, for a more coherent API.
Cascading resources offer unparalleled extensibility. Almost every part of Kohana can be overloaded or extended without editing core system files. Modules allow multi-file plugins to be added to your application, transparently.
Library drivers and API consistency. Libraries can use different "drivers" to handle different external APIs transparently. For example, multiple session storage options are available (database, cookie, and native), but the same interface is used for all of them. This allows new drivers to be developed for existing libraries, which keeps the API consistent and transparent.
Powerful event handler. Observer-style event handlers allow for extreme levels of customization potential.
Rapid development cycle. Rapid development results in faster response to user bugs and requests.
I have learned how to use classes in PHP and so far I have only really found one useful application for them. I created a user class to preform various tasks relating to users in my web application such as output the avatar, show number of messages ect.
Aside from this example, what are some other useful ways to utilize classes in a practical sense?
I use a database class all the time.
Here are a couple examples:
http://www.massless.org/_tests/phpdb/
http://slaout.linux62.org/php/index.html
http://www.tonymarston.net/php-mysql/databaseobjects.html
It's a really good idea to read other people's code and see how they have separated things into classes. Look at some PEAR modules or a framework ( Zend, Symfony, Cake ).
Any time you can define a 'thing' that 'does stuff', you've got a candidate for defining an object. Two concrete examples, from the PHP standard library, that immediately pop to mind are :
Numerous database modules use objects for connections, queries & results.
The DateTime class encapsulates a generic concept of time with input & output formatting, timezone conversions & date arithmetic.
The thing is, Object Oriented Programming is a big idea - you can solve almost any programming problem in an object oriented way.
I've built an utility class that humanizes the use of the mail() function, which I tend to use quite a lot.
By using classes (e.g. PEAR packages mentioned above, others), you are able to leverage code that has already been written and tested to perform common tasks.
Helps you to not reinvent the wheel, too.
I would highly recommend learning about [design patterns][1]. Many of them make good use of classes and solve common programming problems. In particular the Factory and Abstract Factory patterns are a good place to start.
There is also an excellent book called PHP Hacks that has a chapter about implementing a host of different patterns in PHP, so you might want to check that out.
Also, explore some of these built-in objects in PHP to see how they work and get more ideas:
PDO
ArrayObject
SimpleXMLElement
DirectoryIterator
[1]: http://en.wikipedia.org/wiki/Design_pattern_(computer_science)"design patterns"
I created a user class to preform various tasks relating to users in my web application such as output the avatar, show number of messages ect.
Check out http://en.wikipedia.org/wiki/Cohesion_(computer_science)
Your example sounds like Logical cohesion.
Aim for functional cohesion. Each class does a particular task, and make classes as generic as possible and you'll find you can reuse them over and over.
A great example of that, is Symfony's sfParameterHolder:
http://www.symfony-project.org/book/1_2/02-Exploring-Symfony-s-Code#chapter_02_sub_parameter_holders
Symfony uses it to hold variables for view templates (in a MVC), to store request parameters in the web request object (itself a class that represents all request parameters dutifully stripped of backslashes etc), in the sfUser class to store all the parameters that eventually go in the $_SESSION etc etc.
Download Symfony's "sandbox", go into the /lib/symfony/ folder and learn from it. It"s complex but the code imho is very clean.
http://www.symfony-project.org/installation
Zend is nice too, but the number of include files mayb be overwhelming and I am personally not fond of their naming conventions, in particular using underscore prefixes.