What are the advantages/disadvantages of monolithic PHP coding versus small specialized php scripts?
Asked Answered
Z

5

1

I have historically used a monolithic approach to PHP coding.

That is, I write one index.php, with an average size of 70k-250k, and use

mod_rewrite

to turn the rest of the

REQUEST_URI 

into parameters passed into the index.php to control what is happening.

The alternative would be to write many small php scripts, each specialized to a particular purpose. I'm thinking that some of my more active ajax scripts may benefit from this.

One thing that has kept me in this thought process is I don't know how using includes, especially conditional includes would affect the performance of the opcode cache.

I have generally avoided includes altogether if possible due to my paranoia about this, but this results in either duplicating code, or staying monolithic.

As I'm using mod_rewrite anyway, converting between the two methodologies should be simple.

I look forward to your comments.

EDIT: One of my target apps currently handles 80-100 page hits per second (I got some decent hardware). Most of those are ajax requests. Everything works and is snappy, but I've developed as a php programmer without critique and need it.

Zantos answered 13/10, 2009 at 21:15 Comment(1)
This already looks like a candidate for the daily wtfAugustinaaugustine
K
6

Modular code is easier to understand and maintain. A huge monolithic codebase can become like a house of cards. It works just fine in practice, but changing any of the lower elements becomes impossible. If you split up your code into clear abstractions, it can be much easier to make changes and you'll save yourself a nightmare if you ever add developers.

Konikow answered 13/10, 2009 at 21:18 Comment(2)
I agree. Internal to my monolithic approach, nothing is done twice. Everything is a function. But still, does seperating those function groups out into includes introduce a performance penalty?Zantos
As long as the number of includes/requires is within reason, performance won't be a problem. You may have to hit the hard drive a bit more, but it shouldn't make a difference.Konikow
G
3

The performance bonuses of not using included files is far outweighed by the ease of maintaining and debugging a large application using included files.

Rework is waste. Copying and pasting code from one app to another is maintenance hell.

Gotland answered 13/10, 2009 at 21:21 Comment(2)
Usually database queries became a bottleneck in web applications, not source parsing. Especially if you can cache the entire html pages.Hornbeck
Alas, only about 10% of my pages can be cached, and that cache invalidates in about a minute. The database is highly optimized with expensive queries themselves cached in tables.Zantos
C
1

In addition to the other comments (with which I agree completely), another view: I have made the experience that a monolithic approach, if driven to extremes, costs valuable RAM - the whole file has to be loaded to be interpreted, no matter whether everything from it is needed or not, and that alone eats off a lot from the 8, 16, or 32 MB you get per instance.

Client answered 13/10, 2009 at 21:41 Comment(1)
I was thinking that because of the opcode cache, this may not be true as the cache loads from ram anyway right? A single cached code base executed versus the smaller ones with duplicated libraries stored?Zantos
H
0

Please don't forget about testing and maintaining the code. I can't image if you're able to write unit-tests to a project which is just in single file. Futher more, it's much harded to predict which functionality can be broken by changes you've just made. In case of modular architecture if you change some module then you can only break this module and modules which depends on it. Even a small changes can be fatal to single file projects (you can forget to close quote which will break all pages at once). I think you must retest all the functionality after even small changes we've made. And this can be a pain for testers ecpecialy you're not able to use unit-tests.

Also if all code i stored in a single file then you'll more likely have a bad code. Such code will tend you to use global variables. In this case it's hard to reuse such code in other project. Of cause you can copy it, but remember when you copy something you copy all its bugs. Just imagane the project where you can use set of well-tested (tell thanks to unit-tests) libraries. When new bug appear then it's just fixed in a single place.

One more thing, when you're working in a team using a single file will be pain. Even if there is only 2 developers they waste much time to merge changes.

Any way, if your project is not big at all you can use single file appoch.

Hornbeck answered 13/10, 2009 at 21:42 Comment(1)
Thank you for your comments. I use one global variable, to pass around the database handle. I do use constants alot for site wide preferences. I load those with a require. Everything other than parsing my request_uri is a function already and bug fixing has been relatively painless and usually only breaks one function. Yes, I retest the entire app after every change. I am the testing group. :)Zantos
C
0

For Unix command line scripting, the monolithic approach allow a very high level of portability.

Using a single (hashbang) script even allow to dump the script in usr/bin

sudo cp myprog /usr/bin
/* (...) */
sudo cp myprog /usr/games
/* (...) */

This allow to call the program from anywhere, any path, by just typing myprog, instead of /PATH/./myprog. Make sure it can be trusted!

We have to take an extra care of the paths.


Some simple examples about paths:

/* Create a folder in the home directory, named as the script name, if not existing. -*/
if (!is_dir($_SERVER["HOME"]."/".$_SERVER["SCRIPT_NAME"])){
  @mkdir($_SERVER["HOME"]."/".$_SERVER["SCRIPT_NAME"]);
}

/* Program folder path: --------------------------------------------------------------*/
$PATH = $_SERVER["HOME"]."/".basename($_SERVER["SCRIPT_NAME"])."/";

/* Program running path, currently: --------------------------------------------------------------*/
$JOBPATH = getcwd();

Handle POSIX SIGNALS

/* Register cleaning actions at SIGINT ------------------------------------- */
function shutdown() {
  // Perform actions at ctrl+c 
  echo "Good bye!";
  exit;
}
/* Register resize at SIGWINCH ---------------------------------------------- */
function consoleResize() {
  @ob_start;
  $W = (int)exec("tput cols");   // Columns count
  $H = (int)exec("tput lines");  // Lines count
  @ob_end_clean();
  // Shell window terminal resized!
}

/* Register action at SIGSTOP (Ctrl + z) ---------------------------------------------- */
function sigSTOP() {
  // Program paused!
}

/* Register action at SIGCONT (Type fg to resume) ---------------------------------------------- */
function sigCONT() {
  // Program restarted!
}

register_shutdown_function("shutdown");
declare(ticks = 1);
pcntl_signal(SIGINT, "shutdown");
pcntl_signal(SIGWINCH, "consoleResize");

This doesn't mean we have to write everything in one block, but merge the rendering in one file allow many extra capabilities in a unix env.

There is a lot to say, php as cli script is an amazing beast.

Crosscrosslet answered 15/5, 2020 at 17:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.