Decomposing An App Into Components
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 a€˜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
Truncated by Planet PHP, read more at the original (another 6770 bytes)