How to Refactor a Mess into an Organized Web Application (Part 2: the Server Side)
Overview
In the former post of our series, we started to refactor a simple vcard application, which initially was a total mess.
In the first part, we defined a skeleton folder structure for our application; and we laid out the foundations of the BPC architecture.
Where;
- Behavior/business logic (B) would go to the Behavior Tier;
- Presentation/rendering (P) would go to the Presentation Tier;
- And events/signals/callbacks (C) would go to the Communication Tier.
In this post, we will continue our discussion by transforming our application.
BPC versus MVC
There are both similarities and differences between the BPC Architecture, and the MVC paradigm:
- The Behavior Tier (B) has similar functionality to the Model in MVC;
- The Presentation Tier (P) has similar functionality to the View in MVC;
- And the Communication Tier (C) has similar functionality to the Controller in MVC.
There are a handful of client-side and server-side MVC and rapid-development frameworks such as CakePHP, Prado, Symfony on the server side; and backbone, sproutcore, knockout, ember, batman on the client-side.
Though, in this article series, we will be looking at how a really simple application can step-by-step evolve into its own framework.
It will be more educational; and as we dive deep in, we will understand why those frameworks do what they do the way they do
![]()
I’ve been using and re-aligning the BPC Architecture in various production environments, for the last few years. And day by day pieces of the puzzle seem to fit better. I see that the concept has matured enough to be put into words, and that’s what I’m trying to do here
. Though it’s still a work in progress, and I’d love to hear your feedback.
Enough chitchat; time’s candy. So let’s get our hands dirty. Shall we?
Application Constants
Let’s start by defining constants that we will be using in the server-side:
<?php
<?php
namespace o2js\vcardapp\config\constants;
// /o2.js/examples/vcardapp/include/config/constants.php
class PageTitle {
const ABSENT = 'o2js.com - VCard Demo';
const INDEX = 'o2js.com - Welcome to VCard Demo';
const VCARD = 'o2js.com - VCard Demo - Profile of "{0}"';
};
class PageEnum {
const ABSENT = 0;
const INDEX = 1;
const VCARD = 2;
};
class ServiceKey {
const USER_NAME = 'u';
};
class Path {
const VCARD_DATA = '/o2.js/examples/vcardapp/include/persistence/data/{0}/vcard.html';
};
class RegExp {
const TEMPLATE = '/({\d+})/i';
};
?>
?>
The ServiceKey::USER_NAME is for extending our application to support showing vcard information for more than one person. We will be creating an API that will query VCard information of registered users.
Now let us create an …/volkan/vcard.html to simulate a server-side storage.
This data folder is for demonstration purposes. It will simulate the server-side persistence layer.
Normally, an RDBMS, or a NoSQL datastore (such as MongoDB) should be a better fit for the persistence tier.
VCard Template
Here’s the content of the vcard:
<!-- /o2.js/examples/vcardapp/include/persistence/data/volkan/vcard.html -->
<h1>Volkan Özçelik</h1>
<dl>
<dt>Web</dt>
<dd><a href="http://o2js.com">o2js.com</a></dd>
<dt>Email</dt>
<dd><a href="mailto:volkan@o2js.com">volkan@o2js.com</a></dd>
<dt>twitter</dt>
<dd><a href="http://twitter.com/linkibol">@linkibol</a></dd>
<dt>LinkedIn</dt>
<dd><a href="http://linkedin.com/in/volkanozcelik"
>linkedin.com/in/volkanozcelik</a></dd>
</dl>
<p class="clear"><a href="../close" class="close" title="close"
><span>back to home</span></a></p>
Index Page
Now let us change index.php a little:
<?php
namespace o2js\vcardapp\view\index;
require("include/common/common.php");
require("include/init/index.php");
require("include/presentation/header/common.php");
require("include/presentation/body/index.php");
require("include/presentation/footer/common.php");
?>
Where
- include/common/common.php has common includes shared between views,
- include/init/index.php initializes static constants for the current view,
- include/presentation/header/common.php and include/presentation/footer/common.php simply render the page header and footer.
- And include/presentation/body/index.php is responsible for rendering the body.
And let’s observe these file one by one:
include/common
<?php
namespace o2js\vcardapp\common;
// include/common/common.php
require("include/config/constants.php");
require("include/persistence/state/State.php");
?>
State Class
State.php defines a class that holds the page state.
<?php
namespace o2js\vcardapp\state;
// include/persistence/state/State.php
use o2js\vcardapp\config\constants\PageEnum;
use o2js\vcardapp\config\constants\PageTitle;
class State {
public static $currentPageTitle = PageTitle::ABSENT;
public static $currentPageEnum = PageEnum::ABSENT;
};
?>
The class simply defines a default set of state data.
These static State members are then initialized at include/init/index.php:
init/index
<?php
namespace o2js\vcardapp\init;
// include/init/index.php
use \o2js\vcardapp\state\State;
use \o2js\vcardapp\config\constants\PageTitle;
use \o2js\vcardapp\config\constants\PageEnum;
State::$currentPageTitle = PageTitle::INDEX;
State::$currentPageEnum = PageEnum::INDEX;
?>
And here are the header, body, and footer parts of the application:
presentation/header/common
<?php
namespace o2js\vcardapp\presentation\header;
// include/presentation/header/common.php
use \o2js\vcardapp\state\State;
$pageTitle = State::$currentPageTitle;
?>
<!DOCTYPE HTML>
<html>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Style-Type" content="text/css" />
<title><?php echo $pageTitle; ?></title>
<link rel="Stylesheet" type="text/css" href="/vcardapp/css/main.css" />
<head>
</head>
<body>
presentation/footer/common
<?php
namespace o2js\vcardapp\presentation\footer;
// include/presentation/footer/common.php
?>
</body>
</html>
presentation/body/index
<?php
namespace o2js\vcardapp\presentation\body;
// include/presentation/body/index.php
?>
<div id="VCardContainer">
<p id="VCardActivator"><a href="people/volkan"
class="super button action" id="vcard-volkan">Volkan Özçelik</a></p>
<p id="VCardContent"></p>
</div>
You can see what we’ve done so far at this github history snapshot.
Everything Put Together
After all this setup, our initial page will look like this:
And the rendered HTML will be:
<!DOCTYPE HTML>
<html>
<!-- http://localhost/o2.js/examples/vcardapp/ -->
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Style-Type" content="text/css" />
<title>o2js.com - Welcome to VCard Demo</title>
<link rel="Stylesheet" type="text/css" href="/vcardapp/css/main.css" />
<head>
</head>
<body>
<div id="VCardContainer">
<p id="VCardActivator"><a href="people/volkan"
class="super button action" id="vcard-volkan">Volkan Özçelik</a></p>
<p id="VCardContent"></p>
</div></body>
</html>
But when clicking the button we will get an error:
This error is because we have not defined a page for the people/volkan link. We’ll work it out by defining required presentation and business components (into includes/presentation and include/business folders respectively).
Let’s start doing it by defining simple rewrite rules first:
URL Rewrite Rules
Options +FollowSymLinks RewriteEngine on RewriteRule ^include/?.*$ - [F,L] # disallow access to sensitive folders. RewriteRule ^index.php$ http://localhost/o2.js/examples/vcardapp [R] RewriteRule ^close$ http://localhost/o2.js/examples/vcardapp [R] RewriteRule ^people/(.*)$ vcard.php?u=$1
These rules will map:
- …/examples/vcardapp/close to http://…/examples/vcardapp
- and …/examples/vcardapp/people/volkan to http://…/vcard.php?u=volkan.
We can do further URL-rewrite/SEO optimization, but that’s good enough for now
.
VCard Page
But our vcard.php is currently missing. So let’s create it:
<?php
namespace o2js\vcardapp\view\vcard;
require("include/common/common.php");
require("include/business/manager/VCardManager.php");
require("include/init/vcard.php");
require("include/presentation/header/common.php");
require("include/presentation/body/vcard.php");
require("include/presentation/footer/common.php");
?>
vcard.php is quite similar to the index.php above; the only things that differ are the VCardManager.php and include/presentation/body/vcard.php.
Let’s see them one by one:
VCardManager Class
<?php
namespace o2js\vcardapp\business\manager;
// includes/business/manager/VCardManager.php
use \o2js\vcardapp\config\constants\Path;
use \o2js\vcardapp\config\constants\RegExp;
class VCardManager {
public static function getVCardHtml($userName) {
return file_get_contents(
$_SERVER['DOCUMENT_ROOT'
].preg_replace_callback(
RegExp::TEMPLATE,
function($match) use ($userName) {
return $userName;
},
Path::VCARD_DATA
)
);
}
};
?>
VCardManager::getVCardHtml($userName) simply gets the vcard html by finding and reading the relevant file include/persistence/data folder.
presentation/body/vcard
And here’s include/presentation/body/vcard.php:
<?php
namespace o2js\vcardapp\presentation\body;
// include/presentation/body/vcard.php
use o2js\vcardapp\config\constants\ServiceKey;
use o2js\vcardapp\business\manager\VCardManager;
$user_name = $_GET[ServiceKey::USER_NAME];
?>
<div id="VCardContainer">
<?php
echo VCardManager::getVCardHtml($user_name);
?>
</div>
What we have done so far is reachable at this github history snapshot.
the Rendered VCard
After all these, clicking the vcard button will display the following vcard:
With the following HTML:
<!DOCTYPE HTML>
<html>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Style-Type" content="text/css" />
<title>o2js.com - VCard Demo - Profile of "{0}"</title>
<link rel="Stylesheet" type="text/css" href="/vcardapp/css/main.css" />
<head>
</head>
<body>
<div id="VCardContainer">
<h1>Volkan Özçelik</h1>
<dl>
<dt>Web</dt>
<dd><a href="http://o2js.com">o2js.com</a></dd>
<dt>Email</dt>
<dd><a href="mailto:volkan@o2js.com">volkan@o2js.com</a></dd>
<dt>twitter</dt>
<dd><a href="http://twitter.com/linkibol">@linkibol</a></dd>
<dt>LinkedIn</dt>
<dd><a href="http://linkedin.com/in/volkanozcelik"
>linkedin.com/in/volkanozcelik</a></dd>
</dl>
<p class="clear"><a href="../close" class="close" title="close"
><span>back to home</span></a></p>
</div></body>
</html>
… and that concludes our discussion.
Hey, Wait! Did I Miss Something?! There’s no JavaScript in Here!
While the initial application was using JavaScript to dynamically display the vCard information, this application does not have a single line of JavaScript. That’s totally on purpose.
The former application was displaying vcard info dynamically without requiring a page refresh. That was, of course, a nice feature to have. However, it was totally unusable if the user agent did not have JavaScript enabled. Moreover, the vcard information will not be crawlable by search engines, since it was generated via JavaScript.
Progressively Enhance
So instead, in this article, we implemented a base set of functionality that does not depend on JavaScript. We will be enhancing this functionality with JavaScript in the upcoming articles. That’s called progressive enhancement, and it’s an always-to-keep-in-mind best practice.
Wait for the follow up article, where we will be adding some JavaScript kung-fu into the mix
.
And until then, feel free to share your comments
.





Liked the approach totally, Progressive enhancement, unobtrusive Javascript is the way to move forward.
That’s true; progressive enhancement is the way to go.
Yet, sadly, the state today needs to settle down, to say the least.
I quote Chris’ words here:
”
Almost all the technologies in the stack get washed out in this new web technology world and separation becomes much harder. What good is a CANVAS without any scripting? Should we animate in CSS or in JavaScript? Is animation behaviour or presentation? Should elements needed solely for visual effects be in the HTML or generated with JavaScript or with :after and :before in CSS?
”
It’s true that the web is evolving, and revolving… hopefully to a good point.
And we need to keep in mind that with great power comes great responsibility