Summary
In this episode, we focus on the concept of size or granularity in object-oriented programming. We discuss the idea of breaking down a problem into smaller, easily solvable chunks, and the importance of abstraction in object-oriented design.
Detailed Notes
In this episode, we focus on the concept of size or granularity in object-oriented programming. We discuss the idea of breaking down a problem into smaller, easily solvable chunks, and the importance of abstraction in object-oriented design. The guest, who is not explicitly mentioned, discusses the importance of taking a big problem and breaking it down into smaller pieces, and the concept of an outline. We also discuss the idea of genericizing methods to handle different types of data, and the concept of breaking down a problem into smaller, easily solvable chunks. The episode also mentions the importance of abstraction in object-oriented design, reusing code instead of reproducing it. The highlights and interesting links are relevant to the main topic.
Highlights
- The idea of a unit of work being a good measure for how we build out our class and how we break it into modules or components.
- The concept of an outline, taking a big problem and breaking it into smaller pieces.
- The importance of abstraction in object-oriented design, reusing code instead of reproducing it.
- The idea of genericizing methods to handle different types of data.
- The concept of breaking down a problem into smaller, easily solvable chunks.
Key Takeaways
- Break down complex problems into smaller, manageable pieces.
- Reusing code is more important than reproducing it.
- Abstraction is key in object-oriented design.
- Genericizing methods is important for handling different types of data.
- Breaking down a problem into smaller, easily solvable chunks is essential.
Practical Lessons
- Start by breaking down a complex problem into smaller, manageable pieces.
- Focus on reusing code instead of reproducing it.
- Use abstraction to simplify complex designs.
- Genericize methods to handle different types of data.
Strong Lines
- Just a step forward a day is still progress.
- We can take this big problem and all of these steps and just walk through and tackle them one step at a time.
Blog Post Angles
- The importance of abstraction in object-oriented design.
- The concept of breaking down a complex problem into smaller, manageable pieces.
- The role of genericizing methods in handling different types of data.
- The idea of reusing code instead of reproducing it.
- The concept of an outline, taking a big problem and breaking it into smaller pieces.
Keywords
- object-oriented programming
- abstraction
- genericizing methods
- reusing code
- complex problems
Transcript Text
This is Building Better Developers, the Develop-a-Noor 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 are getting towards the end of our practical object-oriented programming season. In these last couple episodes, we'll call them essentially best practices, I guess. You can maybe look at these as lessons learned in dealing with object-oriented and development and processes, procedures, and just all of the above over the years. This episode, I want to focus on, we'll call it size or granularity. We've talked about this through the season, the idea of how we break up our work, how we build up our classes. We can start with very, very fine-grained things. Essentially every method could be one-liners. We could just say that's our goal, which would seem to be very difficult to do, very tedious to deal with it, to say the least. Then you could also do something that's huge, that's just one class with one method, which effectively breaks all object-orientedness anyways. Then you're just back to functional programming. You see these extremes at times. I think we've gotten, for the most part, that we don't do that. I think most developers have, by nature, have a middle ground that they pick up. You can sometimes see that, particularly, I think, either people that have just changed over from maybe more of a functional, traditional, old-school legacy programming skill to object-oriented. Or on the other side, sometimes you'll get maybe students that have just come out of an object-oriented class where everything's an object and they just love the whole concept and they really overdo it. It's not necessarily typical anymore. It does exist. I think every time I walk into a project, that balance is something that is part of the design, is part of the consideration. Some of these are well-known, I think, best practices, but I want to throw a few of these out and talk about them a little bit. The first is the idea of a unit of work, essentially, being a really good measure for how we build out our class and how we break it into modules or components. If you think that you're of a process that has, let's just say, for example, say you've got 10 steps. To some extent, it makes a lot of sense, definitely, for each of those steps to be either a method or potentially even a class. It depends on how you do it. If you look at some of the frameworks that are out there for stepwise or batch processing of a problem, typically each step is an instance of a class. Then, of course, you can code into that step what it does. You may or may not need something that generic, but generally speaking, it does make sense that you will have, as part of building out your class, your steps that you take from start to providing the solution are going to be natural units of work that, to some extent, should be either methods or classes or something, because what you want to think about is how those steps are performed. You can initially do something very brute force. You can walk through each step and do something just to get that step completed. Maybe later on, you refine that or generalize it, and now you can have maybe a more elegant solution, or maybe a faster solution. A good example would be maybe a sort kind of thing. Maybe you have a step where you have to sort the data that you're working on, and you start with something like a bubble sort or something just because you don't remember all the different sort types out there. You just take something that's very, very simple, that's very easy to implement, and you do it. Now, somewhere down the line, that grows, and you realize that that solution is not feasible. It's not going to work with a reasonable return time. You go in and you redo that step, and you do a quick sort or something like that. You pick a different sort, a method that works for your data, and you're off and running. Another thing about this, a benefit of designing in this way, is it goes back to the idea of having an outline that we work towards. When we outline the tasks, the steps required to solve our problem, then we have now a framework to start hanging code on. One of the nice things in object-oriented is we can actually stub out every one of those steps and then come back at some point as we're into implementation and flesh out each step. If we have a step that initially, let's just say it checks a value and it either returns true or false, what you can do is initially you can just have it always return true or always return false or heck, randomly return true or false and then just do that. You don't have to worry about any of the other complexities about what really does true or false mean. You just do that, and so you can skip that step and say, all right, I'm going to come back to that later. This allows us also, when we talk about unit testing and even documentation, it allows us to really focus on one piece, test it, validate it, document it, do it right, end quotes, but do it the right way, be comfortable with it, confident in it, and then move on to the next step. This allows us to not only, as we expand, to build on classes that we're comfortable with, but even as we're building out our classes, we're working with methods and attributes that we are comfortable with, that we know that we have the initialization proper, that we have the validations there, that we know what the states are, that we have exceptions taken care of. All of that stuff that combines to give us high quality software, we can do that in smaller chunks. We can take this big problem and all of these steps and just walk through and tackle them one step at a time. Depending on what your problem is and what the steps are, those steps, as I say, they may be methods. They may be very simple, a few lines of code here, a few lines of code there, or they may be classes in and of themselves. If they are that big, if the steps are that either complex or just have that much going on, then maybe within that step, you break that down. This goes to our classic approach to solving problems, is you just break it down and break it down and break it down until you get to essentially easily solvable chunks of work. The bonus in the object-oriented world is that when we design this way, let's say we start with our 10 steps and we start breaking those down and we've got sub-steps within As we design this thing out, we're going to see possibly and very often, likely, some repetition. We're going to see some work that we do in step two, deep into that, is also very similar work that we do in steps eight and 10. Thus, we see something that it makes sense to abstract it. That's another one of our principles that we want to consider as we are building out in order to build a good object-oriented design. Take a look overall. What are the things we're doing? What are the tasks that we're doing? Where we see similarities, those are going to be opportunities for abstraction and for us to not reproduce code, but instead reuse code. We're going to see this in most applications very often. Typically what happens in a problem is that there is the data, since it's related, not only is the data related, but the manipulations or the calculations or the summations that we need to do are actually going to appear over and over again within that problem. Thinking about the most simple and straightforward is the idea of a spreadsheet. Well, we have rows and columns. We're going to have, within working on those rows and columns in that spreadsheet, we're probably going to have things like summing rows, summing columns, summing cells. Those things are going to recur many times in dealing with our overall spreadsheet. Those would be things that we would essentially abstract and say, okay, I need to sum cells. I've got to have a method that allows me to send a group of cells to this thing, and it's going to sum all the values up and kick something back. That simple. We would see that if we didn't break that up properly, we may not catch that until later in the game. We see this in security and access. Those kinds of things are going to show up a lot. When you're going through each step, there's just things that you do with each step. There may be validations with each step where you come in and you say, okay, I want to make sure that I have a valid record that I'm working on. Let's say we've got this record that we pass through these 10 steps, and each step does something with the record. Well, we may want to do a sanity check, some sort of validation check. The record itself has a method that says validate. You go through each step and you just call validate each time. Instead of within the step trying to validate the data, you code the call once and you're done. Then you just call it multiple times. That's what we're going to see as we lay out our outline. We build our steps and then build our sub-steps. On the way, like I said, we're probably going to see some similar tasks. They may not be similar enough that it makes sense to abstract them out. For example, you may see that task, essentially that task twice, but in one case it deals with a number and another it deals with strings. It just makes sense to leave those as two separate methods. But maybe it's not. In one case it deals with one set of data and another case it deals with three sets of data. Something like that where maybe it's just setting a flag or just giving different data into the system, into the method, you can still properly handle that, assuming that you genericize it accordingly. This is where we do want to avoid hard coding values wherever we can. We want to assume that there's not going to be zero or one. There's going to be maybe zero, maybe one, maybe many, maybe a null value, maybe an invalid value, things like that. Those are what we're going to build into our methods as we're walking through these tasks to genericize them in a way that hopefully when we're building this out or not even implementing designing this out in steps one, two, and three, and we essentially revisit that in steps five and six, we can look at it and say, okay, we've already got that covered. Or this is a slight adjustment to how we do it so that now we can use the same thing in steps one, two, three, five, and beyond. That's where I want to hold off this time around. I really want to just focus on the granularity side of things and this concept of essentially an outline. It goes back to taking a big problem and break it into smaller pieces. When we do this, we're going to find that the object-orientedness of the object design of our solution is going to become rather apparent. Most of the week, what is your latest problem that you're working on? Have you broken it down? Or do you see it as maybe a couple big essentially blobs of work? Or do you have those blobs broken down in a way that you can easily identify where work is being repeated? If you can, have you built out the methods to do that? Or is that technical depth that you have to work with where you know that you're repeating code where you really shouldn't, you should be reusing it? That being said, I'll give you something to think about in your latest design. As always, go out there and have yourself a great day, a great week, and we will talk to you next time. Thank you for listening to Building Better Developers, the Developer North Podcast. For more episodes like this one, you can find us on Apple Podcasts, Stitcher, Amazon, and other podcast venues, or visit our site at developernor.com. Just a step forward a day is still progress, so 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 Developer North. One is the book, The Source Code of Happiness. You can find links to it on our page out on the Developer North site. You can also find it on Amazon, search for Rob Broadhead, 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 developernor.com if you would like more information. Now go out there and have yourself a great one.