I have, within a SaaS app, an abstract class with ~12 extensions totaling ~60 methods, thus making this abstraction quite valuable.
However, these methods must now reference client-specific and db-housed API Keys, as we aim to integrate with a particular CRM that requires this dynamic data. This makes instances ideal, but at the cost of the abstraction.
No longer can we statically store these keys for use with user sessions and crons.
Without doing something as seemingly sloppy as manually setting server variables (notice my desperation), how would you architect this?
P.S. Before something is said, I've referenced SO enough to appreciate the value of code examples, but didn't see an application here.
Thank you.
Related
I am working with an older code base that passed a db connection into most functions in each class of the models. The db connection is created as a global and passed everywhere in the application:
$user = new User();
$user->loadById($db, $userId);
What advantages do we get by doing this vs a single connection the entire model inherits similar to the way most frameworks currently work?
Any insight would be very helpful.
Full Disclosure:
I asked this question this way because this is how we do it at work. I don't like that we pass around the DB connection. I am trying to find a proponent of this method to see if my mind can be changed. That is why I tried to sway the discussion to the PRO side of this conversation without being blocked as a bad question. And it worked. I didn't get banned, but the great StackOverflow community didn't let me down. It appears I'm not out in left field with how I think about this issue.
The main advantage is: it's easier. As in, it's the simplest thing to do, because as a result, you have no application architecture. You're grasping at things from everywhere and anywhere because you have no idea how to get them otherwise, and this makes for very poor maintainability. Guess what happens 5 years down the line with this sort of codebase? Massive legacy technical debt, and it's very likely your developers aren't using Object Oriented Programming - more likely shoving procedural code in classes.
I'm not going to bother explaining about global state, because there's already a fantastic answer that already exists on programmers. A small excerpt:
Very briefly, it makes program state unpredictable.
To elaborate, imagine you have a couple of objects that both use the same global variable. Assuming you're not using a source of randomness anywhere within either module, then the output of a particular method can be predicted (and therefore tested) if the state of the system is known before you execute the method.
However, if a method in one of the objects triggers a side effect which changes the value of the shared global state, then you no longer know what the starting state is when you execute a method in the other object. You can now no longer predict what output you'll get when you execute the method, and therefore you can't test it.
You'll find some developers do this purely out of laziness or a lack of knowledge / understanding of the basic concepts of SOLID. If you access global state (like the database), then the beautiful, isolated class you are currently writing that theoretically can be handed off to any other developer, and also tested in it's own right, is now coupled to this object somewhere off in the clouds.
As well as the above, you're making a liar of your object API. Each object should, via it's constructor / method signatures, specify exactly the required external objects with which it requires to function. This allows:
Your object to have a definitive API for it's usage
Future developers can see exactly what is required for this object to function from the constructor / method signatures
Everything passed in via Dependency Injection (the posh word for passing in parameters, basically), can be 'mocked out' for testability
Developers don't need to read through your code to find out what other objects are required, because of point 2
You aren't accessing something that can be changed by something else, somewhere else, and make debugging a nightmare
Your code should not be brittle. You should be completely confident in making changes somewhere in a massive codebase, without worrying about breaking something somewhere else. Your unit tests will cover this. I highly recommend reading The Clean Coder as it elaborates on some of these concepts.
AlmaDO has a picture of a good image about Singletons, which are basically objects that return a single instance of an object, like a database or logger. So if you request a new database from it, you either get a new one or just get back the one that already exists. In the traditional request / response / dead context, this is completely unecessary. If you're having a very long-running process, maybe this might be necessary, especially in other languages, but as a general rule of thumb in PHP; unless you're running a PHP web socket server or similar, DI is a much better way to go for maintainability.
This is exactly the same as calling StaticObject::Database, again - something that can be accessed from anywhere.
This is a really good post on Singletons in PHP, and how they're not at all needed - that post also has a lot of useful links in it further down.
Basically - don't be lazy and grasp SOLID. There's a reason it exists, and it's certainly not just for PHP, either. The main reason people do it is because they don't know better and it's easier, and easier isn't always the best way.
Also, a few additional clarifications. We don't have "models". We have a model, which is a layer. This is a massive misinterpretation of 'MVC', which we don't even actually have in PHP ('classical mvc'). We have the separation of concerns and that's it.
Your "models" are likely, services, domain objects, entities. More info on what the model is
Your user should not know about the database. It should be an Entity. Active Record Pattern is not the way forward. Take a look at DataMapper. Your repository would use the database object and return an array of User objects. Contextually as well, a user having access to the database makes no sense.
Most frameworks do not work by having access to the database in entities - this isn't PHP 4 any more, it's progressed a lot since then ;-) I highly recommend moving away from CakePHP (it's not MVC in any way) and take a look at a framework like Symfony, which still has it's flaws - knowing the flaws of your chosen framework is very important
I have developed a Web Interface for managing our devices (Dedicated Servers/Switches/etc) at work, however with my basic PHP knowledge, I ignored OOP completely. In the current state it just queries the MYSQL Database and populates the tables. Functions are all stored in a Functions.php file and called as needed.
As the project is functional and used now, I would like to rewrite this to be more efficient as it will be used among our other brands. I am having trouble applying the concept of classes to this project though (I use them all the time in C#/C++).
The way I see it, each Device be it a server, switch, etc. could be a part of a Device class that keeps properties like Datacenter, Name, etc. and methods such as Update, Delete, etc. I suppose I could additionally have a base Device class, then subsequent classes such as Server/Switch/etc. which inherit from that.
My question then is how is this more efficient? Each time the page loads I am still going to have to generate each instance of Device and then populate it from the Database, why I don't really see how this is better than the current implementation.
Thanks for any insight!
Using OOP is mostly unrelated to performance or efficiency. However, it allows you to organize your code in a modular fashion, and encourage code reuse.
A better webpage to explain can be found here.
I have a couple questions regarding best practices and performance for this project I am working on. Forgive me for the huge question.
I'm currently building a text-based game with PHP and MySql that is about 2,500 lines in the core file so far. Currently, this is a library of completely modular functions. Some used for data access, some for data manipulation, and so on.
My first question is this: One class, ItemManager, contains dozens of methods specifically for adding, updating, and deleting game items in the database. The only thing these methods have in common in they interact with the database. Currently, the constructor asks for a mysqli object and then uses that in all it's functions. However, once I add MongoDB into the project, some of these functions may be interacting with a different database.
Would it be acceptable or preferable to simply make all of these functions static? I see no reason to instantiate objects when there would only ever be one, and there is no need for it to maintain class members. So, should I use static methods or not? Why?
Second question: Can someone help me understand the benefit of using classes in PHP BESIDES modularity (as I can achieve that same effect with files of functions)? Coming from a Java background, I recognize the benefit of OOP in a persistent environment, as objects maintain data and states throughout the life of the application. However, with PHP, the life span of a script is a fraction of a second and all state information is stored within a database. Almost all functions just manipulate the database, so what's the purpose? Isn't it pointless to instantiate objects when I can merely call functions? Could I just do entirely static classes containing categorized data manipulation classes without instantiating an object of a class? What are the reasons I should use classes over files of functions? Isn't the basically the same? Are completely static functions acceptable?
Thank you for your time, I wasn't sure how to cut that question into less text, so I apologize.
Would it be acceptable or preferable to simply make all of these
functions static? I see no reason to instantiate objects when there
would only ever be one
There is no reason to instantiate objects if all you ever want to do is what this class is capable of doing. By using static methods you are coupling all of your client code with the class by hardcoding the class name throughout your code base. If at some later point you decide that you might want a different item manager service to fulfill your requests you will most certainly have a bad day.
Note that "a different item manager" can be simply code for "a mock manager used to unit test the rest of your code". So even in cases where alternatives will never be supported, using statics like that makes your code practically untestable.
Of course, you have already mentioned that there could very well be a different item manager in place: if the current one accepts a mysqli object then obviously there is no abstraction layer between your manager code and the mysqli interface. If you want to use a different object to connect to Mongo, how is the current item manager code going to support both configurations? Won't you need to write a new item manager class? How are you going to integrate it with the rest of the code if the class name is hardcoded everywhere?
Let's also view the situation from the opposite side: what does static gain you?
Obviously it makes the item manager a "singleton" object, which may sound like a good idea because "there is only one of it". This idea cannot be dismissed out of hand in PHP (as in other languages where multithreading is supported and there are hidden cross-thread dependencies), but it still doesn't hold much water. If you want your item manager to be a singleton, then simply don't create a second instance. If you want to force this for some reason, use a static variable to count instantiations and throw if you try more than one. Finally, make the class final so that this limitation cannot be removed. The result: a singleton that is not static.
This is all that static has going for it, and in light of the above it's awfully weak to stand as an argument.
and there is no need for it to maintain class
members. So, should I use static methods or not? Why?
I 'm not sure what this means -- you say the constructor already requires a database driver object, which has every right to be a class member. This is another obvious hint that static is not the way to go here.
Can someone help me understand the benefit of using classes in PHP
BESIDES modularity (as I can achieve that same effect with files of
functions)?
I 'm not going to present obvious arguments for OOP here, but raise a counter-point instead: you can achieve the same runtime effect, but you most certainly cannot achieve the same levels of maintainability and debugability for your application. Why use an inferior solution?
Coming from a Java background, I recognize the benefit of OOP in a
persistent environment, as objects maintain data and states throughout
the life of the application. However, with PHP, the life span of a
script is a fraction of a second and all state information is stored
within a database. Almost all functions just manipulate the database,
so what's the purpose? Isn't it pointless to instantiate objects when
I can merely call functions?
The life span of a process is a fraction of a second. The life span of the code base is measured in months, years and decades. That's how long people will be maintaining it, and that's why we use OOP in the first place.
Global variables can hold state just as well as class members, and people have been maintaining state long before "object-oriented" was a term. The benefit of OO is managing the complexity of the source-code-level model of the code, a venture I would most certainly not agree to describe as pointless.
So, should I use static methods or not? Why?
Static methods usually access static variables, which are global state (they are no different than global variables in this regard), which are bad, for many reasons.
Also, while an object instance can be replaced by an other object having the same interface, just by passing an other object to functions using it, static methods cannot easily be replaced. As a result, you can not mock them, and code using them is not easily unit-testable.
If you can, don't use static methods.
1) Stick with the object, as it is easily replaceable or extendable by additional db drivers (e.g. you can overwrite some functions to transparently redirect to MongoDB for special getters.) If you are sure that you will use only once instance, use a singleton, or even better, a regitry pattern.
2) PHPs lifespan isn´t that short. Using an MVC pattern it handles bootstrap, routing, models, business logic and output. So while a single request might only take seconds, it can involve hundreds of classes and thousands of methods.
To stick to your RPG example: One day you might decide to make it multiplayer. Now you can either instanciate a second player-object, or adapt about 500 functions. The former one is only possible with classes.
A great reason is human limitation: It is unlikely to keep the meaning of thousands of functions in mind, especially when working in teams. By using objects, you can define slim APIs. If the player-object has the public methods add_item(\item $item) and remove_item(\item $item), there won´t be a need to keep all those checking, calculating and db-handling functions in mind. You can even ask a fellow developer "create a \monster item with nothing but an attack() method". That´s it, you are done, and cooperation worked at it´s best.
Conclusion If you are from Java background and understand OOP, don´t think twice about ditching that habit. PHP is NOT a pre-OO-script to be used by scriptkiddies. It´s a full-fledged OO environment - but it´s up to you if you take advantage of this.
I was asked to do a project in PHP and to make sure it was object oriented. I've done OO and I've done PHP, but never both.
The main benefit of OO PHP (outside of inheritance/polymorphism) seems to be code organization. That's fine; I'm doing that. But where I get stuck is if I should actually be creating instances for every "object."
To me (and maybe I'm being naive here), a web app is all about making very short, stateless requests to alter or retrieve records in a database. The objects can't persist between requests. So it feels rather pointless to load data from the database, construct an object from that data, make a small update, save the data from the object back to the database, and then throw the object away. The loading/saving code seems to be a lot of work for nothing. [clarification: a waste of development time, not processing time... not too concerned about overhead]
The alternative is to have a bunch of singletons (or classes with static methods) that just provide a nice, organized abstraction layer to the database layer. I guess writing code in this manner just doesn't feel truly OO. Am I missing something or is that style fine?
Yes, you could summarise the benefits of OO as "code organization"; but this is true for all languages (not just PHP). In reality, it's more than that; it's about how you think about your data structures and algorithms, i.e. about how they map to concepts in the problem domain, how they relate to one another (ownership, parent-child, polymorphism, etc.), and how they expose clean, consistent interfaces to one another (encapsulation). If these concepts would benefit your application, and outweigh the extra development time vs. a quick-and-hacky procedural solution, then go for it.
I don't think persistence has anything to do with it.
I think you should question why you've been asked "to make sure it was OO". This seems like a pretty arbitrary request without further justification. Normally, the approach should be to write your application in the style that best suits the requirements, not arbitrary whims...
Singletons are essentially just global variables with some namespace sugar added in. There are a few main benefits to programming with objects and classes that you just don't get from straight procedural programming. One is inheritance, as you mentioned. Another is the namespacing - you can have a code to compress the lot into a single include file (more meaningful in interpreted languages like PHP than in compiled languages).
Objects are essentially a collection of functions with a shared state (though singletons make that a global state. Beware.) As you pointed out the benefit is mostly that that state is transparently shared by the functions without needing to explicitly pass it every single call. If you have various functions per request operating on shared data and wish them to be specialized forms of a general set of functions, OOP is probably a good fit.
Since you have been tasked to "make sure it is object oriented", I'd take some time to consider common groups of functions, generalizations of same, etc.
In the end the setup/teardown time of the objects isn't too bad - and it might even save some development time in the future if you do a good job.
I think OOP is just a programming style and has nothing to do with developing an application. What you need is a pattern that provides a sufficient abstraction layer (for example: MVC).
My recommendation is: Fat-Free.
It's tiny, simple and quickly take you to the minimal viable version of your product. It has everything that you might need (Caching, ORM, CRUD, Captcha...) and is so flexible that you can use any pattern and with your custom directories hierarchy.
Check out the extensive documentation. The only issue is that it requires PHP 5.3. I think it's reasonable considering the options and flexibility it offers. It really changes the way you work; you should definitively give it a shot.
Like most things in life answer is somewhere in a middle.
Todays application use ORMs (for example doctrine for php) for different kind of optimization, better understanding of database approach (which is important for larger dev teams), easier update of the code, abbstraction layer that is well known to people who join the project, caching mechanisms,....
Classes with static methods are just fine if you are doing some smaller project on your own, but when more people are involved in progress you simply need something more robust and standardized.
In my company we have developped some applications. We have to create an API for one application (say application A), so that the others can use it (an its data).
The question is : we already have developped PHP classes for the model of Application A, if we want to create an API, should we :
- re-use these classes (too much functionnalities for an API, too heavy...)
- create one PHP class, with some basic functions, that takes in input and returns only raw values (like strings, array... NOT complex classes)
- create another set of PHP classes, simpler, and designed only to be used by an external application (so only to get data easily)
Usually, an API is the 2nd solution (to be used as well with PHP than as a web service for example), but i find it too bad that we made a complex and usefull class modelisation, then we tear it apart just to have functions, strings and array.
The 3rd one seems to me to be the compromise, but a collegue of mine insist that this is not an API. Too bad...
What do you think ?
Solution number 3 might be the best one from an architectural point of view. Basically you are using a Facade Design Pattern to simplify your API. Since I am dealing with it at the moment: In Patterns Of Enterprise Application Architecture this approach is described as the service layer which makes totally sense since you don't want to expose any user (meaning whoever will deal with your API) to more complexity than is actually needed or desired.
This includes using the easiest possible interface and transfer objects (raw values if they make sense). As soon as your Facade is being called through remoting services (like a webservice) you will eventually have to break repsonses and requests down to raw values (data containers) anyway.
Build a set of Facade classes that simplify the public API.
Create some thin wrappers that implement simpler API over the original classes. DO NOT reimplement any business logic in the wrapper - that'd lead you into trouble if any of the logic changes, as you will surely lose track of which piece was modified and which was not. Keep the external inputs/outputs simple, if you need something more complex than string, use XML or JSON for structured data, but try to avoid too much complexity - if you have 2 things to pass two query parameters might be much better than one structure with 2 fields.
That's the 'Facade' pattern.
I would also say have a look at the Facade pattern.
Build a set of Facade classes that only offers the functionality that is really needed to be public. Those classes then for sure use your current core classes.
This gives you also the advantage that if you change the core classes, the API must not necessarily being changed.