Accessing backend system…

We're sorry, but your session has expired due to inactivity. Please use your browser to refresh this page and log in to our system again.

Message goes here.

Message goes here.

Message goes here.

LOGIN / REGISTER
VIEW BASKET
SEARCH:
 
php|architect logo
 
SERVICES
  • MAGAZINE
  • PHP|TEK 2012
  • CODEWORKS 2011/12 TOUR
  • BOOKS
  • TRAINING
  • ADVERTISE
 
CHANNELS
  • NEWS
  • PODCAST
  • DEVELOPMENT
  • OPINION
  • WRITE

What is “the Cloud”

Posted by Cal Evans on October 17, 2011
IN Opinion
Tags:
 

Recently, I attended a panel of local business executives discussing “the Cloud”. Overall, it was an interesting discussion. Since they all managed what we would consider “Enterprise Scale” operations, it was a different viewpoint for me as I spend much of my time talking to smaller scale operations or start-ups.

As the discussion played out, though, it became clear that “the Cloud” meant something different to each of them. This is my problem with the term and why I feel it has become so meaningless as to be a joke in the development community (the term, not the myriad of concepts it has come to represent). For many of the developers I know, the term “the Cloud” is only useful as the butt of a joke or as a drinking game as we saw at ZendCon ’10. The problem is, too many vendors say “the Cloud” when they mean “my services”, and a lot of time, they also mean “not your services”.

Wikipedia has a great page on “Cloud Computing” which is what a lot of – but not all – people mean when they say “the Cloud”. Here’s a short quote that explains where the term actually came from, when it really meant something.

The actual term “cloud” borrows from telephony in that telecommunications companies, who until the 1990s offered primarily dedicated point-to-point data circuits, began offering Virtual Private Network (VPN) services with comparable quality of service but at a much lower cost. By switching traffic to balance utilization as they saw fit, they were able to utilize their overall network bandwidth more effectively. The cloud symbol was used to denote the demarcation point between that which was the responsibility of the provider and that which was the responsibility of the user. Cloud computing extends this boundary to cover servers as well as the network infrastructure

In its most recent incarnation, “the Cloud” has come to mean a combination of distributed computing and virtualization that allows companies to rent the right amount of computing power they need for the moment. In this sense, “the Cloud” is a much more efficient method of allocating computing resources as a company can spin up or down machines almost real-time. From every aspect, economical to ecological, this is better than having to keep hardware warm in case you see a spike.

Distributed virtual computing also encompasses API vendors like Mashery. When you use an API, you are distributing your computing to the servers run by the API vendor. APIs – whether used to fetch data, transform data or manage other services – are an important part of “the Cloud” but lucky for us, they fit nicely into the new definition of distributed virtual computing.

The same goes for any ?aaS vendor (P, S, I, D, etc.). Since these are all part of “the Cloud”, they should be included in any definition. Luckily, all of these fit nicely as distributed virtual computing. As with APIs, any time you are using someone else’s CPU to do your work, you are doing distributing computing, virtual or not. Maybe we just need to narrow the wording down a bit to “distributed computing” because as cool as it is, “virtual” is not necessary to be “the Cloud”.

So now we reach the heat of the matter, what developers refer to as “the Cloud” is really distributed computing. Since the term “the Cloud” really belongs to the Telecommunications industry and is very vague and nondescript, we really should return it to them. What we need to start saying is “distributed computing”. When vendors start hawking services as being “the Cloud” or “cloud-based” and they aren’t part of the distributed computing definition, we really need to call shenanigans.

Words mean things, we need to stop redefining them because it’s convenient or to make our products look better. Read more in the cloud issue of php|architect. :)


Join our mailing list!


We want to talk to you. Yes, you, the PHP programmer reading this; we want to talk to you. Give us a chance. We won't share your email address with anyone, and we promise not to overload your inbox.





About the author—Cal Evans is a veteran of the browser wars. (BW-I, the big one) He has been programming for more years than he likes to remember but for the past [redacted] years he's been working strictly with PHP, MySQL and their friends. Cal regularly speaks at PHP users groups and conferences, writes articles and wanders the net looking for trouble to cause. He blogs on an "as he feels like it" basis at Postcards from my life.
 
 
 

ZendCon 2011: Pre-cap

Posted by Keith Casey on
IN Uncategorized
Tags:
 

Yet again, it’s that time of year. Later today we have the kick off of the seventh ZendCon (officially called the Zend PHP Conference). This year I’m hitting the event under the php|architect banner as press. It will be my job to cover the good, the bad, the news, the chaos, and generally the things that come from the conference that might change your job on a day to day basis.

To get the ball rolling, I’ve picked five sessions that spark my interest:

Scaling PHP Applications with Redis from Josh Butts (Tuesday, 2:45pm) – Josh gave a beta version of this presentation to Austin PHP last week and it was interesting to hear about their (Offers.com) selective transition away from a relational database. He filled the presentation with specific, real-world examples of what problems they’ve had and their solutions.

Event & Signal Driven Programming Techniques from Elizabeth Smith (Tuesday, 4pm) – Many PHPers don’t realize that we actually practice Event Driven Programming in a few key places, so we overlook it constantly. Regardless, there are some incredibly powerful concepts available that you should review for your toolbox.

Dependency Injection: Containers & Frameworks in PHP from Ralph Schindler (Wednesday, 9:45am) – Dependency Injection is a necessity for effective Unit Testing but the “best” approach is a hotly contested topic. I hope to hear Ralph’s recommendations and find out exactly how wrong right he is.

Character Sets Suck from Ligaya Turmelle & Raymond Deroo (Wednesday, 2:45pm) – What can I say? They do.

API Security from Rob Richards (Wednesday, 4pm) – It’s sadly humorous how bad API security is for many organizations. Sometimes they mix up Authentication with Authorization and just hope nobody notices. Sometimes passwords are sent & stored in clear text and most of the time they’re just bad. Regardless, as Rob is from Mashery, I’m looking forward to his broader perspective.

If you browse the ZendCon schedule yourself, you’ll find topics ranging from good OO principles to REST API design to Unit Testing to NoSQL options to Git discussions to Flex intros to mobile and literally dozens of semi-related topics.

I just chose five sessions for me. There’s something for everyone… even if you don’t write PHP.

Disclosure: As noted above, I am covering ZendCon under press credentials. They’re not covering any expenses but we (Blue Parabola) have done business with Zend numerous times and I’ve worked with various Zenders Zendites Zendians over the years, including on previous ZendCons specifically. I’m probably biased one way or another.


Join our mailing list!


We want to talk to you. Yes, you, the PHP programmer reading this; we want to talk to you. Give us a chance. We won't share your email address with anyone, and we promise not to overload your inbox.





About the author—Keith Casey has been a developer for over a decade and helps organize various tech communities. Previously, he was a professional agitator within the Washington, DC until he decided to explore Austin, TX in 2010. To pay the bills, he works as a Developer Evangelist for Twilio to get good tools to good developers so they can build great things. Previously, he built large-scale PHP-based systems for organizations ranging from major news companies to small non-profits. In his spare time, he is a core contributor to web2project, works to build and support the Austin PHP community, co-founded the HubAustin coworking space in South Austin communities, blogs regularly at CaseySoftware.com and is completely fascinated by monkeys.
 
 
 

PHP is not a Swiss Army Knife, quit calling it that.

Posted by Cal Evans on October 11, 2011
IN Uncategorized
Tags:
 

I’ve heard a lot of people compare PHP to a Swiss Army Knife. You know the ones, 5 blades, a corkscrew, a saw…and the obligatory toothpick that you will lose so you might as well take it out now and just throw it away. Why anyone would consider PHP to be like this is beyond me.

A Swiss Army Knife undergoes a lot of design work before it is released. It is well designed, it is engineered, it is purposeful.

A Swiss Army Knife is polished and refined. You never see a brand new Swiss Army Knife with metal burrs on the blade, or scratches on the casing. It’s beautifully chromed and polished.

A Swiss Army Knife is a bit bulky and kind of a pain to tote around just in case you need to saw something less than 2 inches thick. The larger ones are pointless. Who is going to carry that and even if you do, you can’t hold it comfortably to use it.

No, PHP is none of those things, it is not purposefully designed, it is not polished, and it is not bulky.

PHP is a screwdriver. Not a Wal-Mart $2 screwdriver, PHP is the Craftsman screwdriver your grandfather has had in his toolbox for 10 years and will one day be yours.

PHP is ugly. Yes, I said it, and I don’t care. Sometimes PHP’s syntax can be an ugly beast. You don’t like that, go work with a language that is designed for beauty.

PHP is lean…or at least as lean as you want it to be. Have you ever compiled PHP from scratch? If not, I urge you to try at least once. The options you can turn on and off are amazing. You can tailor PHP to your exact needs and leave out everything else.

PHP is useful. Like that old screwdriver, you can drive screws with it, pry open paint cans, clean out gunk from under your fingernails, or flip it around and beat down a stray nail with the handle. When you are done, you just toss it back in the toolbox until the next time you need to get something done. PHP gets out of your way and lets you get stuff done.

Yes, you can do stupid things with PHP, you can with any language. Like pointing a screwdriver at your eye, it’s easy to do serious damage. That’s not PHP’s fault though, that’s your fault, quit blaming the language.

PHP is a more widely used language on the web for one very good reason, when you need to get something done, it’s always there in your toolbox, ready for you to take out, abuse in new ways and then put away. You can carry around a Swiss Army Knife if you want and hope the situation you are in can be solved by one of the 5 blades…or the corkscrew, or you can just pick up a screwdriver and get the job done.

Photo Credit: tnz
Released under CC BY-ND-2.0


Join our mailing list!


We want to talk to you. Yes, you, the PHP programmer reading this; we want to talk to you. Give us a chance. We won't share your email address with anyone, and we promise not to overload your inbox.





About the author—Cal Evans is a veteran of the browser wars. (BW-I, the big one) He has been programming for more years than he likes to remember but for the past [redacted] years he's been working strictly with PHP, MySQL and their friends. Cal regularly speaks at PHP users groups and conferences, writes articles and wanders the net looking for trouble to cause. He blogs on an "as he feels like it" basis at Postcards from my life.
 
 
 

Opinion: Why Software Fails

Posted by Marco Tabini on October 10, 2011
IN Opinion
Tags: architecture · design
 

What makes software fail? A lot of software projects are outright failures: botched feature specs, missed deadlines, poor functionality, security holes, and so on.

But there is a much subtler category of failure that is much harder to spot and address: the lack of usefulness.

Just last week, I took my car in for maintenance—nothing special, just an oil change and a tire rotation. Now, I’ve taken my cars to the same shop for at least ten years, and they’re usually quick and efficient, as they should, given that these are routine tasks that any mechanic should be able to handle—well, quickly and efficiently.

This time, however, things were distinctly different: the shop had switched from its old, terminal-based computer system to a new, “more modern” system based on a GUI operating system that shall remain unnamed.

What a disaster! The shop’s productivity had dropped dramatically as the techs struggled to figure out how each part of the new software worked and made mistake after mistake, resulting in frustration on both sides of the counter.

Clearly, that software is a working failure: it probably performs the tasks that it was designed to perform, but not in a way that actually helps its users do things more easily and more quickly.

This is a much more common problem than engineers and architects are willing to admit. Far too often I see someone in charge of writing a piece software worry about how a product works without paying so much as a passing thought to whether it actually works the way people expect it to.

The truth is that we are, by and large, stuck in a reality where software somehow equates with automation. We worry about speed, performance, and scalability, and see our job as that of simply providing a tool that makes a repetitive task easier.

This approach, however, betrays a dangerous underlying assumption: that the user already knows how to perform that task—which, unfortunately, is almost never the case.

Take, for example, time-management software. There must be thousands of to-do apps out there, written for just about any platform imaginable.

It’s easy to see why: on the surface, writing a to-do list application is a simple problem that pushes many of a programmer’s favorite hot buttons: data storage, synchronization across multiple devices, perhaps even a touch of user-interface design.

You’d think, with all these thousands of programs at our fingertips, that the whole of humanity—or at least that portion of it who has access to computers—would have, by now, become perfectly organized.

But they haven’t.

You see, the problem that people have is not one of automation: it takes all of a piece of paper and a pencil to handle a to-do list; in fact, I would argue that’s even more portable than just about any piece of software you can write.

The reason why people can’t get organized is much simpler: they don’t know how.

Now, obviously that’s a much harder nut to crack. How do you write software that teaches people how to become more organized? I suspect that even the experts wouldn’t know where to get started.

Yet, that’s exactly the kind of problem that to-do lists should solve, and they pretty much all fail miserably at the task, even though they are perfectly functional software programs.

And that, more often than not, is why software often fails while being perfectly successful: because it simply automates instead of encapsulating knowledge that goes beyond the user’s own.


About the author—Marco is the keeper of keys and Chief Garbage Collector at Blue Parabola, php|architect's parent company. He can be found on Twitter as @mtabini.
 
 
 

Accessibility

Posted by Beth Tucker Long on October 5, 2011
IN Uncategorized
Tags:
 

I was recently reminded of a talk I heard back in 2008 at php|works in Atlanta. Eric David Benari gave a great talk on usability and accessibility for sites, and even though this was quite a while ago, the talk topic remains relevant today. One of the main things that I got out of that talk was how the front-end formatting affected disabled visitors. This struck home for me as years earlier, I had volunteered at the Experimental Aircraft Association’s yearly convention. One of my duties was leading tours for the Blind Veterans’ Association. This included riding around on a tram with them outlining everything I could see in great detail. It also included taking them through various planes and helping them feel/listen their way through the tour.

Photograph by Don Norman of his personal coffeepot.

Photograph by Don Norman of his personal coffeepot.

After several years of doing this, I had gotten to know several of the veterans pretty well. One year, one of the veterans, Dale, knowing that I was “into all that computer stuff”, proudly displayed his new laptop. “Bet you’ve never seen a computer like this,” he said, and he was right. I had never seen a computer for the blind. I’m a little embarrassed to admit that it had never occurred to me that such a thing might even exist. It was shaped like a normal laptop, but instead of a screen, it just had a plastic cover to protect the keys. Everything was vocalized to the user. Watching him use the laptop, I realized how much the front-end design affects a non-visual browser, but at the time, I wasn’t involved in programming yet so I didn’t know what could be done about it.

Fast forward about ten years, and I had begun working in web design, programming in PHP and attending php|works. As I sat in Eric David’s talk listening to him outline the disability accessibility guidelines, I realized that I could now make a difference to users like the Blind Veteran’s Association. I have been hooked ever since. Ask Cal, I am always harping on alt tags on images. Ask anyone who has taken my Essentials PHP course; I am relentless on good error reporting in web forms. Ask all the designers I’ve annoyed over the years because I insisted they use text instead of graphics for the content of the site.

I honestly believe these little things add up to a big improvement in usability and quality. Not only that, but these improvements help your search engine ranking and the mobile accessibility of your site too. So next time you are working on a project, consider making sure your site is easily accessible to your disabled patrons. Not sure where to start? Check out the W3C-WAI Web Content Accessibility Guidelines.


About the author—Elizabeth Tucker Long is the Editor-In-Chief of php|architect magazine as well as a trainer and occasional guest blogger for php|architect. She also runs Treeline Design - http://www.treelinedesign.com, a web development company, and Playlist Event Music - http://www.playlisteventmusic.com, a DJ company, along with her husband, Chris, and son, Liam.
 
 
 

Building the Backside – Part 2

Posted by Cal Evans on October 4, 2011
IN Uncategorized
Tags:
 

Down the Rabbit Hole

The moment you’ve been waiting for, let’s dive into the code. The application has two basic functions, the first is the login and the second is to fetch sales numbers. Since those are very different, we will need two different controllers. While we are only concentrating on the actual code necessary to build out this particular functionality, there’s no sense in not doing it right.

Let’s use Zend Tool to create our controllers

zf create controller User

zf create action login User

zf create controller Sales

zf create breakdown Sales

Thinking back on the early days of Zend Framework (I started working with it at version 0.02), the work that those 4 commands just did would usually have taken 10 minutes.

Ok, now we have everything we need to proceed.

Putting It in Context

The first thing we need to do in each of our controllers is set the context. In this application, we will never deliver anything other than JSON. Therefore in the _init of each, we use the Context Switch action helper to make sure of that.

public function init()
{
	$this->_helper->contextSwitch()
	->addActionContext('breakdown', array('json'))
	->setAutoJsonSerialization(true)
	->initContext('json');
	return;
}

Once set, we never have to worry about it again.

This step is not technically necessary. I show it to you here mainly so that you understand how context switching is handled. This will make sure that the

'Content-Type' 'application/json'.

header is set and will use the *.json.phtml view script. If we were building an application that had multiple contexts (XML, HTML, XML, any other *ML you can think of) then this would be necessary. However, in our case, we are only using JSON, and as you’ll see at the end, there is an easier way.

Logging In

The point of this application is to simply allow the client application to pull out the sales figures. The login system on php|architect’s back end is quite a bit more complex than we care to replicate here, so I’ve just dummy-ed up code here so that it will work. There is, however, one concept demonstrated here that you need to pay attention to.

public function loginAction()
{
	$commonSession = new Zend_Session_Namespace('common');
	$commonSession->token = null;
	$data = $this->_request->getParam('data');
	$data = json_decode($data);

	. . . Auth Code Goes Here . . .

	session_regenerate_id(true);
	$commonSession->token = md5(session_id().$data->t.$_SERVER['REMOTE_ADDR']);
	$payload = array();
	$payload['f'] = false;
	$this->_helper->json($payload);
	return;
}

The bold lines are the important ones. I store the authenticated token in a ‘common’ namespace. If you are using Zend_Auth to authenticate, you can use a separate namespace to store the authentication credentials if you like. The very first thing I do upon login is clear out any old tokens. If someone is already logged in, they shouldn’t be calling the /user/login action a second time. If they are, something may be wrong so let’s clear it out.

Next, you do whatever you do to authenticate the client. Then, immediately regenerate the PHP session if it is successful. If the person does log in again successfully, you will want them to have all new data and not use old data. The TRUE in the session_regenerate_id(true) line tells PHP to remove the old session file. Since it may have sensitive data stored in it, you don’t want to keep it around.

Finally, create a new token. In this case, I took 3 pieces of data that should always remain constant and one of them came from the client. I concatenate the PHP session id, the token passed in from the client, and the IP address of the client. I store the MD5 of the three in the PHP session as the token. Now, with each action, as long as those three pieces of information do not change, I can know that the person has already logged in.

Beyond that, we simply return a payload to the client that will make it think that it has properly authenticated.

Digging the Data

Now that the client has properly authenticated, we need to give it the data that it wants. In the Sales controller, we have the breakdown action which is the central entry point for the data request.

As with /user/login, it takes as its payload an element called ‘data’. This element contains a JSON-encoded object with the data we need to execute the query. We take that payload in and decode it. However, before doing anything else, we need to recalculate our token and make sure we are talking to the same user. Once that has passed, we can move ahead with executing the query and returning the payload. If the token fails, we prepare the payload with a message telling the client what is wrong, and set the fail flag to true.

If the token passes, the very first thing we do is filter our data. We do not validate it because honestly, I don’t care if the dates are valid or not, what comes out of the filtering process will be valid dates, even if they have no data corresponding to them. Countries, handlers and SKUs are arrays that we can filter with Zend_Filter_Alnum, since these arrays would never contain anything other than alphanumeric characters.

Originally, I was using Zend_Filter_LocalizedToNormalized() to filter the date and put it in a format MySQL can use. However, the format in which they are presented proved a little too difficult for that class to parse properly (or maybe it was just me). Either way, strtotime() does a great job of parsing the date passed in and converting it to a timestamp. Once in timestamp format, PHP’s date() function converts it back into a date and allows us to specify the exact format we need.

Finally, we grab an instance of the default database connection. Zend Framework is wonderful at making things like this very easy.

We instantiate a copy of the SalesReporter object. The constructor of SalesReporter accepts the $db object and stores it for later use. Now we just have to call fetchSales(), passing in the array of filtered parameters that we built earlier.

Database Dance – Reprise

Ok, we have now arrived at the heart of the code, the SQL statement necessary to tell the database what data to fetch for us. I am an old database guy. I prefer hand coding my SQL as opposed to letting the code figure it out. However, Zend Framework has an interesting OO interface to do this, so I thought I would give it a try. I was pleasantly surprised by the results.

The database is basically 3 tables: order, orderitem and address.

<
p class="c3">For our purposes, the controlling table is orderitem; that is where the transaction line items are stored. We get the price, quantity, SKU, and product name fields from that table. The field “handler “ equates to category. Since we sell several different types of products at php|architect, we like reports broken out by category.

All reports are based on date ranges so we have to include the order file so we can get the timestamp (ts) for the order. Finally, one of the reports breaks the data down by country. To get the country of the person ordering the product, we have to pull in the address table.

With all the options, the SQL query will look something like this:

SELECT *
  FROM orderItem oi
             INNER JOIN `order` o ON oi.orderId = o.id
 WHERE state=11 AND
             ts BETWEEN '2011-08-01' AND '2011-08-24' AND
             handlerName IN ('MagazineHandler') AND
             sku IN ('phpa') AND
       uid IN (SELECT uid
 FROM address
       WHERE country IN ('US'));

As SQL statements go, not terribly difficult. Now to build this in Zend Framework’s Zend_Db_Select syntax, we get something that looks like this:

$select = $this->_db->select()
                    ->from(array('oi'=>'orderItem',),
                           array('oi.price',
                                 'oi.quantity',
                                 'oi.sku',
                                 'oi.productName')
                                      )
                    ->joinleft(array('o'=>'order'),
                               'oi.orderId = o.id',array())
                    ->where('o.state=11')
                    ->where("o.ts BETWEEN
                               '{$parameters['startDate']}' AND
                               '{$parameters['endDate']}' ");

if (is_array($parameters['handlers']) and
	!empty($parameters['handlers'])) {
$select->where('oi.handlerName IN
 				(?)',implode(',',$parameters['handlers']));
}

if (is_array($parameters['skus']) and
    !empty($parameters['skus'])) {
$select->where('oi.sku IN
                (?)',implode(',',$parameters['skus']));
}

if (is_array($parameters['skus']) and
    !empty($parameters['skus'])) {
$select->where('oi.sku IN
               (?)',implode(',',$parameters['skus']));
}

if (is_array($parameters['countries']) and
    !empty($parameters['countries'])) {
$select->where('uid IN (SELECT uid
		FROM address
        WHERE country IN
               (?))',implode(',',$parameters['countries']));
}

Now honestly, the SQL guy in me cringes at that a little. Until I begin to realize that to do the same thing, I usually end up concatenating a big string. When building SQL statements dynamically like this, it actually makes more sense to do it programmatically. That was the surprising thing to me, after railing against this very concept for a long time, when I sat down and used it the first time, it actually did make more sense.

…And the Rest

The rest is easy. Fetch the records, and return them to the controller. The controller puts them in the outgoing payload and returns the json encoded payload to the client. Again, this is an area where Zend Framework shines. Returning the payload as JSON requires a simple command:

$this->_helper->json($payload);

Since I set the context switching in the _init(), I could also tell it that XML or even HTML were valid contexts. Doing so, however, would mean that I would have to create view scripts for each method/context. In the case of JSON, I could have created vies/scripts/sales/breakdown.json.phtml and manually created the json payload inside of it. The same would go for XML if I had enabled XML, I would have had to create breakdown.xml.phtml and manually formatted the XML output.

However, as we discussed in the Context section, there is an easier way, and that is the line above. This JSON Action helper outputs the proper Content-Type header, turns off view scripts totally and returns the payload json encoded.

fClose()

We have now completed the journey. If you did not download the source code file, I trust you realize that I left out a few lines of code that you will have to fill in yourself.

Flash Builder, with its built-in support for Zend Framework and PHP means that it is even easier now to create both the front end and the back end of a product in a single editor. When you add the Zend Studio module and Zend Server, then it gets even better because you can step through problems as they happen instead of just putting a lot of file_put_contents() and Zend_Debug::dump() statements in your code and hoping to locate the problem. Nobody does that anymore…it’s just silly…right?


About the author—Cal Evans is a veteran of the browser wars. (BW-I, the big one) He has been programming for more years than he likes to remember but for the past [redacted] years he's been working strictly with PHP, MySQL and their friends. Cal regularly speaks at PHP users groups and conferences, writes articles and wanders the net looking for trouble to cause. He blogs on an "as he feels like it" basis at Postcards from my life.
 
 
 

This month's issue

January 2012
Buy · $5 — Subscribe · starts at $35
 

 

Upcoming Training Courses

Course Start Date
Essential PHP 2012-02-03
AJAX Programming with PHP and … 2012-02-10
Essential Zend Framework 2012-02-17
Mobile HTML5, JavaScript and P… 2012-03-02
Professional PHP Development 2012-03-09
 

About us

  • What we do
  • Contact us
  • Write for us

Policies & legal

  • Customer support
  • Privacy policy
  • Refund policy
  • Terms & Conditions

Online Store

  • Magazine
  • Training courses
  • Books

Special sections

  • Codeworks 2011
 

Copyright © 2002-2012 Blue Parabola, L.L.C. — All amounts in USD - WP3