Summary
In this episode, we discuss the importance of finding a balance between cohesion and coupling in object-oriented programming. We explore the pros and cons of big objects vs. small objects and how to approach design with a blended approach.
Detailed Notes
In this episode, we delve into the concept of cohesion and coupling in object-oriented programming. We discuss the challenges of maintaining a balance between these two seemingly opposing forces. The hosts explain that big objects and small objects are not mutually exclusive, but rather, they can coexist in a harmonious balance. The key takeaway is that grouping related data and functionality is essential for efficient design. The episode also touches on the importance of considering the trade-offs between cohesion and coupling. The hosts provide examples of how to approach design with a blended approach, where both big objects and small objects are used effectively.
Highlights
- Balance between cohesion and coupling is key in object-oriented programming.
- Big objects vs. small objects: it's not either-or, but a balance.
- Cohesion and coupling are not mutually exclusive; they're complementary.
- Grouping related data and functionality is essential for efficient design.
- Small objects can be just as effective as big objects in certain situations.
Key Takeaways
- Cohesion and coupling are not mutually exclusive; they're complementary.
- Grouping related data and functionality is essential for efficient design.
- Big objects vs. small objects: it's not either-or, but a balance.
- Small objects can be just as effective as big objects in certain situations.
- A blended approach can be used to achieve a balance between cohesion and coupling.
Practical Lessons
- Consider the trade-offs between cohesion and coupling when designing systems.
- Grouping related data and functionality can improve efficiency.
- Use a blended approach to balance cohesion and coupling.
Strong Lines
- Balance between cohesion and coupling is key in object-oriented programming.
- Grouping related data and functionality is essential for efficient design.
- Small objects can be just as effective as big objects in certain situations.
Blog Post Angles
- The importance of balance between cohesion and coupling in object-oriented programming.
- How to approach design with a blended approach.
- The trade-offs between cohesion and coupling and how to navigate them.
- Examples of successful implementations of cohesion and coupling in real-world systems.
- Best practices for maintaining a balance between cohesion and coupling.
Keywords
- object-oriented programming
- cohesion
- coupling
- design patterns
- balanced approach
Transcript Text
This is Building Better Developers, the Develop-a-newer podcast. We will accomplish our goals through sharing experience, improving tech skills, increasing business knowledge, and embracing life. Let's dive into the next episode. Well, hello and welcome back. We're continuing our season where we're looking at object-oriented programming from a practical point of view. This episode we're continuing sort of a little mini-series within here as we're looking at cohesion and coupling and big objects versus smaller objects, talking as we also often have about a granularity essentially in our designs. And we're going to focus this one on, we're going to talk actually about essentially balance between cohesion and coupling, finding what works for us. We've talked about the big object approach. We've talked about the little object approach. And although we stuck really to the positives, the pros of both of them, there are cons with those as well. In the big object approach, we don't really have flexibility. In the smaller object approach, we have more flexibility, but it can be a performance detraction essentially. We can have a whole lot of things that we're dealing with that means all these things have to be spun up and we have to wait essentially for them to come into, for them to be instantiated. We need to populate them or initialize them. And just a lot of the headaches related to it. And if you get too small, it can be very complicated to build a big system. If we're going to build something of size, then we're going to get there a little faster if we have things that are a little larger, that were not as granular. As I mentioned before, think of starting from sand and having to use sand to make bricks and then bricks to make walls versus starting with bricks or maybe even prefabricated portions of a wall. House is a good example. We have these prefabricated houses where they can throw stuff together fairly quickly because they have most of the pieces built to some extent. And you can just bring walls up. You can put floors in, ceilings, all that kind of stuff, as opposed to having to lay a foundation and build a framework and all the things that go into a non prefabricated house. When we are looking at these two approaches, that is where I find that it's the best, I guess the sweet spot for us in finding a usage between larger and smaller objects. And it goes back to some things we've talked about before when we look at things like interfaces and some of the other opportunities we've got in the object-oriented world. And that really comes down to the idea of grouping, of putting things where they belong. When you talk about helpers in particular, even with large objects, when you've got that kind of a design, there's still probably going to be something out there, as we talked about in Top 4, where you've got some sort of interaction between large objects. You're most likely not going to, and I'm not sure why you would, build one monolithic object that just holds everything, because that, in a sense, really breaks the whole purpose of object-orientedness. Instead you're going to have at least some numbers of objects. Could be that you've got a few very large objects that do most of your work. And honestly, that can be possible. If you think about it somewhat, you have to tweak it a little bit, but very similar would be some of these large applications that have a core functionality, and then there are, they'll call them modules or plugins or extensions that you can add that are basically for a for a couple different customer types. Maybe for like taxes, maybe you've got something that's tax software that just does personal taxes, but then maybe you can add something in that handles investments and something different that handles real estate and something different that handles business-related taxes. And larger, now it's a little bit blurred because we have these software-as-a-service But still, they're not necessarily, they may not be reviewed as plugins, but they are, sometimes they're like a gold, silver, platinum, introductory, professional, enterprise-level subscriptions that are essentially a core application, or if you think of it in an object term, and then there's some additional ones that you can add to interact with that. One of the challenges, you have to interact. There's got to be, almost always there's going to be some sort of data that goes back and forth. You can just do it via a data store, database, something like that, and just shovel your data into the database and let everything essentially live in a silo so that you don't need cross-object code or functionality. Everything just does what it needs to, saves all the data, and then the next object that comes around loads the data, does what it needs to, saves the data. But that can be time-consuming. There's cases where that just doesn't really work, or it's just a lot of spin-up and spin-down time. Think about it. If you've got a large object, it needs to save all of its values, clean itself up out of memory, and then another instance of some other class needs to be instantiated, it needs to load the data, it needs to initialize itself, all that kind of stuff. That's a lot of work to just move from one type of functionality to another type of functionality. This is where we can find a blended use of smaller and larger objects. This is probably more common than not. Where we take the core functionality, the main things that we have within our application, whatever that happens to be, it may be invoices, it may be customer records, it could be financial records, it could be some sort of data set, whatever our application is, there's probably some core features. Those probably, in a lot of cases, those constitute most of the data and the functionality that we're working with. Because it's, for example, a customer relationship management application, then we're going to be dealing with customer data and data that deals with the relationships among customers, the contacting them and messaging them and things like that. Those are probably going to be your primary objects. Then you have these manipulations, essentially, the data manipulations that exist out there. I guess there's two forms of that. There is either the data manipulation where we're actually working with the data and it generates new data or changes the data. Then we also have this stuff that's just transferring data from point A to point B. Maybe if you've got a CRM app, maybe you've got a customer instance or some of that customer data that you want to transfer. For example, let's say you want to contact a customer within your application. Maybe you've got a customer instance and then you've got a contact instance and you need to pass the customer contact information to that contact object. Your customer is probably going to be a bigger object and your contact is probably going to be a smaller thing. You could group your contact methods, but still you end up in a situation where you've got essentially bigger objects or more often used objects, depending on what kind of data sets you're working with. Then you have these things that run calculations, that move data around, that are administrative types of classes and instances. You may have some shared functionality across objects that doesn't make sense in the hierarchical sense and the hierarchical approach. It doesn't make sense that you share that functionality by something inheriting from something else. That puts you in a situation where you need to be able to interact with other objects. You can either do that through objects themselves by sending these smaller sets of data. We've talked about that even. We touched on it in the flyweight pattern and some things like that, where you basically gather up your data and then shoot it from one class to another. You can also have plugins kinds of things where an object, a class, has another class, that they have this property or this group of functionality. We see this in interfaces where you can have these potentially rather small sorts of interface objects and then you've got the primary cogs of your application. This gives us actually some ways to see a nice blended approach. Where we take the things that we do the most, that we are working in the most, and maybe those are a little bit larger objects because we are doing so much work within them. We want to keep the data, the functions that are related to that together. We want to minimize the spinning up and spinning down of instances so we can have this bigger thing but we can be comfortable with it being bigger because we know that there's a lot of data and a lot of functionality that we're working with within that context. Then we've got these other things that are maybe the lesser used functionality and data that are smaller classes that we can bring up, that we can link to. That ends up giving us to some extent the best of both worlds. We have this core functionality that is also besides being useful to be holding up, gather that stuff together to group it. It's also less likely to be dynamic. There's a foundation of functionality we're going to have in almost every application that it is the stuff that you know for the most part is not going to change. It's only going to be expanded upon. That can be larger and more static. Then you leave the less defined, the things that are more likely to be dynamic, you leave those to be the smaller classes and interaction, the things that has us for the large class. It has these smaller functionalities or these smaller groups of functionality. Of course all of that being relative. The small may be one method or small could be 50 methods and 50 data items. Those things can sometimes be rather sizable. Within themselves, they may be targets to be big enough to be self-contained as well. Think about security. Security in an application can actually have quite a bit of stuff in there. You can have your users, you can have permissions, you can have some sort of audit trail or history. There's a lot of things that can go into security. It can be a smaller group of objects working in classes and objects working together or it could be more like a monolithic security class that you just plug it in and say, okay, if you're going to use security, boom, this is what you get. Both of those are valid, but what you see again is that with the larger version of it, probably what you've done, if you've got a single security class, more likely when you get to that situation, you've really settled your security. You know what you're going to do, you know what's included, you know the data that's involved and it may be something that you've used actually in multiple other applications. It is very not only static, but well tested that you're very confident in it. Those can be your bigger objects. Your design may evolve over time. You may take, based on confidence and use and things like that, you may actually at some point combine some of those smaller objects into a larger one and then use that. Maybe under the cover, you still have the smaller objects, but maybe not. Maybe for performance reasons or licensing or who knows, there's a lot of different reasons that may push you to say instead of this group of small objects, I'm just going to create one, put it all together, streamline it and then use that going forward. There are definitely a way to find balance and a blended approach is definitely possible. You don't have to go all cohesion or all coupling. You don't have to have all big objects or all small objects. Challenge the week. Where's your latest design at? Take a look at whatever the latest thing either you're working with or the design maybe that you put together. Where does it live? Is it bigger objects? Is it smaller objects? Is it a combination of them? Is it hit or miss? Some things are very big, some things are very small, or is there a consistency across your design in how you approach whether you do the big object or the small object approach? That being said, while you're thinking on that, I think we'll part ways into the next time. Go out there and have yourself a great day, a great week, and we will talk to you next time. Let's keep moving forward together. There are two things I want to mention to help you get a little further along in your embracing of the content of Developineur. One is the book, The Source Code of Happiness. You can find links to it on our page out on the Developineur site. You can also find it on Amazon, search for Rob Rodhead or Source Code of Happiness. You can get it on Kindle. If you're an Amazon Prime member, you can read it free. A lot of good information there. That'll be a lot easier than trying to dig through all of our past blog posts. The other thing is our masterminds slash mentor group. We meet roughly every other week, and this is an opportunity to meet with some other people from a lot of different areas of IT. We have a presentation every time. We talk about some cool tools and features and things that we've come across, things that we've learned, things that you can use to advance your career today. Just shoot us an email at info at Developineur.com if you would like more information. Now go out there and have yourself a great one.