In my Beyond Frameworks talk, I explained how a component-based architecture can help answer some of the important (i.e. expensive!) questions you might face when creating long-lived apps that rely on a PHP framework. In this series of blog posts, I’m going to look at how to go about creating and working with components.

In the last article, I set out some very simple requirements for my example app. Now that I have an idea of what I want to build, I need to break that down into a set of components to create. My apologies if you’re keen to jump straight to the code; it’s coming soon, and I want to make sure it’s the right code when we get there 🙂

Thought Process: Decomposition

Decomposition is all about figuring out how to chop up a large problem into a co-operating sets of smaller problems. If you get the boundaries right across the set, then you can solve each of the smaller problems on their own, glue it all together, and job done.

In a traditional PHP app, decomposition normally means getting into class design. When you’re working with components, you need to decide how you’re going to group those classes together into components.

Figuring out your list of components and their contents very much a creative process. I’m a visual person, so I do it by scribbling on whiteboards or moving things around in OmniGraffle. There are few right or wrong solutions – most ‘wrong’ solutions are really just philosophically differences between people – but there are a few important questions that I ask myself to avoid problems later down the road.

Questions When Decomposing To Components

When I’m deciding what should be grouped into components, I’m always asking myself these questions:

  • Does the component do one job, and do it well?

    This is the key question. Just like classes that have too many responsibilities become too complex to both use and maintain, the exact same trap lies in wait when you start designing components, just on a larger scale.

    Take a look at the components that phix is made up of, by reading its package.xml file. Each of those components does one job, and only one job. phix glues them all together, but you could take any one of those components, and use it to solve the same problem in a different app.

  • Is it clear which components relies on which?

    A good feel-good factor for deciding whether you’ve got the right components or not is how easy it is to compile a list of which components your app relies on, and which components in turn they rely on. If you feel any doubt or uncertainty, then listen to your heart, and carve up the code into a different set of components.

    Ultimately, you need to be able to fill out your component’s package.xml file with a definitive list. Take a look at ComponentManager’s package.xml file as an example. It clearly states every component that ComponentManager glues together.

  • Do two components mutually depend upon each other?

    One of the key benefits of creating components is being able to isolate change. If I change Component A, I might have to change Component B too, because I’ve broken backwards compatibility. That doesn’t cause any architectural problems. Now, if I change Component B, and then have to change Component A too, then that is a very important problem. You have to install components one at a time. Which one do you install first?

    This problem can also appear in more subtle ways, when you have three or more components that rely on each other, for example when Component A relies on Component B, Component B relies on Component C, and then Component C relies on Component A.

    This is an easy one to work out. Draw out the list of components as a graph, connecting up which components rely on which. If you end up with a tree, you’re fine. If your graph has cycles, you’ve got a problem that needs to be fixed. You can’t reliably install components with mutual dependencies.

  • Is there any shared code I can split out into its own component?

    One way to solve the interdependence problem between Components A and B is to move some of the functionality out into a Component C, and then have both Components A and B rely on that, instead of each other. This is also one way of achieving DRY: Don’t Repeat Yourself.

    An example of this can be seen in the ComponentManagerShared component. Both ComponentManagerPhpLibrary and ComponentManagerPhpDocbook rely on it, but they don’t need to rely on each other at all.

  • How is someone going to install and upgrade this component?

    What I’m asking here is: will the component be listed in the <dependencies> section of a component’s package.xml (or an app’s!), or will a user install the component for himself by running the pear command? Or maybe both?

    Sometimes, you’ll want to introduce a meta-component into your design to make it very easy to install and upgrade a larger collection of components.

    ComponentManager is a meta-package; all it does is pull in all the other components that support creating and managing specific types of components. Every time I find and fix a bug, or add a new feature, the bug fix or feature goes into one of the specific components (such as ComponentManagerPhpLibrary) … but you don’t need to keep track of them all. All you have to do is pear upgrade phix/ComponentManager, and it takes care of upgrading all of the other components for you.

  • Where will your component be installed?

    Components can be installed into two places on a computer: system-wide (e.g. /usr/share/php), or inside an app (e.g. vendor/ folder inside the app’s code tree). Does the component work in both places?

    This is a question I personally wish the Doctrine developers had asked themselves. At the time of writing, Doctrine assumes that it will only be installed system-wide, making it a real pain in the backside if I want to run two or more separate apps that use Doctrine on the same server. By forcing me to install Doctrine system-wide, they also force me to test (and potentially fix) all apps that use it in one go whenever I need to upgrade Doctrine.

    The components built using ComponentManager can easily support installing into both system-wide or inside an app to suit your choices, and I’ll show you exactly how that is done when we get there.

  • Can I get this functionality from an existing component from someone else?

    Or, put another way … am I re-inventing the wheel here? Or living my not-invented-here dreams?

    Today, PHP components are at an embryonic state compared to our cousin languages. There aren’t all that many out there, and support for the PSR0 autoloading standard is still to become widespread.

    That said, you should still take a look first before deciding to build your own component. Folks like the Symfony 2 community seriously get components, and are doing a great job in publishing high-quality code that might just suit your needs.

  • Am I ever going to re-use this code?

    I’ve saved the most important question for last. Is it worth the trouble? There isn’t much practically in creating a component for the sake of it. If you can’t see yourself (or anyone else) ever re-using the code, put the code inside another component (or your app) for now. You can always break it out into a component at a later date.

    This is exactly what I did with phix. It started off as a single PEAR-compatible package, and as it evolved, I extracted out more and more code into separate PEAR-compatible packages when I felt it was worth doing so.

These are all questions about how to organise the code, and it’s this organisation – this list of components and their dependency graph – that then affects the design of the code inside each component. It’s good to start out with a plan, but don’t get hung up on it. As you build the code, and learn to feel what it’s like to live with the list of components, you’ll probably want to make changes to make life easier. There’s nothing at all wrong with that.

So what could the component list for my example app look like?

Component Design For The Sentiment App

If I apply these questions to the app I’m building in these blog posts, I end up with:

Components by type …

  • The orange components are going to contain useful code. Either I’m going to have to create them (sental, sentalXmlStore, repustateApi, lymbixApi, rssFeeder) or they already exist (phix, phix’s dependencies).
  • The green components are meta-packages, to make it easy to manage creating and updating the code (sentalApis, sentalFeeders).
  • The blue component contains shared code (sentalApiShared). It’s going to contain the interfaces that all the APIs will have to implement, and will also hold any base classes or utilities that the APIs are likely to find useful.

I’ve decomposed my requirements from this morning into a list of named components to tackle. Whether it’s the right list or not is too early to tell – there’s always more than one design that will work – but this is what I’m going with for now.

For the rest of this week’s blog posts, I’ll focus on creating the repustateApi component. Code at last 🙂 And that should just about (fingers crossed!) give me enough time at the weekend to fill in some of the other components before we pick things up again on Monday 🙂

Be the first to leave a comment »

In my Beyond Frameworks talk, I explained how a component-based architecture can help answer some of the important (i.e. expensive!) questions you might face when creating long-lived apps that rely on a PHP framework. In this series of blog posts, I’m going to look at how to go about creating and working with components.

Components don’t exist entirely in isolation. They’re built to solve a specific problem, and ultimately to get used inside some sort of application (or two). To help explain one way to approach designing and building components, blog post by blog post I’m going to create a real app and its components, showing you the workings involved and highlighting any decisions that were made along the way. All the code will appear on GitHub, so that you can tinker with it yourself too.

If you want to jump right in and figure it all out in your own way by taking existing code apart, phix and the now-separated-out ComponentManager are both built as components in their own right. Clone the git repos, look at the phing targets in the build.xml files, and have a play. Poke me on Twitter if you have questions. If/when you run into issues, please file them on GitHub, and I’ll get them fixed for you.

Hopefully you’re staying with me for the worked example app though 🙂 I’m going to start by defining what the final app needs to do.

App Requirements

I need an app that will consume a bunch of blog posts off the ‘net, and summarise for me how many are positive articles, and how many are negative articles. I’m going to use the data in future strategic planning sessions at work, to add another perspective where it will be useful. The app can be easily changed in future to analyse other data … I’m thinking of feeding it Flickr feeds too at some point, to give my photography some much-needed feedback.

Here’s how I’d summarise the technical requirements for this app:

  • The command-line portion of the app will do the analysis, running off a cron job.
  • The command-line portion will analyse a list of RSS feeds loaded from a .ini file.
  • The command-line portion will use a web-based API to score each blog article. The value of zero will be neutral; positive numbers mean the article is positive in tone, and negative numbers mean that the article is negative in tone.
  • The command-line portion will cache the results as XML files on disk (just to keep the example simple).
  • The website part of the app will present the analysis, consuming the summary data created by the cron job.
  • The app will be built as components, to make it easy to share code between both parts of the app.

That should give us enough variety to be able to get into some non-trivial examples.

With a very basic set of requirements documented, before I go near any code, my next step is to figure out a rough structure. I need to decompose my requirements into an architecture. That will be in the next blog post, which will along this evening.

Be the first to leave a comment »

In my Beyond Frameworks talk, I explained how a component-based architecture can help answer some of the important (i.e. expensive!) questions you might face when creating long-lived apps that rely on a PHP framework. In this series of blog posts, I’m going to look at how to go about creating and working with components.

phix is a generic command-line tool that I recently released with support for creating and managing several types of PHP components. phix was always intended to be a framework-agnostic environment for easily creating and running CLI apps, and to keep that goal pure, I’ve separated the tasks for creating and updating PHP components out of phix into their own components.

This allows phix itself to be developed and improved on its own, and for the support for each type of component to move forward at their own pace. And, for an immediate practical benefit, it means that the 14 megabytes needed for the php-docbook component support doesn’t have to be downloaded every time we fix a bug elsewhere.

There’s a new PEAR-compatible package now, to keep up to date with support for the different types of components, called ComponentManager.

How To Install ComponentManager

If you haven’t installed phix before, you only need to install ComponentManager. It will pull in phix as one of its dependencies:

pear channel-discover pear.gradwell.com
pear install Gradwell/ComponentManager

How To Upgrade From phix-0.10

To upgrade from phix-0.10, just run the following:

pear upgrade Gradwell/phix
pear install Gradwell/ComponentManager
Be the first to leave a comment »

Introducing phix

Posted by Stuart Herbert on March 21st, 2011 in 1 - Beginner, phix, Toolbox.

In my Beyond Frameworks talk, I explained how a component-based architecture can help answer some of the important (i.e. expensive!) questions you might face when creating long-lived apps that rely on a PHP framework. In this series of blog posts, I’m going to look at how to go about creating and working with components.

This page has been updated with the latest information about phix.

phix is a small command-line tool for PHP applications. I created it to fix (pun intended) the problem of how to easily automate the tasks involved in creating and (especially) maintaining components. These tasks aren’t built into phix; they are commands that ship with the phix distribution. You can create your own commands to run inside phix too, and it’s easy to do so.

Installing phix

There are full installation instructions for phix on the phix project’s website.

What Can phix Do?

Running phix without any command-line parameters gives us a basic overview of what it can do:

phix 0.13.2 - http://www.phix-project.org
Copyright (c) 2011 Stuart Herbert and contributors
Released under the BSD license

SYNOPSIS
    /usr/bin/phix [ -?dhv ] [ --? --debug --help --version ] [ -I<path> ] [ 
    --include=<path> ] [ command ] [ command-options ]

OPTIONS
    Use the following switches in front of any <command> to have the following
    effects.

    -? | -h
        display a summary of the command-line structure

    -I<path> | --include=<path>
        add a folder to load commands from

        phix finds all of its commands by searching PHP's include_path for PHP
        files in folders called 'PhixCommands'. If you want to phix to look in
        other folders without having to add them to PHP's include_path, use
        --include to tell phix to look in these folders.

        phix expects '<path>' to point to a folder that conforms to the PSR0
        standard for autoloaders.

        For example, if your command is the class 'MeToolsPhixCommands
        ScheduledTask', phix would expect to autoload this class from the 'Me
        /Tools/PhixCommands/ScheduledTask.php' file.

        If your class lives in the './myApp/lib/Me/Tools/PhixCommands' folder,
        you would call phix with 'phix --include=./myApp/lib'

    -d | --debug
        enable debugging output

    -v | --version
        display phix version number

    --? | --help
        display a full list of supported commands

COMMANDS
    help                    # get detailed help about a specific phix command
    pear:expand-package-xml # expand the tokens and contents of the
                              PEAR-compatible package.xml file
    pear:register-channels  # register the channels for the dependencies
                              listed in the PEAR-compatible package.xml file
    php-library:init        # initialise the directory structure of a
                              php-library component
    php-library:status      # check the status of a php-library component
    php-library:upgrade     # upgrade the structure of a php-library component
                              to the latest version

    See /usr/bin/phix help <command> for detailed help on <command>

phix ships with easy-to-use commands for creating and maintained packaged components of PHP code. Additional commands will be added in the future!

You can add your own commands to this list with minimal effort, something we’ll look at in a later blog post. By default, phix searches your PHP include_path for new PhixCommands namespaces to load; you can also use the -I flag to tell it to search a specific PSR-0 compatible class tree if needed.

And the best thing of all is that phix is framework-agnostic; it isn’t going to break as you upgrade or change frameworks – an important requirement for creating and working with components!

Self-Documenting

phix comes with a built-in help command to show you what any single command can do. And best of all, it automatically tells you where the code is for that command, so if something isn’t working or you want to enhance it, you don’t have to wonder where phix is getting the code from:

$ phix help php-library:init
NAME
    /usr/bin/phix php-library:init - initialise the directory structure of a
    php-library component

SYNOPSIS
    /usr/bin/phix php-library:init <folder>

OPTIONS
    <folder>
        <folder> is a path to an existing folder, which you must have
        permission to write to.

IMPLEMENTATION
    This command is implemented in the PHP class:

    * Phix_ProjectComponentMakerPhixCommandsPhpLibraryInit

    which is defined in the file:

    * /usr/share/php/Phix_Project/ComponentMaker/PhixCommands/PhpLibraryInit
.php

Where To Find Further Information

The Phix Project website is the official homepage for the project. Hopefully you’ll be able to find everything you need from there.

Stuart’s PHP Components blog posts provide a step-by-step look at using phix to create and maintain packaged components of PHP code.

14 comments »
Page 5 of 512345

This Month

November 2017
M T W T F S S
« Jul    
 12345
6789101112
13141516171819
20212223242526
27282930