Maintaining a separation of concerns is an important part of building OO applications. By separating concerns, you can build more-modular applications. As your applications become more modular, they become easier to maintain.
Even though PHP supports OO language features like classes and interfaces, you can still write a PHP application that does not use any OO features. Sometimes, building an OO design is difficult and, depending on the project, can seem like a diminishing return for a small, simple application.
Because OO designs allow for easier application modifications during the application's lifetime, as well as the benefits of reusability, I use a simple test to determine whether I should build my application using OO techniques. If the application does not pass my test, I take a more-functional approach, still incorporating techniques as best I can to build modular functions:
- Can parts of my application be reused elsewhere? If you will be building other applications, think about where you can reuse parts of the application.
- Is my application likely to need changes later? If your application contains business logic or rules, it is likely that when the business logic changes, the application will need to change as a result.
Identifying a concern
It's fine to know that you should separate concerns when you're building applications. But before you can do a good job of separating them, you must know what a concern is. When building an application, a concern is "is a particular set of behaviors needed by a computer program, the conceptual sections" (see Resources).
To define this better, think of a typical application. For the most part, most applications get data from somewhere (input), put the data away somewhere (persistence), and then get the data back again later (presentation). When your application gets input from a user, it might validate the data before putting it away. When the application is displaying the data back to the user, it might format the data in such a way that it is easier to read.
All of these — holding data, formatting data, validating
data — are concerns. If your application's concerns are separated
from each other, a
Person component that
contains data elements about a person should not have any idea about how
to format the person's name. Although it is data from the person that is
being formatted, something like formatting preferences can change from
application to application. Some applications might format a person's name
in first-name/last-name format. Others may only use the first name.
Formatting is a type of a presentation concern that should not be
integrated tightly into a component, as doing so limits the component's
Identifying a boundary
When separating concerns horizontally by using layers — as in presentation, process or business logic, and data layers — a boundary is the line drawn that defines the edges of the layer. For instance, there is a boundary between presentation layers and logic layers. Using a framework that supports the Model-View-Controller (MVC) pattern will help enforce these boundaries.
But if you are not using a framework to help you, you must start separating concerns by identifying the concerns, then drawing boundaries between them. Your PHP code should stay inside the boundaries you identify. For instance, a boundary separates the presentation layer from the data layer. That means you keep PHP code that deals with presentation behaviors, such as arranging text, concatenating values, or formatting numbers, out of the layer that contains the data behaviors. Conversely, keep your PHP code that connects to a database and runs queries separate from the code that arranges the text or numbers.
Identifying a dependency is also very important when learning how to separate concerns properly. Using the person and name formatting example, a dependency exists between a component that formats a person's name and the data. The data must exist before it can be formatted. However, the data doesn't depend on the formatter to exist.
One way of knowing that you can and should separate concerns is whether you can draw a unidirectional (not circular) dependency between two behaviors. If one can exist without the other, separate them.
After you have the concerns separated, you can draw components that handle
the concern. A
Person component contains the
data about a person, and a
contains methods that properly format the
Person component for viewing. Various
PersonNameValidator, can be
built to validate the data about a person.
You can also build components that represent domain objects. For instance,
Person may represent an employee, customer,
student, or contact. Depending on your application, a person might log in
to work, place an order, take a class, or provide personal information.
These can be turned into components, like an
Order component or a
It's important when building the components to think of the components'
data as a concern for each component. For instance, a
Person component should not calculate
Order subtotals or determine whether
Classes are full.
Isolating logic in an application is important because, most of the time, the logic should be separated from the other areas. In other words, think of the logic in your application as a concern all by itself.
In a business application, logic is what you do to your data between user input (presentation) and putting it away in storage (data). If you calculate interest rates, a customer's total orders for the year, or whether a customer has a certain number of bonus points based on the total orders for the year, you are using logic to make the calculations. It's best not to intertwine this logic with the code that simply represents the object or stores it in the database or validates the data. Instead, it's best to put logic like this in different classes so the other objects don't need to be concerned about the details of the logic.
Identifying and separating concerns is an important step in building modular object-oriented applications. As you identify concerns and learn to identify boundaries, you learn where to put your PHP code that does certain behaviors.
- Read "Build seven good object-oriented habits in PHP" to discover seven steps to building object-oriented PHP applications.
- Read the Wikipedia entry on Separation of concerns.
- PHP.net is the central resource for PHP developers.
- Check out the "Recommended PHP reading list."
- Browse all the PHP content on developerWorks.
- Follow developerWorks on Twitter.
- Expand your PHP skills by checking out IBM developerWorks' PHP project resources.
- To listen to interesting interviews and discussions for software developers, check out developerWorks podcasts.
- Using a database with PHP? Check out the Zend Core for IBM, a seamless, out-of-the-box, easy-to-install PHP development and production environment that supports IBM DB2 V9.
- Stay current with developerWorks' Technical events and webcasts.
- Check out upcoming conferences, trade shows, webcasts, and other Events around the world that are of interest to IBM open source developers.
- Visit the developerWorks Open source zone for extensive how-to information, tools, and project updates to help you develop with open source technologies and use them with IBM's products.
- Watch and learn about IBM and open source technologies and product functions with the no-cost developerWorks On demand demos.
Get products and technologies
- Innovate your next open source development project with IBM trial software, available for download or on DVD.
- Download IBM product evaluation versions or explore the online trials in the IBM SOA Sandbox and get your hands on application development tools and middleware products from DB2®, Lotus®, Rational®, Tivoli®, and WebSphere®.
- Participate in developerWorks blogs and get involved in the developerWorks community.
- Participate in the developerWorks PHP Forum: Developing PHP applications with IBM Information Management products (DB2, IDS).