« Partial Classes. Totally Stupid?| Main | Attack Of The Interface Octopus »
How Big Should Your Class Be?

Who is the King of your Code?
Digg picked up the article linked below. I asked "what is the purpose of partial classes?" One of the comments was really insightful: [Emphasis Mine]
I guess you actually have to code a large project first before you find an instance where partial classes are useful.The perfect example is VS 2005 where designer code is put in its own partial class file. Before in VS 2003 an interface file would be so messy with thousands of lines of interface code and variables, and then below it your own custom code. Now the custom code is all in a nice, small, manageable, file which is much cleaner to work with than before.
In my own projects I sometimes end up with a large class file where a set of functions have to deal with interop, another set for packet handling, and a set of functions for logic. It might come out to 3000 lines of code which is a bitch to traverse through. With partial classes I can put those three function sets into their own files so now when I want to look up logic code its all together in its own manageable file. And its easier for others to understand and work with also.
Does this sound right? So how big should your classes be?
Call me crazy, but a 3000-line class doesn't sound too good to me. How can I know that? How can anybody say how big any class should be? Doesn't it depend on what the program is trying to do?
In a word, no.
Here's why. Let's start with the example I was giving last week.
You start with a WinForm. Let's say you want a form to work with a Customer. You add some controls, you add some stuff to retrieve and save your business stuff. Pretty soon, the users want more controls. Then they want the controls to do more stuff. The business thing you are working with gets more complicated. Then there are rules about when you can save it. Then there are rules about when you can retrieve it, or edit it. Finally, there's a bunch of "wiring" code you have to write just to get hooked up to the datastore and things humming on your page.
It doesn't take a rocket scientist to realize that pretty soon that one form file of yours has turned into one of those 3000-line classes. Could be bigger. You can have 50-60 controls on a page, and it is not unusual for something like a customer business object to have dozens of fields. Perhaps more than a hundred. Most likely it will have other groups of things that relate to it, that also need to be stored, retrieved, updated, etc.
If you continue down this road, at some point, you realize that you got too much stuff in this class to work with efficiently. There's bits of stuff everywhere! Do you decide to use partial classes to solve this problem? If you do, go directly to programmer jail. Do not pass go. Do not collect $200. Spreading out global variables and functions over multiple files is something to do as a last resort.
What you need to think about is what kinds of groups of things do you have. In this case, we have stuff that works the UI, stuff that is involved with the business logic, and stuff that works the database. Even though we are working with one thing, the Customer, we really have three types of code we are trying to stuff into that one form file.
So we split it up. We make one file CustomerDb, where we put the database wiring. We make one file Customer, where we put the business logic. And we make one file frmCustomer, where the UI is stored.
Doing it this way (the hard way!) is called many things: Refactoring, growing an architecture, or simply applying good coupling and cohesion. Remember Low Coupling and High Cohesion?
Coupling can be "low" (also "loose" and "weak") or "high" (also "tight" and "strong"). Low coupling means that one module does not have to be concerned with the internal implementation of another module, and interacts with another module with a stable interface (see Information hiding). With low coupling, a change in one module will not require a change in the implementation of another module. Low coupling is a sign of a well structured computer system.However, in order to achieve maximum efficiency, a highly coupled system is sometimes needed. In modern computing systems, performance is often be traded for lower coupling; the gains in the software development process are greater than the value of the running performance gain.{citationneeded}
Low-coupling / high-cohesion is a general goal to achieve when structuring computer programs, so that they are easier to understand and maintain.
The concepts are usually related: low coupling implies high cohesion and vice versa. In the field of object-oriented programming, the connection between classes tends to get lower (low coupling), if we group related methods of a class together (high cohesion).
In object-oriented programming, coupling is a measure of how strongly one class is connected to another.
Coupling is increased between two classes A and B if:
A has an attribute that refers to (is of type) B.
A calls on services of a B object.
A has a method which references B (via return type or parameter).
A is a subclass of (or implements) B.
Disadvantages of high coupling include:A change in one class forces a ripple of changes in other classes.
Difficult to understand a class in isolation.
Difficult to reuse or test a class because dependent class must also be included.
One measure to achieve low coupling is functional design: it limits the responsibilities of modules. Modules with single responsibilities usually need to communicate less with other modules, and this has the virtuous side-effect of reducing coupling and increasing cohesion in many cases.
So what is going on with our friend with the 3000-line class? He has what we in the business call a "King Class" -- this is a class that does so much it seems to do everything. It can happen in a lot of ways. Most of the time it is the result of a class file "growing" without the programmer taking the time to start separating concerns.
What should be done? Well, listen to the programmer himself. He says he has code in that one class "where a set of functions have to deal with interop, another set for packet handling, and a set of functions for logic"
Sounds to me like he has three tiers all stuffed into that one class. Maybe not. I can't read the code from here. But I can say that if you have a huge class and you have general categories that your functions fall into -- Dude! You need to re-factor! Make that class do just one thing and do it well. If it has business logic and it can store and talk to things all over the world, then split up the business and the talking parts at least. Socket code don't got no business being mixed in with your business stuff.
But I can tell you what will happen. These classes will just get worse and worse. What happens when you grow classes out of control like this is that you have an organizational problem where the programmers are not improving the code each time they touch it. If you're just adding features and not re-organizing your thoughts, then you will create class and program structures that get more and more complex. Until they stop writing checks to pay for maintaining it, which might be many years. Hey! Job security!
So fix your code, big guy!
You know, a little bit of design up front can be a pretty nifty thing. Whoever is creating these monstrosities might want to try it.
Leave a comment