views:

447

answers:

11

This came up in a conversation I was having online, and it occured to me that I have no idea how this is supposed to work: Quite a lot of programmers seem to just take as a given- indeed, obvious that classes are a necessary language feature for managing huge software projects.

It's not obvious to me how they do this.

My question to you is, how do you know? What objective measures are there that show that classes increase productivity, code reuse, and reduce the complexity of the production of a program? What aspects of classes make them ideal for large teams to collaborate on?

And now, there's a question I would like to ask, that is somewhat difficult to express. I'm sorry if I get this wrong and end up confusing or angering anyone:

Objectively, how do you know that the use of classes is not the cause of the application being large to begin with? That is, is it possible that a program with equivalent function could have been written, with much less code, small enough to not need any special measures to "manage" it, using some other code re-use strategy? (there are lots to choose from, such as those in functional programming paradigms, or aspect oriented programming).

That last bit is something that Steve Yegge has been hinting at on his blog. But I'm kind of sceptical of both sides of the argument, due to a real lack of any hard data from anyone, and not enough experience to come to a conclusion on my own.

What do you think?

edit: In particular I'm interested in why many programmers think prototypal style inheritance is not up to the task when it comes to large applications. I'm sorry of this question is vague- it's a product of my lack of understanding about this topic.

edit2: there seems to be some confusion over what I mean by functional programming. (I don't think any version of VB was ever functional, certainly not older versions). Please refer to the wikipedia article. http://en.wikipedia.org/wiki/Functional_programming

edit3: and let me emphasize that I'm looking for Objective measures. Not subjective opinions.

+2  A: 

I'm by no means a bigot towards any programming paradigm, but I have been operating in an OO fashion for a while.

Personally, I've had a lot of 'a-HA!' moments that classes have directly helped me understand the domain I'm working in better.

Most notably, in cases where there is confusion on why a system is malfunctioning, or what a system is supposed to do, classes have often forced me to think about what this discrete piece of the whole should be doing, and more often than not lead to refactoring the classes/methods at hand.

In short, encapsulation really makes me a happier person. ;)

Hope that helps.

Eddie Parker
A: 

I prefer classes so that I can divide a large problem into manageable pieces that are testable as individual units. IMHO, code reuse is over-rated--I've hardly seen it happen where I work. To me, what I get most out of good OO is good testability.

The other extreme is to use a bunch of global variables and jam all your logic in public static void main (or Page_Load in ASP.NET) and call static methods that call other static methods and so on... (I got dizzy at the end of the last sentence.)

The only thing that would break my OO mindset is if I was working with a pure functional language, which is something I haven't thought about since college unfortunately.

barneytron
+6  A: 

This is a very good question. Organizing code into classes is one way for a development team to create small, reusable modules. Also these modules have expressive and limited interfaces that express only what the class is capable of and not how it does it. Each class is orthogonal to the others and is therefore highly testable and modular in case of error.

Now what I have just described is a strange scene from a perfect world. But any good developer doing OOP work ought to be striving for something like this.

OOP is an acknowledgment that we, the developers, are simply human and cannot comprehend an entire system at once. So we break the system up into tiny reusable parts and focus on those.

Take a ten-digit US phone number as an example. It is difficult to remember a ten digit number in you head so we do what psychologists call "chunking". This means we mentally break down the numbers into chunks that we can better remember.

So 1234567890 becomes 123-456-7890. Fortunately for us, the phone companies also break these numbers down the same way and assign the chunks meaning. 123 is the area code, 456 is the prefix, and 7890 is the line number. Each of these chunks is like a class, they all have individual responsibilities, formats, and meanings.

So in conclusion the best thing I can say is that OOP allows us to build large, scalable systems that have centralized and encapsulated functionality. It allows us to not have to see the big picture all the time and be able to focus on doing one thing and doing it well.

Andrew Hare
A: 

Two things.

The first is the idea that a class is an opaque domain entity. When done correctly, object-oriented programs introduce a layer of abstraction: at the next highest layer, you marshal objects to do what you want, rather than dealing with details. You don't need to know how the objects and classes work: only what they do. This is a kind of information hiding, and it reduces the complexity that a team has to keep in their heads as they work.

The second is that OO programming allows for one kind of code reuse: you can define classes that override certain behaviors in other classes (inheritance), or classes whose instances include instances of other classes, using them to achieve their aims (encapsulation and composition).

Correctly using OO techniques can reduce the amount of code you need to manage, and reduce the number of things you need to bear in mind as you work or maintain the system. In practice this approach doesn't always work.

Rich
+1  A: 

I think classes can help, because they correspond to the very general cognitive concept of categorization, and so can help to describe large applications naturally.

Fabian Steeg
A: 

Objectively, how do you know that the use of classes is not the cause of the application being large to begin with?

Take any large program/application that was not written in an OO language (e.g. C, COBOL, even plain SQL) and you should be able to witness that code size is not directly attributed to language paradigm. For every number of well-designed, highly-refined, reusable C# or Java components, there are also an equal number of well-designed, highly-refined, reusable C DLLs. Conversely, there are equal numbers of horrible, bloated code.

The point is, good programmers are able to refine their system designs regardless of language/platform.

With regards to OOP, at least for me, it brings to the table a "potential" - a view of the programming world abit closer to our real world. We all know our world and this universe of matter are full of objects composed of smaller objects. Keep zooming in all the way from galatical star systems right down to the molecule, atom, and sub-atomic particles, it is truly amazing how vastly different matter are made of the same tiny particles combined in various patterns. Look at our own biology even, it is mind-boggling sometimes to think 60% of our bodies is actually just water when broken down to its finest. Yet look at all the various systems and organs in place burning with chemistry to keep us running and alive.

When we learn to understand the simplicity (oh really... ha ha) of the building blocks that form the real-world systems we see in every-day nature, we should then be able to understand that designing and building extremely complicated or sophisticated systems ought to start with small components that do very little themselves. And by slowly combining and meshing them together into ever larger components can we obtain more functionality and capability. Until we reach the desired system we envisioned.

The (proper) use of classes is to break down a system into its finest. As possible. So that you may look at something at a time and a particular level of abstraction and not be overwhelmed by purposes and logic that is not dealing with your present area of concern. Whenever you design a system, think of your own anatomy; think how you would design the human body. Whenever you design a system, think about starting a new company; what are the major divisions, the departments you need to operate the business. Who are the type of staff required to run those departments. The various equipment they need to use and interact with to carry out their jobs. How do you break down the business operations into its finest to allow yourself it understand it better?

When you understand the basic principle that some object is simply made up of smaller objects, you will be on your way to creating highly-reusable cells or molecules.

icelava
A: 

Classes have been most helpful to me in the aspect that I can work on one small aspect of a complex project at one time. Being able to decouple one aspect of the code from the large project is very helpful so you do not become overwhelmed. In the end, the cohesion between those classes can give you a quick overview of how a program works without having to deal with the innards.

As far as maintainability goes, it is much easier to look at a UML class diagram and figure out how everything is laid out than looking at a list of functions, in my opinion.

Joe Philllips
A: 

I think by saying classes, you should mean objects. Classes are nothing but place where you can put in your objects. The OOP paradigm is so successful for a reason. Once you've have that 'aha!' moment when you think you've finally understood the concept of OOP, you can start programming in a much more organised fashion.

I've programmed in Visual Basic 3 for a long time, so I had a lot of experience with functional programming, then coming to VB5 and discovering objects was an immense relief because I could relate real-world entities into my code, and it helped a lot.

That's the entire point of it, recreating real-world entities in your code. It makes reading and working easier cause you can pick up something and do stuff with it, or do stuff to it.

Cyril Gupta
A: 

It's probably possible to over-engineer a simple problem by making it unnecessarily complex (OO all the way down). However, for any sufficiently large problem, I do not think that it's probable that OO paradigm is what caused it to be large in the first place. Take an operating system for example, it's hard to imagine it being easy to maintain (code-wise) if it's not written in an object-oriented way.

Hao Wooi Lim
+1  A: 

If you have a bunch of "bare" functions in a large application, it's hard to make changes to those functions.

  • harder to see who is using the function ("if I change this, who does it affect?")
  • difficult to make changes to the functions without breaking other people's code.

If you wrap the functions up in classes, you help to isolate the scope of the code. It's not a magic bullet, but it helps.

Mark Harrison
+2  A: 

Encapsulation theory provides one objective reason why classes are better than having no classes at all.

The International Organisation for Standardization defines encapsulation as, 'The property that the information contained in an object is accessible only through interactions at the interfaces supported by the object.'

Thus, as some information is accessible via these interfaces, some information must be hidden and inaccessible within the object. The property such information exhibits is called information hiding, which Parnas defined by arguing that modules should be designed to hide both difficult decisions and decisions that are likely to change.

Note that word: change. Information hiding concerns potential events, such as the changing of difficult design decisions in the future.

Consider a class with two methods: method a() which is information hidden within the class, and method b() which is public and thus accessible directly by other classes.

There is a certain probability that a future change to method a() will require changes in methods in other classes. There is also a certain probability that a future change to method b() will require changes in methods in other classes. The probability that such ripple changes will occur for method a(), however, will usually be lower than that for method b() simply because method b() may be depended upon by more classes.

This reduced probability of ripple impacts is a key benefit of encapsulation.

Consider the maximum potential number of source code dependencies (MPE - the acronym is from graph theory) in any program. Extrapolating from the definitions above, we can say that, given two programs delivering identical functionality to users, the program with the lowest MPE is better encapsulated, and that statistically the more well-encapsulated program will be cheaper to maintain and develop, because the cost of the maximum potential change to it will be lower than the maximum potential change to the less well-encapsulated systém.

Consider, furthermore, a language with just methods and no classes and hence no means of information hiding methods from one another. Let's say our program has 1000 methods. What is the MPE of this program?

Encapsulation theory tells us that, given a system of n public nodes, the MPE of this system is n(n-1). Thus the MPE of our 1000 public methods is 999,000.

Now let's break that systém into two classes, each having 500 methods. As we now have classes, we can choose to have some methods public and some methods private. This will be the case unless every method is actually dependent on every other method (which is unlikely). Let's say that 50 methods in each class is public. What would the MPE of the systém be?

Encapsulation theory tells us it's: n((n/r) -1 + (r-1)p) where r is the number of classes, and p is the number of public methods per class. This would give our two-class systém an MPE of 499,000. Thus the maximum potential cost of a change in this two-class systém is already substantially lower than that of the unencapsulated systém.

Let's say you break your systém into 3 classes, each having 333 classes (well, one will have 334), and again each with 50 public methods. What's the MPE? Using the above equation again, the MPE would be approximately 482,000.

If the systém is broken into 4 classes of 250 methods each, the MPE will would be 449,000.

If may seem that increasing the number of classes in our systém will always decrease its MPE, but this is not so. Encapsulation theory shows that the number of classes into which the systém should be decomposed to minimise MPE is: r = sqrt(n/p), which for our systém is actually 4. A systém with 6 classes, for example, would have an MPE of 465,666.

Stellar answer. I think I get it, but even if I don't, I think reading this has made me incrementally a better programmer. I still have hope for the future, that we won't stop looking for better more usable ways to gain these encapsulation benefits.
Breton