can classes be too big? - php

I'm planning on adding Steam-like achievement to my gaming site. The calculations will be handled by scheduled cron, with the results stored in a typical MySQL database. For convenience's sake I was considering just dumping all the various calculation methods into one giant STATS class. These are methods that would never be called on by any other aspects of the site, only for this particular achievements cron.
Do I need to worry about this class growing too large? It's about 2k LOC now, but there's no reason it couldn't expand to 10k, or 50k, over time...
This is on shared hosting btw, so memory constraints do exist to some degree...

Yes, classes can definitely grow too big.
When that happens, it is usually a sign of misplaced responsibilities. Classes that do too much are an AntiPattern called The Blob aka God class. Those classes violate the Single Responsibiliy Principle and will have a negative impact on coupling and cohesion. That in turn will make your application less reusable and harder to extend and maintain.
To divide Responsibilities properly, consider which data you can logically group together and then make that into a separate object. The same is true for overlongy long methods. Divide them. If you find that a particular subroutine is taking a lot of space in an object, see if you can promote that code to a Strategy encapsulating that algorithm.
In your specific case, it sounds like you could benefit from a Command Pattern, e.g. have one StatsCommander that uses many StatCommands (which are Strategies). That keeps the logic required to get the various stats cleanly separated from each other. When you need to add a new Stat, just add a new Strategy/Command.

Why do you think that the class would grow too large?
And if you think that multiple instance of the same class could used, you can either make all those methods as static (So all the functions will have only one instance.)
Or create only one instance of it and let others access the same instance by using & before the original instance.
Or you can consider using a Singleton Pattern.
EDIT
You can consider creating small classes, and making them members of your now big class.
This will keep your code organized and classes divided accordingly.

When writing a class, you ask yourself "Is this function required as an instance? Or as a global function", This is best described by an example:
class House {
private $door;
private $window;
private static $adverb;
public function __construct(Door $door, Window $window) {
$this->door = $door;
$this->window = $window;
}
public function placeNewDoor($door) {
$this->door = $door;
}
public function placeNewWindow() {
$this->window = $window;
}
public static function advertiseNeighborhood() {
echo "Advertisment! " . self::$adverb;
}
}
There would be many houses, each would probably have a Door and a Window. So each of these get an instance method/property. However, you only advertise your Neighborhood once (not per house), so that function is static and will be accessed by House::advertiseNeighborhood.
Why did I post this example? If there's a function which doesn't required being instantiated, they should remain static. It will prevent memory leaking when instantiating multiple objects.
As for your actual question, it's perfectly acceptable to have a very large class, just make sure you don't overuse your memory.

By Creating a Class bigger you only have drawback of leaking memory as most of the functions will not used and will remain sit in the memory till object exist, but the point that if you are creating very few objects like Singleton than it is perfect.
A very good fact is that no mater how many function do you have in a class your execution of single function will take same time as declaring a single function in a class and use it.
What I would suggest you to implement inheritance between classes, code organization mater too, Make a OOD for it. So, you would take less time to modify and managing the code. Take the advantage of encapsulation and polymorphism :)

Related

Value object encapsulating domain logic

We use DDD in our project in financial domain.
I have a value object:
final class VatRate extends DecimalNumber {
}
abstract class DecimalNumber
{
public static function fromString(string $number): static
{
return new static(\Brick\Math\BigDecimal:of($number));
}
}
I need to create zero vat rate in domain aggregate.
Both aggregate and VatRate exists in domain layer.
This is the way I am doing it:
$zeroVat = VatRate::fromString('0.0');
I was told it is not right. I should doing it this way:
final class VatRate extends DecimalNumber {
public static function zero(): self
{
return self::fromString('0.0');
}
}
$zeroVat = VatRate::zero();
What is the point to encapsulate domain logic in this case?
The only response I had is that it is more "Domain" way of doing things.
When I need to create VAT rate 0.20 then should I similarly create static method VatRate::zeroPointTwenty()?
What are the pros and cons of both solutions?
What is the point to encapsulate domain logic in this case?
"Information hiding" -- see Parnas 1971.
Basic idea, by creating a seam between the code that knows how to use a zero and the code that knows how to create a zero, we reduce the amount of code directly impacted if we need to change the underlying data structure or initialization routine.
In addition, by introducing a seam, you create the opportunity to introduce an intention revealing name.
If your development environment has a decent indexer, you'll easily be able to find usages of zero without getting your results cluttered with a bunch of other calls to fromString with different arguments.
Another way of thinking about this: strings are not "of the financial domain", they are the general purpose data structure that this implementation just happens to use. Therefore, they don't "belong" in the domain specific language we are creating to describe to programmers how this code does something useful to the business.
There are lots of ways we can tell the computer to do the right thing. The goal is to use that freedom to better communicate with the next programmer to come along.
What are the cons? It's trade offs all the way down, right?
The main downsides are this: that it's another piece of code to keep track of. You've got to find a good place to put it, and make sure that everybody who needs it can find it. If you've got a bunch of "unit" test zealots around, then maybe they are going to insist on a bunch of testing ceremony to go with this new one-line-function.
It's not "free" - especially if it isn't your current habit. It's extra work we do today, while all of the context is fresh in our minds, so that the people who have to work in this code later have an easier time of it.

Why is the amount of visibility on methods and attributes important?

Why shouldn't one leave all methods and attributes accessible from anywhere (i.e. public)?
Can you give me an example of a problem I can run into if I declared an attribute as public?
Think of McDonald's as an object. There's a well known public method to order a BigMac.
Internally there's going to be a few zillion other calls to actually GET the materials for making that Bigmac. They don't want you to know how their supply chain works, so all you get is the public Gimme_a_BigMac() call, and would never ever allow you to get access to the Slaughter_a_cow() or Buy_potatoes_for_fries() methods.
For your own code, that no one will ever see, go ahead and leave everything public. But if you're doing a library for others to reuse, then you go and protect the internal details. That leaves McDonald's free to switch to having Scotty beam over a patty rather than having to call up a Trucking company to deliver the meat by land. The end-user never knows the difference - they just get their BigMac. But internally everything could fundamentally change.
Why shouldn't one leave all methods and attributes accessible from anywhere (i.e. public)?
Because that is far too expensive.
Every public method that I make has to be carefully designed and then approved by a team of architects, it has to be implemented to be robust in the face of arbitrarily hostile or buggy callers, it has to be fully tested, all problems found during testing have to have regression suites added, the method has to be documented, the documentation has to be translated into at least twelve different languages.
The biggest cost of all though is: the method has to be maintained, unchanged, forever and ever, amen. If I decide in the next version that I didn't like what that method did, I can't change it because customers now rely on it. Breaking backwards compatibility of a public method imposes costs on users and I am loathe to do that. Living with a bad design or implementation of a public method imposes high costs on the designers, testers and implementers of the next version.
A public method can easily cost thousands or even tens of thousands of dollars. Make a hundred of them in a class and that's a million dollar class right there.
Private methods have none of those costs. Spend shareholder money wisely; make everything private that you possibly can.
Think of visibility scopes as inner circles of trust.
Take yourself as an example, and think about what activities are public and what are private or protected. There are number of things that you are not delegating for anybody to do on your behalf. There are some that are fine others to trigger and there are some with limited access.
Similarly, in programming, scopes give you tools for creating different circles of trust. Additionally, making things private/protected, give you more control on what's happening. For example, you can allow 3rd-party plugins that can extend some of your code, while they can be limited to the scope of how far they can go.
So, to generalize, scopes give you the extra level of security and keeps things more organized that they would be otherwise.
Because that violates the concept of encapsulation, a key tenet of OOP.
A risk you run, you say?
<?php
class Foo
{
/**
* #var SomeObject
*/
public $bar;
}
Your code states that $bar should contain an object instanceof SomeObject. However, anyone using your code could do
$myFoo->bar = new SomeOtherObject();
... and any code relying on Foo::$bar being a SomeObject would break. With getters and setters and protected properties, you can enforce this expectation:
<?php
class Foo
{
/**
* #var SomeObject
*/
protected $bar;
public function setBar(SomeObject $bar)
{
$this->bar = $bar;
}
}
Now you can be certain that any time Foo::$bar is set, it will be with an object instanceof SomeObject.
By hiding implementation details, it is also preventing an object from getting into an inconsistent state.
Here is an contrived example of a stack (pseudo code).
public class Stack {
public List stack = new List();
public int currentStackPosition = 0;
public String pop() {
if (currentStackPosition-1 >= 0) {
currentStackPosition--;
return stack.remove(currentStackPosition + 1);
} else {
return null;
}
}
public void push(String value) {
currentStackPosition++;
stack.add(value);
}
}
If you make both variables private the implementation works fine. But if public you can easily break it by just setting an incorrect value for currentStackPosition or directly modifying the List.
If you only expose the functions you provide a reliable contract that others can use and trust. Exposing the implementation just make it a thing that might work of nobody messes with it.
Encapsulation is not needed in any language, but it's useful.
Encapsulation is used to minimise the number of potential dependencies with the highest probability of change propagation also it helps preventing inconsistencies :
Simple example: Assume we made a Rectangle class that contained four variables - length, width, area, perimeter. Please note that area and perimeter are derived from length and width (normally I wouldn't make variables for them), so that changing length would change both area and perimeter.
If you did not use proper information hiding (encapsulation), then another program utilizing that Rectangle class could alter the length without altering the area, and you would have an inconsistent Rectangle. Without encapsulation, it would be possible to create a Rectangle with a length of 1 and a width of 3, and have an area of 32345.
Using encapsulation, we can create a function that, if a program wanted to change the length of the rectangle, that the object would appropriately update its area and perimeter without being inconsistent.
Encapsulation eliminates the possibilities for inconsistency, and shifts the responsibility of staying consistent onto the object itself rather than a program utilizing it.
However at the same time encapsulation is sometimes a bad idea, and motion planning and collision (in game programming) are areas where this is particularly likely to be the case.
the problem is that encapsulation is fantastic in places where it is needed, but it is terrible when applied in places where it isn’t needed like when there are global properties that need to be maintained by a group of encapsulation, Since OOP enforced encapsulation no matter what, you are stuck. For example, there are many properties of objects that are non-local, for example, any kind of global consistency. What tends to happen in OOP is that every object has to encode its view of the global consistency condition, and do its part to help maintain the right global properties. This can be fun if you really need the encapsulation, to allow alternative implementations. But if you don’t need it, you end up writing lots of very tricky code in multiple places that basically does the same thing. Everything seems encapsulated, but is in fact completely interdependent.
Well, in fact you can have everything public and it doesn't break encapsulation when you state clearly, what is the contract, the correct way to use objects. Maybe not attributes, but methods are often more hidden than they have to be.
Remember, that it is not you, the API designer, that is breaking the encapsulation by making things public. It is the users of the class that can do so, by calling internal methods in their application. You can either slap their hands for trying to do so (i.e. declaring methods private), or pass the responsibility to them (e.g. by prefixing non-API methods with "_"). Do you really care whether someone breaks his code by using your library the other way you advice him to do? I don't.
Making almost everything private or final -- or leaving them without API documentation, on the other hand -- is a way of discouraging extendability and feedback in open source. Your code can be used in a ways you even didn't think of, which might not be the case when everything is locked (e.g. sealed-by-default methods in C#).
The only problem you can run into is that people will see you as "uncool" if you don't use Private or Protected or Abstract Static Final Interface or whatever. This stuff is like designer clothes or Apple gadgets - people buy them not because they need to, but just to keep up with others.
Yes, encapsulation is an important theoretical concept, but in the practice "private" and friends rarely make sense. They might make some sense in Java or C#, but in a scripting language like PHP using "private" or "protected" is sheer stupid, because encapsulation is invented to be checked by a compiler, which doesn't exist in PHP. More details.
See also this excellent response and #troelskn and #mario comments over here
The visibility is just something that you can use for your own good, to help you not break your own code. And if you use it right, you will help others (who are using your code) that don't break their own code (by not using your code right).
The simplest, widely known example, in my opinion is the Singleton pattern. It's a pattern, because it's a common problem. (Definition of pattern from Wikipedia:
is a formal way of documenting a solution to a design problem
Definition of the Singleton pattern in Wikipedia:
In software engineering, the singleton pattern is a design pattern used to implement the mathematical concept of a singleton, by restricting the instantiation of a class to one object. This is useful when exactly one object is needed to coordinate actions across the system.
http://en.wikipedia.org/wiki/Singleton_pattern
The implementation of the pattern uses a private constructor. If you don't make the constructor private, anyone could mistakenly create a new instance, and break the whole point of having only one instance.
You may think that the previous answers are "theoretical", if you use public properties in Doctrine2 Entities, you break lazy loading.
To save you from yourself!
There's been some excellent answers above, but I wanted to add a bit. This is called principle of least privilege. With less privilege, less entities have authority to break things. Breaking things is bad.
If you follow the principle of least privilege, the principle of least knowledge (or Law of Demeter) and single responsibility principle aren't far behind. Since your class you wrote to download the latest football scores has followed this principle, and you have to poll it's data instead of it being dumped straight to your interface, you copy and paste the whole class into your next project, saving development time. Saving development time is good.
If you're lucky, you'll be coming back to this code in 6 months to fix a small bug, after you've made gigaquads of money from it. Future self will take prior self's name in vain for not following the above principles, and he will fall victim to a violation of the principle of least astonishment. That is, your bug is a parse error in the football score model, but since you didn't follow LOD and SRP, you're astonished at the fact that you're doing XML parsing inline with your output generation. There are much better things in life to be astonished by than the horrificness of your own code. Trust me, I know.
Since you followed all the principles and documented your code, you work two hours every Thursday afternoon on maintenance programming, and the rest of the time surfing.

PHP: Best way to write a Class where its functions can be added infinitely "as you go"?

Right now I have a normal class like this
class MyClass
{
function myfunc1 () { }
function myfunc2 () { }
}
However the filesize of MyClass is becoming large as I add more functions along the way.
Everytime I use MyClass, only selected functions will be used by each individual application.
What is the best way to minimize the filesize of MyClass?
Is it advisable to separate each functions in a separate file, and just include them if they're needed? If yes, how do you implement it in terms of code?
Infinitely growing classes generally lead to god objects, which are considered an anti-pattern in OO software development. When designing a class, first think about what this class is supposed to do for you, then you can design it's interface (aka public methods). If you have a good design, it's unlikely your class grows by much later on. If it does, it's time for a refactorization and breaking the class into smaller pieces.
You want to split functionality up in different classes and files. For example, have 1 file per class, and have a single class have a clear purpose instead of one big god class.
You probably shouldn't use several files for the same class. If the class is getting to big to manage, it's likely that you should be using subclasses.

Is there a use-case for singletons with database access in PHP?

I access my MySQL database via PDO. I'm setting up access to the database, and my first attempt was to use the following:
The first thing I thought of is global:
$db = new PDO('mysql:host=127.0.0.1;dbname=toto', 'root', 'pwd');
function some_function() {
global $db;
$db->query('...');
}
This is considered a bad practice. After a little search, I ended up with the Singleton pattern, which
"applies to situations in which there needs to be a single instance of a class."
According to the example in the manual, we should do this:
class Database {
private static $instance, $db;
private function __construct(){}
static function singleton() {
if(!isset(self::$instance))
self::$instance = new __CLASS__;
return self:$instance;
}
function get() {
if(!isset(self::$db))
self::$db = new PDO('mysql:host=127.0.0.1;dbname=toto', 'user', 'pwd')
return self::$db;
}
}
function some_function() {
$db = Database::singleton();
$db->get()->query('...');
}
some_function();
Why do I need that relatively large class when I can do this?
class Database {
private static $db;
private function __construct(){}
static function get() {
if(!isset(self::$db))
self::$db = new PDO('mysql:host=127.0.0.1;dbname=toto', 'user', 'pwd');
return self::$db;
}
}
function some_function() {
Database::get()->query('...');
}
some_function();
This last one works perfectly and I don't need to worry about $db anymore.
How can I create a smaller singleton class, or is there a use-case for singletons that I'm missing in PHP?
Singletons have very little - if not to say no - use in PHP.
In languages where objects live in shared memory, Singletons can be used to keep memory usage low. Instead of creating two objects, you reference an existing instance from the globally shared application memory. In PHP there is no such application memory. A Singleton created in one Request lives for exactly that request. A Singleton created in another Request done at the same time is still a completely different instance. Thus, one of the two main purposes of a Singleton is not applicable here.
In addition, many of the objects that can conceptually exist only once in your application do not necessarily require a language mechanism to enforce this. If you need only one instance, then don't instantiate another. It's only when you may have no other instance, e.g. when kittens die when you create a second instance, that you might have a valid Use Case for a Singleton.
The other purpose would be to have a global access point to an instance within the same Request. While this might sound desirable, it really isnt, because it creates coupling to the global scope (like any globals and statics). This makes Unit-Testing harder and your application in general less maintainable. There is ways to mitigate this, but in general, if you need to have the same instance in many classes, use Dependency Injection.
See my slides for Singletons in PHP - Why they are bad and how you can eliminate them from your applications for additional information.
Even Erich Gamma, one of the Singleton pattern's inventors, doubts this pattern nowadays:
"I'm in favor of dropping Singleton. Its use is almost always a design smell"
Further reading
How is testing the registry pattern or singleton hard in PHP?
What are the disadvantages of using a PHP database class as a singleton?
Database abstraction class design using PHP PDO
Would singleton be a good design pattern for a microblogging site?
Modifying a class to encapsulate instead of inherit
How to access an object from another class?
Why Singletons have no use in PHP
The Clean Code Talks - Singletons and Global State
If, after the above, you still need help deciding:
Okay, I wondered over that one for a while when I first started my career. Implemented it different ways and came up with two reasons to choose not to use static classes, but they are pretty big ones.
One is that you will find that very often something that you are absolutely sure that you'll never have more than one instance of, you eventually have a second. You may end up with a second monitor, a second database, a second server--whatever.
When this happens, if you have used a static class you're in for a much worse refactor than if you had used a singleton. A singleton is an iffy pattern in itself, but it converts fairly easily to an intelligent factory pattern--can even be converted to use dependency injection without too much trouble. For instance, if your singleton is gotten through getInstance(), you can pretty easily change that to getInstance(databaseName) and allow for multiple databases--no other code changes.
The second issue is testing (And honestly, this is the same as the first issue). Sometimes you want to replace your database with a mock database. In effect this is a second instance of the database object. This is much harder to do with static classes than it is with a singleton, you only have to mock out the getInstance() method, not every single method in a static class (which in some languages can be very difficult).
It really comes down to habits--and when people say "Globals" are bad, they have very good reasons to say so, but it may not always be obvious until you've hit the problem yourself.
The best thing you can do is ask (like you did) then make a choice and observe the ramifications of your decision. Having the knowledge to interpret your code's evolution over time is much more important than doing it right in the first place.
Who needs singletons in PHP?
Notice that almost all of the objections to singletons come from technical standpoints - but they are also VERY limited in their scope. Especially for PHP. First, I will list some of the reasons for using singletons, and then I will analyze the objections to usage of singletons. First, people who need them:
- People who are coding a large framework/codebase, which will be used in many different environments, will have to work with previously existing, different frameworks/codebases, with the necessity of implementing many different, changing, even whimsical requests from clients/bosses/management/unit leaders do.
See, the singleton pattern is self inclusive. When done, a singleton class is rigid across any code you include it in, and it acts exactly like how you created its methods and variables. And it is always the same object in a given request. Since it cannot be created twice to be two different objects, you know what a singleton object is at any given point in a code - even if the singleton is inserted to two, three different, old, even spaghetti codebases. Therefore, it makes it easier in terms of development purposes - even if there are many people working in that project, when you see a singleton being initialized in one point in any given codebase, you know what it is, what it does, how it does, and the state it is in. If it was the traditional class, you would need to keep track of where was that object first created, what methods were invoked in it until that point in the code, and its particular state. But, drop a singleton there, and if you dropped proper debugging and information methods and tracking into the singleton while coding it, you know exactly what it is. So therefore, it makes it easier for people who have to work with differing codebases, with the necessity of integrating code which was done earlier with different philosophies, or done by people who you have no contact with. (that is, vendor-project-company-whatever is there no more, no support nothing).
- People who need to work with third-party APIs, services and websites.
If you look closer, this is not too different than the earlier case - third-party APIs, services, websites, are just like external, isolated codebases over which you have NO control. Anything can happen. So, with a singleton session/user class, you can manage ANY kind of session/authorization implementation from third-party providers like OpenID, Facebook, Twitter and many more - and you can do these ALL at the same time from the SAME singleton object - which is easily accessible, in a known state at any given point in whatever code you plug it into. You can even create multiple sessions to multiple different, third-party APIs/services for the SAME user in your own website/application, and do whatever you want to do with them.
Of course, all of this also can be tone with traditional methods by using normal classes and objects - the catch here is, singleton is tidier, neater and therefore because of that manageable/testable easier compared to traditional class/object usage in such situations.
- People who need to do rapid development
The global-like behavior of singletons make it easier to build any kind of code with a framework which has a collection of singletons to build on, because once you construct your singleton classes well, the established, mature and set methods will be easily available and usable anywhere, anytime, in a consistent fashion. It takes some time to mature your classes, but after that, they are rock solid and consistent, and useful. You can have as many methods in a singleton doing whatever you want, and, though this may increase the memory footprint of the object, it brings much more savings in time required for rapid development - a method you are not using in one given instance of an application can be used in another integrated one, and you can just slap a new feature which client/boss/project manager asks just by a few modifications.
You get the idea. Now lets move on to the objections to singletons and
the unholy crusade against something that is useful:
- Foremost objection is that it makes testing harder.
And really, it does to some extent, even if it can be easily mitigated by taking proper precautions and coding debugging routines into your singletons WITH the realization that you will be debugging a singleton. But see, this isnt too different than ANY other coding philosophy/method/pattern that is out there - it's just that, singletons are relatively new and not widespread, so the current testing methods are ending up comparably incompatible with them. But that is not different in any aspect of programming languages - different styles require different approaches.
One point this objection falls flat in that, it ignores the fact that the reasons applications developed is not for 'testing', and testing is not the only phase/process that goes into an application development. Applications are developed for production use. And as I explained in the 'who needs singletons' section, singletons can cut a GREAT deal from the complexity of having to make a code work WITH and INSIDE many different codebases/applications/third-party services. The time which may be lost in testing, is time gained in development and deployment. This is especially useful in this era of third-party authentication/application/integration - Facebook, Twitter, OpenID, many more and who knows what's next.
Though it is understandable - programmers work in very different circumstances depending on their career. And for people who work in relatively big companies with defined departments tending different, defined software/applications in a comfortable fashion and without the impending doom of budget cuts/layoffs and the accompanying need to do a LOT of stuff with a lot of different stuff in a cheap/fast/reliable fashion, singletons may not seem so necessary. And it may even be nuisance/impediment to what they ALREADY have.
But for those who needs to work in the dirty trenches of 'agile' development, having to implement many different requests (sometimes unreasonable) from their client/manager/project, singletons are a saving grace due to reasons explained earlier.
- Another objection is that its memory footprint is higher
Because a new singleton will exist for each request from each client, this MAY be an objection for PHP. With badly constructed and used singletons, the memory footprint of an application can be higher if many users are served by the application at any given point.
Though, this is valid for ANY kind of approach you can take while coding things. The questions which should be asked are, are the methods, data which are held and processed by these singletons unnecessary? For, if they ARE necessary across many of the requests application is getting, then even if you don't use singletons, those methods and data WILL be present in your application in some form or another through the code. So, it all becomes a question of how much memory will you be saving, when you initialize a traditional class object 1/3 into the code processing, and destroy it 3/4 into it.
See, when put this way, the question becomes quite irrelevant - there should not be unnecessary methods, data held in objects in your code ANYway - regardless of you use singletons or not. So, this objection to singletons becomes really hilarious in that, it ASSUMES that there will be unnecessary methods, data in the objects created from the classes you use.
- Some invalid objections like 'makes maintaining multiple database connnections impossible/harder'
I can't even begin to comprehend this objection, when all one needs to maintain multiple database connections, multiple database selections, multiple database queries, multiple result sets in a given singleton is just keeping them in variables/arrays in the singleton as long as they are needed. This can be as simple as keeping them in arrays, though you can invent whatever method you want to use to effect that. But let's examine the simplest case, use of variables and arrays in a given singleton:
Imagine the below is inside a given database singleton:
$this->connections = array(); (wrong syntax, I just typed it like this to give you the picture - the proper declaration of the variable is public $connections = array(); and its usage is $this->connections['connectionkey'] naturally )
You can set up, and keep multiple connections at any given time in an array in this fashion. And same goes for queries, result sets and so forth.
$this->query(QUERYSTRING,'queryname',$this->connections['particulrconnection']);
Which can just do a query to a selected database with a selected connection, and just store in your
$this->results
array with the key 'queryname'. Of course, you will need to have your query method coded for this - which is trivial to do.
This enables you to maintain a virtually infinite number of (as much as the resource limits allow of course) different database connections and result sets as much as you need them. And they are available to ANY piece of code in any given point in any given codebase into which this singleton class has been instantiated.
OF COURSE, you would naturally need to free the result sets, and connections when not needed - but that goes without saying, and it's not specific to singletons or any other coding method/style/concept.
At this point, you can see how you can maintain multiple connections/states to third-party applications or services in the same singleton. Not so different.
Long story short, in the end, singleton patterns are just another method/style/philosophy to program with, and they are as useful as ANY other when they are used in the correct place, in the correct fashion. Which is not different from anything.
You will notice that in most of the articles in which singletons are bashed, you will also see references to 'globals' being 'evil'.
Let's face it - ANYthing that is not used properly, abused, misused, IS evil. That is not limited to any language, any coding concept, any method. Whenever you see someone issuing blanket statements like 'X is evil', run away from that article. Chances are very high that it's the product of a limited viewpoint - even if the viewpoint is the result of years of experience in something particular - which generally ends up being the result of working too much in a given style/method - typical intellectual conservatism.
Endless examples can be given for that, ranging from 'globals are evil' to 'iframes are evil'. Back around 10 years ago, even proposing the use of an iframe in any given application was heresy. Then comes Facebook, iframes everywhere, and look what has happened - iframes are not so evil anymore.
There are still people who stubbornly insist that they are 'evil' - and sometimes for good reason too - but, as you can see, there is a need, iframes fill that need and work well, and therefore the entire world just moves on.
The foremost asset of a programmer/coder/software engineer is a free, open and flexible mind.
Singletons are considered by many to be anti-patterns as they're really just glorified global variables. In practice there are relatively few scenarios where it's necessary for a class to have only one instance; usually it's just that one instance is sufficient, in which case implementing it as a singleton is completely unnecessary.
To answer the question, you're right that singletons are overkill here. A simple variable or function will do. A better (more robust) approach, however, would be to use dependency injection to remove the need for global variables altogether.
In your example you're dealing with a single piece of seemingly unchanging information. For this example a Singleton would be overkill and just using a static function in a class will do just fine.
More thoughts: You might be experiencing a case of implementing patterns for the sake of patterns and your gut is telling you "no, you don't have to" for the reasons you spelled out.
BUT: We have no idea of the size and scope of your project. If this is simple code, perhaps throw away, that isn't likely to need to change then yes, go ahead and use static members. But, if you think that your project might need to scale or be prepped for maintenance coding down the road then, yes, you might want to use the Singleton pattern.
First, I just want to say that I don't find much uses to the Singleton pattern. Why would one want to keep a single object thorough the whole application? Especially for databases, what if I want to connect to another database server? I have to disconnect and reconnect every time...? Anyway...
There are several drawbacks to using globals in an application (which is what the traditional use of the Singleton pattern does):
Difficult to unit test
Dependency injection issues
Can create locking issues (multi-threaded application)
Use static classes instead of a singleton instance provides some of the same drawbacks as well, because the biggest problem of singleton is the static getInstance method.
You can limit the number of instances a class can have without using the traditional getInstance method:
class Single {
static private $_instance = false;
public function __construct() {
if (self::$_instance)
throw new RuntimeException('An instance of '.__CLASS__.' already exists');
self::$_instance = true;
}
private function __clone() {
throw new RuntimeException('Cannot clone a singleton class');
}
public function __destruct() {
self::$_instance = false;
}
}
$a = new Single;
$b = new Single; // error
$b = clone($a); // error
unset($a);
$b = new Single; // works
This will help on the first the points mentioned above: unit testing and dependency injection; while still making sure a single instance of the class exist in your application. You could, per example, just pass the resulting object to your models (MVC pattern) for them to use.
Consider simply how your solution differs from the one presented in the PHP docs. In fact, there is just one "small" difference: your solution provides callers of the getter with a PDO instance, while the one in the docs provides callers of Database::singleton with a Database instance (they then use the getter on that to get a PDO instance).
So what conclusion do we reach?
In the documentation code, callers get a Database instance. The Database class may expose (in fact, it should expose if you 're going to all this trouble) a richer or higher-level interface than the PDO object it wraps.
If you change your implementation to return another (richer) type than PDO, then the two implementations are equivalent. There's no gain to be had from following the manual implementation.
On the practical side, Singleton is a pretty controversial pattern. This is mainly because:
It's overused. Novice programmers grok Singleton much easier than they grok other patterns. They then go on to apply their newfound knowledge everywhere, even if the problem at hand can be solved better without Singleton (when you 're holding a hammer, everything looks like a nail).
Depending on the programming language, implementing a Singleton in an airtight, non-leaky manner can prove to be a titanic task (especially if we have advanced scenarios: a singleton depending on another singleton, singletons that can be destroyed and re-created, etc). Just try to search for "the definitive" Singleton implementation in C++, I dare you (I own Andrei Alexandrescu's groundbreaking Modern C++ Design, which documents much of the mess).
It imposes additional workload both when coding the Singleton and when writing code to access it, workload which you can do without by following a few self-imposed constraints on what you try to do with your program variables.
So, as a final conclusion: your singleton is just fine. Not using Singleton at all is just fine most of the time as well.
Your interpretation is correct. Singletons have their place but are overused. Often, accessing static member functions is sufficient (notably, when you do not need to control time-of-construction in any way). Better, you can just put some free functions and variables in a namespace.
When programming there is not "right" and "wrong"; there is "good practice" and "bad practice".
Singletons are generally created as a class to be reused later. They need to be created in such a way that the programmer doesn't accidentally instantiate two instances while drunkenly coding at midnight.
If you have a simple little class that shouldn't be instantiated more than once, you don't need to make it a singleton. It's just a safety net if you do.
it's not always bad practice to have global objects. If you know that you're going to use it globally/everywhere/all the time, it may be one of the few exceptions. However, globals are generally considered "bad practice" in the same way that goto is considered bad practice.
I don't see any point to this at all. If you implemented the class in such a way that the connection string was taken as a parameter to the constructor and maintained a list of PDO objects (one for each unique connection string) then maybe there would be some benefit, but the implementation of singleton in this instance seems like a pointless exercise.
You are not missing anything, as far as I can see. The example is pretty flawed.
It would make difference, if the singleton class had some non-static instance variables.

I'm new to OOP/PHP. What's the practicality of visibility and extensibility in classes?

I'm obviously brand new to these concepts. I just don't understand why you would limit access to properties or methods. It seems that you would just write the code according to intended results. Why would you create a private method instead of simply not calling that method? Is it for iterative object creation (if I'm stating that correctly), a multiple developer situation (don't mess up other people's work), or just so you don't mess up your own work accidentally?
Your last two points are quite accurate - you don't need multiple developers to have your stuff messed with. If you work on a project long enough, you'll realize you've forgotten much of what you did at the beginning.
One of the most important reasons for hiding something is so that you can safely change it later. If a field is public, and several months later you want to change it so that every time the field changes, something else happens, you're in trouble. Because it was public, there's no way to know or remember how many other places accessed that field directly. If it's private, you have a guarantee that it isn't being touched outside of this class. You likely have a public method wrapped around it, and you can easily change the behavior of that method.
In general, more you things make public, the more you have to worry about compatibility with other code.
We create private methods so that consumers of our classes don't have to care about implementation details - they can focus on the few nifty things our classes provide for them.
Moreover, we're obligated to consider every possible use of public methods. By making methods private, we reduce the number of features a class has to support, and we have more freedom to change them.
Say you have a Queue class - every time a caller adds an item to the queue, it may be necessary to to increase the queue's capacity. Because of the underlying implementation, setting the capacity isn't trivial, so you break it out into a separate function to improve the readability of your Enqueue function. Since callers don't care about a queue's capacity (you're handling it for them), you can make the method private: callers don't get distracted by superfluous methods, you don't have to worry that callers will do ridiculous things to the capacity, and you can change the implementation any time you like without breaking code that uses your class (as long as it still sets the capacity within the limited use cases defined by your class).
It all comes down to encapsulation. This means hiding the insides of the class and just caring about what it does. If you want to have a credit card processing class, you don't really care 'how' it processes the credit card. You just want to be able to go: $creditCardProcessor->charge(10.99, $creditCardNumber); and expect it to work.
By making some methods public and others private or protected, we leave an entry way for others so they know where it is safe to call code from. The public methods and variables are called an 'interface'.
For any class, you have an implementation. This is how the class carries out its duty. If it is a smoothie making class, how the class adds the ingredients, what ingredients it adds, etc are all part of the implementation. The outside code shouldn't know and/or care about the implementation.
The other side of the class it its interface. The interface is the public methods that the developer of the class intended to be called by outside code. This means that you should be able to call any public method and it will work properly.
There are several reasons for using encapsulation, one of the strongest is: Imagine using a large, complicated library written by someone else. If every object was unprotected you could unknowingly be accessing or changing values that the developer never intended to be manipulated in that way.
Hiding data makes the program easier to conceptualize and easier to implement.
It's all about encapsulation. Methods are private that do the inner grunt work while exposing graceful functions that make things easy. E.g. you might have an $product->insert() function that utilizes 4 inner functions to validate a singleton db object, make the query safe, etc - those are inner functions that don't need to be exposed and if called, might mess up other structures or flows you, the developer, have put in place.
a multiple developer situation (don't
mess up other people's work), or just
so you don't mess up your own work
accidentally?
Mainly these two things. Making a method public says "this is how the class is supposed to be used by its clients", making it private says "this is an implementation detail that may change without warning and which clients should not care about" AND forces clients to follow that advice.
A class with a few, well documented public methods is much easier to use by someone who's not familiar with it (which may well be its original author, looking at it for the first time in 6 months) than one where everything is public, including all the little implementation details that you don't care about.
It makes collaboration easier, you tell the users of your classes what parts should not change so often and you can guarantee that your object will be in a meaningful state if they use only public methods.
It does not need to be so strict as distinguishing between private/public/whatever (I mean enforced by the language). For example, in Python, this is accomplished by a naming convention. You know you shouldn't mess with anything marked as not public.
For example - private/protected method may be part of some class which is called in another (public) method. If that part is called in more public methods, it makes sense. And yet you don't want these methods to be called anywhere else.
It's quite the same with class properties. Yes, you can write all-public classes, but whats the fun in that?

Categories