Might be related
Another 7 deadly sins for PHP
Ok, Since I had some really bad seafood on Good Friday (hence not turning out to be that good). resulting in me vegitating in bed today, I thought considering how much crap I gave some of those CMS projects, they deserve a bit of an explanation about why they got nailed.
Otherwise known as the deadly sins re-run post...
Defines for configuration
Well, in principle this does not sound like such a bad idea. Coming from a C background, it's pretty much the only way to do things, without doing some huge layer.
Unfortunately with PHP once you go beyond a few lines of code, the classic problem arises, "Where was that set", or even worse "Which bit of code changed that"
I've used defines like this (DataObjects uses a define to turn off the overloading for buggy versions of PHP4) - but that is only there because it's something that is needed at compile time, and not at runtime. So there was no clean way to use settings that are specific to that class prior to it being loaded.
All configuration variables in almost every application I write now are set in the index.php file, why? you may ask. Well when you start looking at an application, what's the first file you look at. - yes. index.php, it all starts there..
Other that a few minor things like setting include_path, (yes, you can do that, and it get's rid of alot of stupid reasons for defines) the only thing index.php does is call the 'app runner' with all the config variables. Each nicely grouped by package.
This is a reasonable simple index.php (or bootstraper from FlexySvn) - the concept being that you have to rename the example file to index.php
if you look through the application code, it uses PEAR::getStaticProperties() to retrieve the config.
In summary it manages to solve a number of issues
not depending on the class to be loaded to set the config
not using a global variable (that may be overwritten, or is difficult to find how it came about.
easy to find out where config variables are being used.. - or incorrectly used..
easy to detect if some part of the code is accidentally changing variables (& on the same as the getStaticProperties.
easy to find and read.
Re-uses an existing bit of code that pretty much has to be loaded anyway.
BTW, I do not recommend using this bootstrap file for documenting all the possible options. - add a note about where to find that information. The standard index.php (or example bootstrapper) should be just enough for the user to get the basic application up and going. - without sifting through 30 pages of possible configuration.)
What's the difference between a good directory layout and a bad one?
Basically directory layout's for code have a few purposes
to make it easier for anyone maintaining the code to find a specific bit of code
Segmenting code into modules (for different distribution, or preventing overlapping or similar features)
mmh.. Nothing else!!!
So if your directory structure uses java.endless.name.format, Then half the directory structure is just a pointless empty directory that makes navigationing and locating the code time consuming and annoying.
PEAR's standard was thought through and has proven simple, yet successfull for so long now, that it's just amazing that people even have to think about making up a new standard.
class Aaaa_Bbbb_Cccc goes in Aaaa/Bbbb/Cccc.php
Yeap, that's about it.. Since you dont have a file with a list of Functions, or if there is any data files, it's only used by a package, and hence the file ends up as a subdirectory of that package, Pretty much everything is easy to find, and easy to spot if something is out of place.
Well, what so wrong about .inc, .class.php, .myending,
.inc, .myending etc. have a number of problems, first of all once you have realized that they are PHP code, and your editor has also picked this up so the highlighting and auto-completion work properly. You then have to worry about you web server picking them up and not serving them up as text - revealing your inner most secrets to anyone at google..
.class.php, well what's the point! do you have files called func.php, data.php, tpl.php, no, well probably because your classes follow the PEAR standard and your functions do not exist, and your data and templates are in directories called data and template... This get's especially worse if for some reason you can not avoid having a classname ThisReallyLongInterfaceAddonName.class.php - while not recommended on the rare occasion that you could not think of anyway around this, you just added 6 characters to the file name, just because you thought it was cool... - it's not! - and it makes the .php dissapear of the end of the tree if you have a tree browser in your editor..
Dont fall for the 'Not created here' idea.
Yes, we all love the 'Not created here' idea, I tried that code in PEAR, but I could not get it to work, So I'll start from scratch and see if I can write some code that does the same, but does not have a 6 year history of bug fixes and user contributed features.
Think about it, the core stuff has been done 100 times, and there are a few places that you can look to find them.
PEAR (well not a supprise here as I've been contributing for so long)
Zend (not sure about this - do they actually distribute PART's rather than one big 'do it this way ball')
Very few other places.. (do not mention CakePHP - it's does not solve the problems below)
PHP classes - if you can stand the noise / authentication / licensing crap ? (haven't used this for a long time so these may be out of date)
Why so few, well, you need to watch out for:
Do the parts work without the downloading a huge dependency blob of code - can you normally just download and keep updated a single class or group of classes?
Do they follow standards
Do they have a bug tracker, a specific maintainer, and a parent group that can help sort out if the maintainers disappeared off the place of the planet (or you want to volunteer to help or take over)
Can you replace or just keep one part maintained by you? (a prime example is the old XML Tree code in PEAR, that got a BC issue many years ago, rather than re-writing code to meet the new specification, budget wise, for an application that rarely changes and uses this a minor part of it's code, having the ability to override the 'pear' version with a modified copy of the original, without confusing the packaging system. saves alot of time and money...
Don't be afraid to give up on a library after using it for a while. - Smarty for all it's maintainers and hoohar, can be a pig's ear to write for, and maintain. It gives you too much power, which should never really go into a template engine. Keep it simple (where possible) is a good rule for libraries...
If your code is public, you should try not to ridicule yourself.
On the rare occasion we interview people, one thing we like to see is examples of code they have written, (open source code is usually a great way to evaluate them). Taking a certain amount of pride in their work makes the difference between a candidate who get's offered a better package, that a candidate who just get's the basic one. Other than the things listed here there are a few other telltale signs that someone can solve problems cleaner and tighter than others. A great one is when you see a huge blob of code that basically does
$a = $something_a
$b = $something_b
$c = $something_c
$z = $something_z
This kind of either assignment or function call repeated in a similar context over and over again, smacks of code that should have been typed about halfway through, and the engineer thought.. mmh... this is a bit dumb, let's see if I can tidy it up a bit... - So it would probably never have seen the repo, or even the save button..
Part of this is also making you code readable. Not just for others, but for yourself, Some of us older guys still have to look after code we wrote 6 or more years ago. The good stuff has some comments and some structure to it. The bad stuff is usually the one where you wish you had time to recode it because it's a pain to work on and you dread every bug report for it. So making code readable (comments in sensible places, helping you understand the point of a block of code ) come in really handy later.
Other little things like using Capital letters for your variables tends to be a good warning sign, PHP uses case sensitive variable names, and all the super globals are called $_BIGLETTERS - so it's quite easy to read some code and see what data is coming from outside. When you start adding your own variables to this mixture, you dilute that advantages that that readability gives you...
Functional Crap (or Procedural code)
PHP has functions, and Classes, Classes for some are a black magic or just too difficult to understand.... Or as some old wives have said 'OOP code in PHP is slow' ... well, I think that one died a death years ago.
The reality is that you can not write a application that is bigger than one or two files without starting to use objects. Why? well, you very quickly come into the problem of 'what does "uses('xxx')" do, and why is it not working correctly.
So every time you find a bug in that code, (which can be every 6 months or so) you end up trying to hunt down a tree of activity in many different files, and spend your time learning the ins and outs of Grep.
I once said to someone, even if you dont understand objects, just using Static methods, and calling them rather than functions would make life alot easier in the long run. The only downside is that they started writing classes like Util:: ???? and putting every function on earth in there.... - Well some people will never learn.
Mixing PHP and HTML
Well this is so 1999 (well 2000 really as that's when php4 came out), but everyone still inists on doing it. Stop, it just makes your code complete jiberish. You cant see what it was trying to do, let alone what it is really doing.
The fundamental problem with this approach is that outputting anything before you are certian that you can fetch all the required data for the page, results in half rendered pages, and hidden error messages or horrific kludgy workarounds..
If you can determine if there is a problem before you start rendering a page (outputting HTML), you can then decide how to handle it correctly - display the form again, display a problem with the database message etc...
I have a feeling this has probably repeated my 7 deadly sins post from a few years back... but hey, why write once what somebody else has already written before (even if it's yourself)...
Nice to read other's take on developing standards with php, and agree with all of it. Well done, and hope you get to feeling better.
You know what else is so 1999?
Posting something to a blog you want to be taken without proofreading it.
Please properly spell and punctuate your posts in the future, that was just hard to read.
Actually this one's not too bad compared to some of my previous ones..
I did go through it again but fr**ging serendipity, which is what the backend of this thing uses timed out and lost the changes..
Not quite sure if Blogs are more just 'venting' frustration or ever supposed to be taken seriously....
I have to disagree with some of your points...
"Mixing PHP and HTML"
This should be retitled as "Mixing HTML and business logic". I think that's what you mean anyway. It's ok to mix php and html (how else do you generate a dynamic page), however, having your business logic interspersed with the display html is a PITA for code maintenance, among other things.
"Functional Crap (or Procedural code)"
I disagree that no complex program can be created procedurally. This is entirely programmer dependent. If the person doing the programming is competent and disciplined then anything that can be done w/OOP can be done just as well procedurally. The biggest advantage of OOP is reusability. Everything is in a nice, neat package that is able to be used over and over. Aside from that advantage (which is quite large), there is little more, in my opinion, than additional overhead that is added with OOP.
OOP actually is slower. I was benchmarking some code, and when I had the algorithm down, I converted the function to a class method. Solely from putting the identical code into a class, its speed dropped by 30%. Apparently the engine has to do a lot more work from inside an object to call functions.
After I noticed that with 5.1.6, I was able to duplicate it on then-current 5.2.3.
Not that it mattered. That code got ported to Perl; it failed in production because I forgot PHP *still* can't handle large files. Grrr!
Well, I guess that is a most instructive post than the previous one, but there is a few points I disagree with.
As for me, using procedural AND objet in the same application is a quality for php, you don't have to modelize everything nor using static methods if you don't want to. I really love OOP, but I think a few things would have pissed me off if I had to turn them into classes. Even if using static functions make your code easy to organize, it stays slower than using simple functions, I guess.
What I want to say is using *.class.php extention is, in my opinions, very usefull as you know this file contains a class (named Plop for plop.class.php...) and there is no need to look for something in this file, you know what I mean ? (I'm not sure I understand my own words...)
Mixing PHP and HTML is pretty cool too, if your code is well-organized (queries at the top, not in the HTML code, for exemple)...).
I'm still using defines for config vars, but not as you said, I usually put them in a file named "config.php" or "needs.php" or something like that...
Php actually is a quite simple language you can do powerfull thing with without discouraging beginners with jiberish concepts... If I were you, I'll put a few "I think", "In my opinion" or "as for me" in my posts, otherwise it's a bit impetuous, just my 2 cents...
(I'm still french since my last comment, once again please excuse my english ;))
I just wanted to add something about the class nomination.
I'm okay to say that a good nomination is important, but the way you explain (using Aaaa_Bbbbb_Cccc) makes me think that you are involved into the Zend fw :D.
Maybe it's a good idea the way they call their classes, but it's certainly not the only one.
Otherwise, I read an other post into your blog (the original post of this one, this one you listed the bad cms), and I disagree with you with the fact some cms does not use PDO or some PEAR code. I'm totally agree to the fact theses codes are powerful and they have a lot of user contributed features and 6 years of bug fixes. But sometime, on some web server, you don't have PDO or PEAR package. So if you use a cms/fw that need Pear/PDO, you screwed !
Maybe the better way is to have a cms/fw that could use pear/pdo but also implement their own scripts (or a functionnal else). Don't you ?
Sorry for my english..
As far as packaging goes you pretty much have to download the whole Zend Framework if you want to use it (with the exceptions of the Google Data APIs and Microsoft Infocard components which can be downloaded separately). However, just because you have to download it all doesn't mean you have to use it all. Zend Framework is really just a bunch of loosely coupled components that you can use to "glue" your application together. This is important to keep in mind - just because the whole framework is sitting on disk doesn't mean you have the overhead of a whole framework. You can use it like a class library that you pick-and-choose components from. There's really no reason to not use Zend Framework in your application - there's a lots of useful stuff in there that your application could most likely benefit from. There is, however, a Zend Framework MVC stack which you can use if you'd like. It's your choice, individual Zend Framework components or the whole MVC stack plus individual components.
Full of yourself? Never "mixing" php and HTML? Are you advocating a use of a template system like Smarty (Hey, PHP IS a template system).
Not defining constants in a config file? Why not? You are assuming everyone uses the front controller pattern then if you only set it in index.php...what happens when you have another page? Oh no, they are defined there unless you include index.php too.
Get off your high horse and make a constructive post, instead of your "I'm better than you" junk you have up there.
Andrew - "It's ok to mix php and html (how else do you generate a dynamic page)"
Actually you can do this by using a JS front end that is only asking for data that it will mold on the clients side. I have a current project where the PHP is just generating JSON for an ext-js frontend. Though I still love having to have the ability to go into a current HTML page we have and throw in 5 lines of php where needed and not have rewrite the whole file.
@Bradley Holt : If your previous post was for me, I totally agree at the fact that you could use a part of the zend fw, and it's not because you have all the files that you need to load all of them. But I was talking about external needs. A framework that use PDO, Pear, is great because not use the "I created from scratch because I'm a roxor". But if your server does not have Pdo/Pear, you can't do nothing with this fw. That's why the most important framework (zend, cake, code igniter, etc) use their own abstract database, cache and view renderers.
What are 'defines'? A common name for what you mean is 'constants'. They are called like that for ages.
Telling other people about 'sins' and then you don't even know how things are called...
Why do you notice the splinter in your brother's eye, but do not perceive the wooden beam in your own eye?
Telling others about unwritten laws and rules and saying they are sinning? How's that?
Nobody has told about what is the best, so you can't sin against it either. You can argue about best practices, but why calling it sins if one doens't comply with it?
- Unomi -
LOL - Some people obviously dont get the sin's analogy...
The fact that good coding practices are often treated with religious fervor is quite an apt way to title the post...
I name my class-files .class.php because I name my interface-files .interface.php, because I have interfaces and classes in OOP. And if I have Test-Cases (for unit-tests) I call this files .test.php .. and I have them all in the same directory: foo.class.php, foo.interface.php and foo.test.php
"Actually you can do this by using a JS front end that is only asking for data that it will mold on the clients side."
I've tried to use js as the main content display mechanism and I end up spending more time fighting the js to get it to work in all 3 major browsers than I do everything else...combined. In addition to that, performance when you have a large amount of data to display is on par with "stupidly slow". Sending the data from the server takes 2 seconds. Then js spends the next 60 rendering the html and attaching events to it, during which the browser is eating .5 a gig of ram, or more, and 95% processor time (I'm staring at you FIREFOX).
Not to mention the headaches that are caused with each "update" from the browsers. IE is especially bad about things like that...a supposedly minor update creates a new bug that will break your site.
I'm not saying it's not possible, but it's not for me :).
None of those... Well, I really DO like static methods. What's wrong with them? I think they are like Ubik, "safe when used as directed..."
The error that occurred when I tried to post, pretty much makes my point about the very poor quality of code that is AVAILABLE.
Maybe my message was too big, let me try segmenting it and see what happens?
But on the other hand, you SHOULD use all of that succky stuff just because it was already written (by someone of unknown capability) and IT IS AVAILABLE, instead of writing your own hopefully less suckky stuff??? Did I get that right???
Frankly I have yet to be impressed with PEAR; way too many inscrutable dependencies for my taste. Why brag about how many bug fixes it has? That's often a sign of some poor quality code! Do it right and you won't have so many bugs to brag about fixing.
I just wanted to use one simple thing from PEAR and it loads in gobs of stuff... I tried to hack out such things as the fancy dancy error logging that I didn't want or need and which itself pulled in a zillion other dependencies. But I ultimately found that it was easier to write my own program than to try to extract anything out of the entwined ensnared mesh of PEAR. I do think that there is some good stuff in PEAR but with a gridlocked structure like that I say No thanks. (I've even heard one of the main PEAR devs talk about that problem. He said it was a mistake but it was too late to undo it.)
okay, breaking it up into pieces seems to work... so why can't this blog program be bother to give a proper error message?
especially since the focus of this discussion is on code quality.
And that is the whole problem, take "PHP Classes" which you mention above. I find it's a good place for inspiration of a wide range of techniques, but most of the code there is er uh I'll be polite and call it "less than production quality code", translate to your favorite word as you will. There are a few jewels on that site but it's rare, most of it is for "demonstration purposes only".
There is little QC in most of these projects (frameworks, forums, etc) and no qualifications for joining up and writing code. It's often the ~first~ serious program that somebody has written and it shows. Hey it's great that people have an opportunity to get experience and to have fun, but don't ask me to gamble on it for production use in critical apps.
The greatest recurring nightmare of a programmer is to be dependent upon somebody else's buggy code. It bites you every time. This is even true for commercial code from places like M$. The less dependencies that I have on other peoples code the happier I am and the more likely something is to work long term reliably. Does that sound arrogant? It's not intended to be, this is just the voice of agonized experience.
Frankly, (I won't mention names) but some of the code I see in some of these big name PHP projects is downright scary. And this kind of stuff results in membership in the security exploit of the week club.
You want to see something interesting? Put some big name forums and frameworks on a server and then monitor your web logs and take a look at all of the exploits that are being probed for.
here we go again, error [invalidbody] = 1...
still trying to solve the problem, no indication of what it does not like.
Marks this blog software as... well, you figure it out.
At least if there is a bug in one of my programs, I know what my intentions were and it is easier to fix. But if there is a bug in someone else's program you must first expend a considerable effort to figure out their intention before you can even begin to fix it. Thus there is some validity for the 'Not Invented Here' syndrome.
Objects are Cool! Procedural is Cool! Huge Complex Programs were written in FORTRAN and Assembly a long time before objects came along. That's just an absurd notion that it can't be done. Ever heard of 'Turing Complete?'.
Objects are for Encapsulation, no more no less. If you have something that it makes sense to encapsulate then by all means go for it. You can achieve huge structural efficiencies by using objects. As far as speed concerns, these days it is generally cheaper to buy faster hardware then to expend expensive dev time to save a few millisecs -
this stupid content filter was rejecting my pithy signoff message. Not what I ask you is wrong with this???
beware of prem + ature optimization..
The Jab + ber + wock Out gabe...
P.S. I agree with Andrew (16) above
But unfortunately we are stuck with it and must make the best of a very bad situation. The show must go on!
- PHP just does some things better. cloud backups, pecl-expect
- Roo J Solutions Growing into 2013, always recruiting, and developing differently
- Interesting Problems.
- Prettybooked.com turning a startup into a reality.
- Migrating off Netsuite - The hidden cost of Clouds..
- Roo.XComponent introduction
- Roo J Solutions Limited is recruiting