greg's blog

Turning a Class into a Service in ZF2

If the class/service requires no configuration you can do this:

1) Ensure the class implements ServiceLocatorAwareInterface.
2) Add/update the service information in the module.config.php

I'll add an example below.

If the service requires configuration you should use a service factory, its not that much more complicated.

Example service-aware class:

<?php

namespace My\Name\Space;

use Zend\ServiceManager\ServiceLocatorAwareInterface,
Zend\ServiceManager\ServiceLocatorInterface;

class TimeService implements ServiceLocatorAwareInterface
{
/** @var ServiceLocatorInterface */
protected $serviceLocator;

// This is set-up during initialization. We don't
// have to call this ourselves
public function setServiceLocator(ServiceLocatorInterface $serviceLocator)
{
$this->serviceLocator = $serviceLocator;
}

Quote From "The Clean Coder"

I'm currently fighting a culture of test last development. So here's some light relief from Bob Martin...

"But isn’t some code hard to test? Yes, but only because that code has been designed to be hard to test. The solution to that is to design your code to be easy to test. And the best way to do that is to write your tests first, before you write the code that passes them."
Robert Martin

Correctly Naming Methods

Method and variable naming is known to be one of the most difficult aspects of software development. The idea is to choose methods that correctly describe the intended purpose of the variable or method to other developers.

This is why developers with good memories sometimes make poor developers. If you can always remember the precise purpose of your variables regardless of the name you choose then you don't have to choose good names.

Often the solution is right in front of you. Here is a very slightly modified example from a well known PHP framework:


/**
* Determine if an instance exists.
*
* @param string|array
* Example: array('canonicalName', 'requestName')
* @param bool $checkAbstractFactories
* @param bool $usePeeringServiceManagers
* @return bool
*/
public function has($name, $checkAbstractFactories = true, $usePeeringServiceManagers = true)
{ ... }

If you want testable code start with TDD

I'm having to deal with unit testing code that has been written in a way that makes it resilient to testing. If the original author had been doing TDD, writing tests first, he'd have realised that his code is extremely difficult to test. The problem is that the code isn't SOLID and uses inheritance over composition, which is the wrong way round. If you need to mock a class you can't use that mock in classes that extend the class you want to mock. If a class uses another class by DI you can always pass in a mock dependency.

Symfony2 Controllers as Services - Remember to change your routes

If you upgrade a controller to be a service you need to change the entry in the routing.yml for each action:

Change

defaults: { _controller: SomeBundle:Api:queueFormSubmissionToService, _format: ~ }

to

defaults: { _controller: someservice.someapi.controller:queueFormSubmissionToServiceAction, _format: ~ }

If you don't change the route then the controller is not run as a service and any dependencies are not injected.

The "Action" part of the controller action method name is only required if running the controller as a service. If you forget it you get the slightly obscure error message:

"The controller for URI ... is not callable."

Use Column Aliases to Annotate Magic Numbers in SQL

Magic numbers embedded in SQL make the query extremely difficut to understand. You can use column aliases to annotate them and make them easily comprehensible!


SELECT ...
LEFT JOIN annotationTypes illustrationNotes ON (annotations.annotationtypeId = illustrationNotes.id AND annotationTypeId = 38)
LEFT JOIN annotationTypes tableOfContents ON (annotations.annotationtypeId = tableOfContents.id AND annotationTypeId = 4)
LEFT JOIN annotationTypes shortDescription ON (annotations.annotationtypeId = shortDescription.id AND annotationTypeId = 2)
LEFT JOIN annotationTypes longDescription ON (annotations.annotationtypeId = longDescription.id AND annotationTypeId = 3)

Softwareburg Uncertainty Principle

With my tongue only slightly in my cheek:

A software development correspondent to the Heisenberg Uncertainty principle:

"The more you know about a project's requirements, the less you know about its time-scales, and the more you know about it time-scales the less you know about its requirements."

So if you're told how long a project will take you can be fairly sure nobody understands precisely what it is supposed to do, and if you know the precise details of what a project is supposed to do you can be fairly sure that nobody has a clue how long it will take. ;)

Professional Software Developer Manifesto

Poor software development standards are fatal for businesses and for the morale of those who have to support bad development.

Every software developer should sign up to minimum standards:

1 Readable Code

Software development is primarily about communicating with other programmers.

2 No hidden knowledge

Other programmers must be able to take over your work without having any missing knowledge. If there is anything any other programmer should know then it must be documented.

One important related area which must be avoided is magic numbers in code. These should never be used and should always have a descriptive textual equivalent (for example an enum or a const) instead.

It is completely unacceptable for a developer to try to make themselves indispensable by any means, such as obfuscating code, using poor names for variables and methods, poor commenting and documentation.

3 Quality Documentation

Risk Management in Software Talent Investment

Quote from Forbes.com "Risk Management in Software Talent Investment" http://www.forbes.com/sites/venkateshrao/2011/12/05/the-rise-of-develope...

"On the flip side — and this doesn’t have a name, perhaps it should be called the “-10x effect” — bad software developers aren’t just a minor drag or inefficiency. For a variety of subtle reasons, they can be catastrophically toxic in a complex software system. A bad engineer writing dangerously buggy or ill-conceived software can create a ticking time-bomb that will cost thousands of times the original investment to clean up after, once it explodes (there’s a phrase for it, “technical debt”). What’s more, the clean-up effort will absorb the efforts of many more good developers."

Unit testing in Zend Framework 2

Unit testing fails in ZF2 Beta 1 if you download the tarball. Use the git repository, this contains the Bootstrap.php and phpunit.xml which are missing from the tarball.

It would be very useful to have symbollic links from the source directories to the test directories so you can quickly update tests and see the interfaces in action.

Lack of proper class method overloading is holding PHP back

The lack of proper class method overloading as found in other languages like Java and C# is holding back PHP's development as a first class language and leading to very clunky code. Here is an example based on Zend Framework 2's Zend\Tag\Item class:
   public function __construct($options)
    {
        if ($options instanceof \Zend\Config\Config) {
            $options = $options->toArray();
        }

        if (!is_array($options)) {
            throw new Exception\InvalidArgumentException('Invalid options provided to constructor');
        }
       $this->setOptions($options);
    }
And here is how it should look:

   public function __construct(\Zend\Config\Config $options)
   {
      $this->__construct($options->toArray());
   }

   public function __construct(array $options)
   {
      $this->setOptions($options);
   }
The latter is so much more elegant but sadly it is not going to work in PHP any time soon.

Setting the title in gnome-terminal

Put this in your .bashrc(s):

export PS1='\[\e]0;`hostname`\a\]${debian_chroot:+($debian_chroot)}\u@\h:\w\$ '

Now whenever you log into a remote machine the title in the gnome-terminal will change to the name of the host. When you log out it changed back.

Very neat!

7 Indicators of good software project management

Here's a very brief summary of what works for me. Take it or leave it:

1. Have a methodology

No methodology implies no path to success. Methodologies are processes and processes are useful in social activities because problems become the fault of the process, and not of the people. It takes discipline and practice to keep to the process.


2. (Almost) The last thing you do is program

This is the failing of most projects. Unless your methodology is to develop software early hold your nerve and don't develop too soon.


3. Think it through first

Think the project through clearly. Many of the pitfalls you would otherwise fall into can be worked out in your head. Design now or face expensive disaster later.


4. Estimate

I Want a goto and I Want it NOW!

This evening I was working on testing some code that is called by AJAX. It returns a string which is either "OK", if everything is fine or something else, if it isn't. If something else is returned the user is alerted.

So to test this I pull it into my test framework - except that the calls to "exit" mess everything up and make the test framework exit too. wget and curl are too clunky so, proceeding with the elegant solution I need to change the code so that instead of exiting it jumps to the end of the script, that way it will return to the test suite even if there is a problem. I'm sure PHP has a GOTO so go look in the documentation - its 5.30 - nightmare!

So instead move the AJAX code into a function and change the exit calls to be returns. Ta-da unit testable AJAX.

Still this is a milestone. The first time in my life I ever wanted a goto.

Syndicate content