Break free from procedural programming and learn how to optimize your applications and enhance your skills using objects and design patterns
- Fast-paced easy-to-follow guide introducing object-oriented programming for ColdFusion developers
- Enhance your applications by building structured applications utilizing basic design patterns and object-oriented principles
- Streamline your code base with reusable, modular objects
- Packed with example code and useful snippets
What is a Bean?
Although the terminology evokes the initial reaction of cooking ingredients or a tin of food from a supermarket, the Bean is an incredibly important piece of the object-oriented design pattern.
The term ‘Bean’ originates from the Java programming language, and for those developers out there who enjoy their coffee as much as I do, the thought process behind it will make sense: Java = Coffee = Coffee Bean = Bean.
A Bean is basically the building block for your object. Think of it as a blueprint for the information you want each object to hold and contain. In relation to other ColdFusion components, the Bean is a relatively simple CFC that primarily has two roles in life:
- to store information or a collection of values
- to return the information or collection of values when required
But what is it really?
Typically, a ColdFusion bean is a single CFC built to encapsulate and store a single record of data, and not a record-set query result, which would normally hold more than one record. This is not to say that the information within the Bean should only be pulled from one record within a database table, or that the data needs to be only a single string—far from it.
You can include information in your Bean from any source at your disposal; however, the Bean can only ever contain one set of information.
Your Bean represents a specific entity. This entity could be a person, a car, or a building. Essentially, any ‘single’ object can be represented by a bean in terms of development.
The Bean holds information about the entity it is written for. Imagine we have a Bean to represent a person, and this Bean will hold details on that individual’s name, age, hair color, and so on. These details are the properties for the entity, and together they make up the completed Bean for that person.
In reality, the idea of the Bean itself is incredibly similar to a structure. You could easily represent the person entity in the form of a structure, as follows:
hairColor = ”} />
Listing: 3.1 – Creating an entity structure
This seems like an entirely feasible way to hold your data, right? To some extent it is. You have a structure, complete with properties for the object/entity, wrapped up into one tidy package.
You can easily update the structure to hold the properties for the individual, and retrieve the information for each property, as seen in the following code example:
hairColor = ”} />
Listing 3.2 – Populating the entity structure
Although the structure is an incredibly simple method of retaining and accessing data, particularly when looking at the code, they do not suit the purpose of a blueprint for an entity very well, and as soon as you have populated the structure it is no longer a blueprint, but a specific entity.
Imagine that you were reading data from the database and wanted to use the structure for every person who was drawn out from the query. Sure enough, you could create a standard structure that was persistent in the Application scope, for example. You could then loop through the query and populate the structure with the recordset results. For every person object you wanted, you could run ColdFusion’s built-in Duplicate() function to create a copy of the original ‘base’ structure, and apply it to a new variable.
Or perhaps, the structure might need to be written again on every page it is required in, or maybe written on a separate .cfm page that is included into the template using cfinclude.
Perhaps over time, your application will grow, requirements will change, and extra details will need to be stored. You would then be faced with the task of changing and updating every instance of the structures across your entire application to include additional keys and values, or remove some from the structure.
This route could possibly have you searching for code, testing, and debugging at every turn, and would not be the best method to optimize your development time and to enhance the scalability of your application.
Taking the time to invest in your code base and development practices from the start will greatly enhance your application, development time, and go some way to reduce unnecessary headaches caused by spaghetti code and lack of structure.
The benefit of using beans
By creating a Bean for each entity within your application, you have created a specific blueprint for the data we wish to hold for that entity. The rules of encapsulation are adhered to, and nothing is hardcoded into our CFC.
We have already seen how our objects are created, and how we can pass variables and data into them, which can be through the init() method during instantiation or perhaps as an argument when calling an included function within the component.
Every time you need to use the blueprint for the Person class, you can simply create an instance of the Bean.
You instantly have a completely fresh new object ready to populate with specific properties, and you can create a fully populated Person object in just one line of code within your application.
The main purpose of a Bean in object-oriented development is to capture and encapsulate a variety of different objects, be they structures, arrays, queries, or strings for example, into one single object, which is the Bean itself.
The Bean can then be passed around your application where required, containing all of the included information, instead of the application itself sending the many individual objects around or storing each one in, for example, the Application or Session scope, which could get messy.
This creates a nicely packaged container that holds all of the information we need to send and use within our applications, and acts as a much easier way to manage the data we are passing around.
If your blueprints need updating, for example more properties need to be added to the objects, you only have one file to modify, the CFC of the Bean itself. This instantly removes the problematic issues of having to search for every instance or every structure for your object throughout your entire code base.
A Bean essentially provides you with a consistent and elegant interface, which will help you to organize your data into objects, removing the need to create, persist, and replicate ad-hoc structures.
Creating our first Bean
Let’s look at creating a Bean for use with the projects table in the database. We’ll continue with the Person Bean as the primary example, and create the CFC to handle person objects.
An introduction to UML
Before we start coding the component, let’s have a quick look at a visual representation of the object using Unified Modeling Language (UML).
UML is a widely-used method to display, share, and reference objects, Classes, workflows, and structures in the world of object-oriented programming, which you will come into contact with during your time with OOP development.
The modeling language itself is incredibly detailed and in-depth, and can express such a wide array of details and information.
Person object in UML
In this example, let’s take a look at the basics of UML and the visual representation of the Person component that we will create, which looks like this:
At first glances, you can instantly see what variables and functions our component consists of.
With most UML objects, it is broken into segments for easier digestion. The actual name of the component is clearly visible within the top section of the diagram.
In the second section, we include the variables that will be included within our object. These have a ‘–‘ character in front of them, to indicate that these variables are private and are hidden within the component (they are not accessible externally).
These variables are followed by the variable type, separated by a colon (‘:‘). This lets you easily see which variable type is expected. In this example, we can see that all of the variables are strings.
In the bottom section of the diagram we include the function references, which contain all methods within the component.
All of the functions are prefixed with a ‘+‘ to indicate that they are publically accessible, and so are available to be called externally from the component itself.
For any functions that require parameters, they are included inside the parenthesis. If a function returns a value, the returnType is specified after the ‘:‘.
Based upon this UML diagram, let’s create the core wrapper for the CFC, and create the constructor method—the init() function.
Create a new file called Person.cfc and save this file in the following location within your project folder: com/packtApp/oop/beans.
dateofbirth = ”, hairColor = ”
Listing 3.3 – com/packtApp/oop/beans/Person.cfc
Here, we have the init() method for the Person.cfc and the arguments defined for each property within the object. The bean will hold the values of its properties within the variables.instance structure, which we have defined above the init() method as a pseudo-constructor.