No shame in this question. CFC’s (and OO programming in general) provide a few specific things:
- Code reuse
Now, I understand the last two items may make zero sense, but that’s also likely why CFC’s don’t seem that useful. A lot of people never get past the first one or so bullet points. I’ve seen apps that treat CFCs more like glorified includes and that’s ok. The encapsulation part is important because the main difference between a cfincluded template and a method call is that the template just “embeds” itself in the parent page’s variables whereas a function has a more strict set of inputs and outputs. This of course, assuming you’re not abusing the “transcendent” scopes like application, request, and server-- (the enemies of encapsulation) means that your code is much more portable and easier to refactor and move around. Now you can insulate the hairy details and all the intermediate variables necessary to calculate pricing from the code that needs the price. This is encapsulation.
Now the last two bullets go way past simple code re-use and into the world of domain modeling. The main difference between a struct of data and a CFC is the CFC adds behavior. I can have a struct called “user” with a first and last name, but if I have a CFC called user with a firstname and lastname property I can have a method like getFullName() that operates on the data in the CFC instance in a self contained and portable way that allows a user to define behavior. A very large amount of people don’t use CFC’s to model business objects (A user, an order, a shopping cart) or if they do, these CFCs are stateless instances with “static” behavior which sort of puts them back in the first two bullets.
When you model a business concept or real life object in a CFC, you can have groups of objects that share similar traits and behaviors. Now you can have a Vendor and Client object that both extend User and share all the properties and behaviors of a user (first name, last name) PLUS additional properties and behaviors that define them specifically as a vendor (vendor ID, available services) and client (username, order history). This is Inheritance.
The last bullet is a very fancy way of saying you can have behaviors defined that are flexible and react at runtime based on their inputs. Let’s say your payment Processor class has a method for billing the client and it accepts an Order. Now you have two types of orders in your app, let’s say. inStoreOrders and digtalOrders, each implement the same methods, but have their own custom logic on how to calculate taxes based on local tax laws. Your payment processing method can declare that it needs an object that implements an Order interface at compile time, and then at runtime it calls the passed in order’s getTax() method and the logic of whether to tax based on the shipping or billing address can be encapsulated in each of your concrete order implementations. Now you have parts of a system that get difference behaviors neatly packed into different classes implementing the same API. This is Polymorphism.
So the first couple bullet points are nice use cases of CFCs, but it’s when you get into complex applications and really dip into the advanced features of objects and hit those last bullets that you really get a lot more out of OO.