Thursday, July 31, 2008

Development/Integration/Staging/Production

See Development/Integration/Staging/Production at its new home on bradley-holt.com.

I am surprised by how many developers think it's OK to do work directly in a production environment or to deploy to production directly from their development environment. I found a good article today that explains the traditional Development/Integration/Staging/Production practice. The specific setup may be different depending on your environment, but the basic ideas are the same.

Wednesday, July 30, 2008

Social Capital in Free/Open Source Software Projects

See Social Capital in Free/Open Source Software Projects at its new home on bradley-holt.com.

A colleague of mine recently introduced me to the concept of social capital. Many organizations these days value human capital but I'm not sure how many value the social contacts between people involved in the organization. This raised the following question for me: I wonder how much of the success around free/open source software projects can be attributed to the generation of social capital? There are all sorts of technical reasons people will give as to why free/open source software is "better" than proprietary software but has anyone looked at it from a social perspective? I wonder if this is the real importance of Stallman's four freedoms - that they provide the opportunity for the creation of social capital?

I did some Googling and discovered an academic paper called The Influence of Structural Social Capital on Open Source Project Success. It was very interesting but I must admit I didn't read all of it as it gets rather technical towards the end. Here is a summary of the results:

Our main results are (1) teams with greater internal cohesion are more successful, (2) external cohesion (cohesion among the external contacts of a team) has an inverse U-shaped relationship with the project's success; moderate levels of external cohesion are the best for a project's success, rather than very low or very high levels of this variable, (3) the technological diversity of a contact also has the greatest benefit when it is neither too low nor too high, and (4) the number of direct and indirect external contacts are positively correlated with a project's success with the effect of the number of direct contacts being moderated by the number of indirect contacts.

Monday, July 28, 2008

Dependency Injection in Zend Framework

See Dependency Injection in Zend Framework at its new home on bradley-holt.com.

Ibuildings has an article on Dependency Injection and Zend Framework Controllers. In the comments, the Zend_Di proposal is mentioned. I had posted several comments when the Zend_Di component was proposed. Most of my comments were ideas on how to make a dead-simple dependency injection container for Zend Framework. Zend Framework prides itself on simplicity and, in my humble opinion, if Zend Framework is going to have a dependency injection component this component needs to be as simple as possible - something along the lines of PicoContainer. So, I'd like to summarize my thoughts here. I should probably just write a proposal, but I'd like to start here and see what kind of feedback I get.

For the purposes of this blog entry, I'll call this component Zend_Container (I apologize if this name has been proposed for any other components). First, some basic assumptions:

  • The component's primary purpose is to replace the use of class-managed singletons and Zend_Registry.
  • The component will only manage singleton items within a container, it will not act as a factory (except for creating the single instance).
  • A container can have zero or one parent container and have access to items in its parent, but a parent cannot have access to items in its children.
  • The component uses reflection to determine dependencies.
Below is an example of a class that will have its dependent items injected:
class Zoo {

/**
* @var Feline
*/
protected $_feline;

/**
* @var Canine
*/
protected $_canine;

/**
* Sets the Feline for the Zoo to have.
*
* @param Feline $feline
* @return void
*/
public function setFeline(Feline $feline) {
$this->_feline = $feline;
}

/**
* Sets the Canine for the Zoo to have.
*
* @param Canine $canine
* @return void
*/
public function setCanine(Canine $canine) {
$this->_canine = $canine;
}

}
Here is an example of wiring up dependencies:
$container = new Zend_Container();
//note the ability to specify class or interface and class
$container->addComponent('Zoo')
->addComponent('Feline', 'Tiger')
->addComponent('Canine', 'Wolf');
$zoo = $container->getComponent('Zoo');

//the above is equivalent to (assuming setter injection)
$feline = new Tiger();
$canine = new Wolf();
$zoo = new Zoo();
$zoo->setFeline($feline);
$zoo->setCanine($canine);
An example of parent/child relationships:
$rootContainer = new Zend_Container();
//passing in the root container so the child is aware of its parent
$childContainer = new Zend_Container($rootContainer);
//note again that we can add either class or class and interface
$rootContainer->addComponent('SomeClass');
$childContainer->addComponent('SomeClass');
$instanceA = $rootContainer->getComponent('SomeClass');
/*
Child containers should have access to their parent's components (but not the other
way round) so if we hadn't added the component specifically to the child container
this next line would have given us instanceA.
*/
$instanceB = $childContainer->getComponent('SomeClass');
echo (int) ($instanceA === $instanceB); // echoes "0" (false)
There is one major problem that I have not figured out. Reflection is used to determine potential dependencies. The container then would look to see if it (or its parent) contains the dependency and if it does, wire it up, otherwise ignore it. In other words, there's no way to assert that a component is a required dependency. Perhaps this could be solved through the use of an @required DocBlock tag if this can be read using PHP's reflection mechanism. There could also be a configuration option that would simply make your addComponent calls for you.

Friday, July 25, 2008

Easy Way to Run Web Applications Locally

See Easy Way to Run Web Applications Locally at its new home on bradley-holt.com.

I've been trying out a new way to run web applications on my local machine. Since I work on many different websites I like to be able to run these sites on my local machine. This lets me try out changes locally before committing them to Subversion and rolling them out to a staging or production environment. In the past I've simply created a new virtual host in Apache listening on its own port. The problem with this is that not only do I need to manually setup each new site, I also need to remember which site goes with which port number.

So, I've started using Apache's dynamically configured mass virtual hosting. This gets me two things. First, I don't need to make any changes in Apache's configuration file when I want to setup a new local web application. Second, I now have an easy-to-remember naming convention for sites that are running locally. This works really well for me, but your mileage may vary depending on your specific needs. There are also other tools that can help you accomplish similar results, but I like the simplicity of this in that it doesn't require anything other than Apache and some DNS settings.

Let me explain the end result first, and then I'll explain how I got there. For each website I work on I use the subdomain to indicate the environment it's running in. Using the domain example.org we may have the following environments setup:

  • local.example.org - the local copy
  • beta.example.org - a semi-publicly available beta
  • www.example.org - the live site
The beta and www versions aren't anything special, just normal websites. For local.example.org I need to have a DNS entry that points to the loopback address, 127.0.0.1. This can either be a publicly available DNS entry (which could be a little awkward) or simply set in your hosts file. I've simply made the entry in my hosts file:

127.0.0.1 local.example.org

The downside of this is that you would need to update the host file on each machine that you wanted to run the local.example.org site on. A comprimise would be to run your own recursive DNS service that only your computers used and make the DNS entries there.

This next step only needs to be done once. The dynamically configured mass virtual hosting article explains in detail how to set this up. My Apache configuration looks something like this:

VirtualDocumentRoot /path/to/workspace/%2+/public

Again, your specific configuration may be different. When making a request to http://local.example.org/ the document root would expand to /path/to/workspace/example.org/public. This assumes that you have placed all of your projects in the same location and they all have a similar directory layout (I'm using Zend Framework's directory layout). I think there's a way to do this in a way that's more flexible, but I haven't had the need. Let me know if you have any questions!

PHP Users Group at VCET

See PHP Users Group at VCET at its new home on bradley-holt.com.

Last night's PHP Users Group was at the Vermont Center for Emerging Technologies (VCET) in Burlington. Adam Bouchard gave us a demo of Springloops - a service that helps you deploy web applications (among other things). Rob Riggen and Aaron Carlino gave us a presentation on the Symfony web framework. We had a smaller turn-out than usual, but that's not suprising for a summer meeting. Next month we're going to have a presentation on Flex by someone from Adobe - more details to come.