This is a multi-part series on Refactoring to Functional Programming
- Getting Started
- Basic Primitives
- Reducing and Flattening Lists
- Why Class?
Teacher: We are surrounded by objects in the real world. These can be cars, houses, etc. That’s why it’s very easy to associate real world objects with classes in Object Oriented Programming.
2 weeks later
Jake: I’m having a bit of hard time with these objects. Can you give me some guidance?
Teacher: Sure. There’s actually a couple of more or less formal processes to help you, but to sum it up, look for nouns. And verbs are like methods that can be performed on the class. The behavior so to speak.
Jake: Well that seems reasonable. Thanks!
Jake’s on the job
Phil: Hey Jake. I’ve been looking at this class of yours. It’s a little bit too big.
Jake: Sorry. And what’s the issue with that?
Phil: Well, thing is. It’s got too many responsibilities. It does too much.
Phil: Well think about it. If it does too much, it means that it touches many parts of the system. So the probability of having to touch the class when changing code is higher, which means more probability of breaking things. Plus, 1000 lines of code in a single class is harder to understand than 30 lines.
Jake: Yeah. Makes sense.
Phil: Break these up into smaller classes. That way each class does only one thing and one thing alone.
A year later
Mary: Jake, I’m just reviewing this class of yours, there’s not much behavior in it.
Jake: Yeah well I wasn’t sure if that behavior belonged in the Customer class or to the Accounts class, so I placed it in this other class called CustomerService.
Mary: OK. Fair enough. But the Customer class isn’t really a class anymore. It’s more a DTO.
Mary: Yes, a Data Transfer Object. It’s like a class but without behavior.
Jake: So like a structure? A record?
Mary: Yes. Kind of. So just make sure your classes have behavior. Otherwise, they’re not really classes. They’re DTO’s.
2 years later
Mathew: Jake, looking at this class. It’s tightly coupled to a specific implementation.
Mathew: Well, you’re creating an instance of Repository inside the Controller. How you going to test it?
Jake: Hmm. Fire up a demo database?
Mathew: No. What you need to do is first off, program to an interface not a class. That way you don’t depend on a specific implementation. Then, you need to use Dependency Injection to pass in a specific implementation, so that when you want to change the implementation you can.
Jake: Makes sense.
Mathew: And in production, you can use an IoC Container to wire up all instances of the different classes.
3 years later
Francis: Jake. You’re passing in too many dependencies into this class.
Jake: Yeah but the IoC Container handles that.
Francis: Yes. I know but just because it does, it doesn’t make it right. Your class is still tightly coupled to too many other classes (even though the implementations can vary). Try and keep it to 1 to 3 maximum.
Jake: OK. Makes sense. Thanks.
4 years later
Anna: Jake. This class, why did you name it Utils?
Jake: Well. I didn’t really know where to place that stuff cause I don’t know where it really belongs.
Anna: OK. It’s just that we already have a class for that. It’s called RandomStuff
Over a beer…
Jake: You know Pete, I’ve been thinking. They teach us that we need to think in terms of objects and identify these with nouns among other techniques. We then need to make sure that we name them correctly, that they’re small, that they only have a single responsibility and that they can’t have too many dependencies injected into them. And now they’re telling us that we should try and not maintain state because it’s bad for concurrency. I’m beginning to wonder, why the hell have classes at all?
Pete: Don’t be silly Jake. Where else are you going to put functions if you don’t have classes?
Pete: Another beer?
Until next time.