• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

General OO questions

 
Chicken Farmer ()
Posts: 1932
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I'm taking an OO Engineering course, and I brought up the question about so-called "utility classes", for example the Math class and all it's static methods, private contstructor, etc. My question was basically how common are utility classes in the real-world, and do they not go against the whole OO principle. In other words, if I'm working on a program, and I have some methods that I can't really fit into a class, is it common to make a class that can't be instantiated or extended, but have methods that you may need?
The Math class holds a bunch of related math related functions, so that at least has some cohesiveness. What about just general maintenance methods, or something to that extent? In my opinion, and I avoid such thoughts and practices.
Also, another thing that struck me as odd is he mentioned that even simple data types have behaviors. Since I've always thought as behaviors as meaning methods/functions, this didn't sound right to me, but he was coming from the idea that you can add, subtract, etc things like int's, so that is a behavior.
Just was curious what others who have more experience in the field would think.
Jason
 
Ranch Hand
Posts: 118
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Jason,
Utility class means that it can return answer only based on the arguments you send when calling some methods. In many times we need this kind of functionality, like in Math class.
It looks reasonable, why should I need to create an instance of a class if I have nothing to add to that object? That is, this object works as same as its class.
Many people use static methods like procedure and it is terrible. This is not the case of using class method. Smalltalk also let you create and use class methods.
I Hope it helps,
Adrian
 
jason adam
Chicken Farmer ()
Posts: 1932
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I think you hit upon what I am trying to get at when you mentioned procedural. I have no problems using class methods, my question is about creating a class that has methods that don't seem to fit anywhere else. Class Math has a bunch of these, but they're all math related. What about a class, let's say called Utility, that just has a hodge-podge. Would it make more sense, or is it better design, to create this class instead of putting methods in a class that doesn't really fit?
 
Adrian Ferreira
Ranch Hand
Posts: 118
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Jason,
You can group many related methods in one class. Whether one method is related do other or not depends on your model and your abstract view for the problem.
If utility methods are related, group them in a class. If classes are tightly related, group them in a package. If a model appears with many loosely utility methods, may be it is time to reorganize the project.
IMO, Math class looks reasonable organized since every time I need some method, there is no difficult to presume where they are localized. You can give me some bad example in Math class and suggest some changes but in general they are related as you wrote before.
Adrian
 
Ranch Hand
Posts: 67
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Larman divides the design of objects into 2 groups: representational decomposition vs. behavioural decomposition.
As Jason states, representational decomposition is a common OO technique, where classes are used to represent real-world concepts in the domain. In contrast, behavioural decomposition assigns responsibilities by grouping behaviour. The java Math class is an example of this.
These type of behavioural classes, which provide utility methods and functions can be very useful - they focus on a very specific set of related tasks, which can promote re-use. However, this should not be an excuse for functional decomposition - the danger is that the design degenerates into a collection of 'function' classes. This is very common in those people new to OO design.
In addition, I would emphasise that the principles of good OO design are just as applicable to these 'behavioural' classes as they are to representational classes. A class which is a "hodge-podge" of unrelated methods is not good design practice. This gives rise to highly-coupled, incohesive classes.
One additional note, I sometimes find it useful to create one or two classes that contain methods that do not have a clear 'home' in the system. This is arguably a result of a poor design, but it is a useful technique none the less.
regards,
paul.
 
whippersnapper
Posts: 1843
5
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I saw Jason's post some time ago and finlly got the time to respond.


I'm taking an OO Engineering course, and I brought up the question about so-called "utility classes", for example the Math class and all it's static methods, private contstructor, etc. My question was basically how common are utility classes in the real-world, and do they not go against the whole OO principle.


Is there a specific OO principle (encapsulation, inheritance, polymorphism, etc.) or "good design practice" (Liskov substitution, programming to an interface, etc.) that you think such utility classes violate?
I'm not trying to be combative -- it's just that there seems to be so much fuzziness around what OO is that I think it's sometimes helpful to try to articulate which specific principles are being upheld or violated.


In other words, if I'm working on a program, and I have some methods that I can't really fit into a class, is it common to make a class that can't be instantiated or extended, but have methods that you may need?
The Math class holds a bunch of related math related functions, so that at least has some cohesiveness. What about just general maintenance methods, or something to that extent? In my opinion, and I avoid such thoughts and practices.


In Effective Java Joshua Bloch deals with this topic in the section "Item 3: Enforce noninstantiability with a private constructor" (page 12). Bloch says that though the idiom is often abused (used to write essentially procedural programs in OO languages), there are valid uses. He goes on to recommend that such classes be made noninstantiable and nonextendable by including a single explicit private constructor.
The example from Effective Java:

Here's what Bloch gives as some valid uses:


They can be used to group related methods on primitive values or arrays, in the manner of java.lang.Math or java.util.Arrays, or to group static methods on objects that implement a particular interface, in the manner of java.util.Collections. They can also be used to group methods on a final class, in lieu of extending the class.


Yeah, I know he wrote Arrays and Collections and I'll bet he was involved with Math. All three do use the private constructor like you pointed out for Math.
The main point he seems to be making is that instances of such classes don't make sense, so you should prevent their creation. (This is a sort of special case of advice he makes elsewhere -- either to design for inheritance or to prevent it.)
I think it's interesting Bloch mentions using such utility classes and methods on primitives and arrays.
Some of the static methods you find in java.lang.Math you also find as instance methods on BigInteger and BigDecimal (abs(), max(), min(), pow()). That is (ignoring for a second the issues about range that would lead you to choose between a primitive and BigInteger or BigDecimal), when you have an object to work on, you use instance methods for that object, but when you have a primitive you have to use the statics on java.lang.Math. If Java didn't have primitives for numbers, these static methods on java.lang.Math wouldn't be necessary. They'd be instance methods on whatever class(es) represented numbers.

Arrays are a bit flaky in Java too. Apparently they're "full-fledged" objects, but you create instances of them a bit differently from other objects. Plus they don't have any methods you can call on the array structure itself ("length" is apparently a public field). So in lieu of instance methods to call on arrays, you have all these statics in java.util.Arrays.
(I see the similarities between Collections and Arrays, but I'm not sure I understand what Bloch is getting at regarding the relevance of interefaces here. And I don't get the point about grouping methods on final classes either.)


Also, another thing that struck me as odd is he mentioned that even simple data types have behaviors.


I think "simple data types" muddies the water a bit. Do you mean primitives? Java makes the distinction between primitives and objects (objects as instances of classes or "Abstract Data Types"). Not all OO languages do.
Not to turn this into SmalltalkRanch, but some comparison with Smalltalk might be interesting. In Smalltalk, numbers are full-fledged objects and have all sorts of behavior.


Since I've always thought as behaviors as meaning methods/functions, this didn't sound right to me, but he was coming from the idea that you can add, subtract, etc things like int's, so that is a behavior.


Sure. I think you're coming at this with a Java-language bias. In Java, the typical way of doing math is to have operators act on primitives and produce a result. In Smalltalk, arithmetic operations such as "+", "-", aren't even "built into" the language; they're simply method calls on objects.
First consider the following Java:

Suppose Java didn't have primitives or operators, so these objects were the only way to represent numbers. Wouldn't line (A) be a fairly convincing argument that numbers have behavior?
Incidentally, the syntax in Smalltalk is much cleaner:
result := 3 + 5
"3" and "5" are both numeric literals (instances of the class SmallInteger). "+" is a method on SmallInteger. The method "+" is being called on the number "3" and is passing the parameter "5" into the method body. (Beware: having arithmetic operators as method calls wreaks havoc with traditional operator precedence.)
(Another behavior associated with numbers is looping. In Smalltalk loops aren't really built into the language either; they're just method calls on numbers. The following two code examples both print "Hello world" to the console 3 times.
1 to: 3 do: [:n | Transcript show: 'Hello world' ; cr ].
3 timesRepeat: [ Transcript show: 'Hello world' ; cr ].
Note that the stuff in square brackets makes up a block, which is a kind of object (which is being sent to the methods as a parameter and then code in the method says "execute the block passed in"). timesRepeat: and to:do: are both method calls on the SmallIntegers. (Smalltalk combines the method name and parameter list into a single unit, so to:do: is a method that takes two parameters.)
Consider the following Ruby code snippets, which do the same as the Smalltalk:
result = 3 + 5
1.upto( 3 ) { print "Hello World\n" }
3.times { print "Hello World\n" }
This is about where my knowledge of Smalltalk and Ruby tops out...
)
 
author
Posts: 14112
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Michael, nice post!

Originally posted by Michael Matola:
Is there a specific OO principle (encapsulation, inheritance, polymorphism, etc.) or "good design practice" (Liskov substitution, programming to an interface, etc.) that you think such utility classes violate?


*I* think it violates encapsulation, that is, putting the data and operations on the data into the same place.
Regards, Ilja
 
jason adam
Chicken Farmer ()
Posts: 1932
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Once again, Michael, you have provided wonderful explainations to basic questions I've posed.
Basically, my question was more in reference to classes that were a hodge-podge of methods. I can see the need for some where the methods are related, like Math. However, if you come up with a design, and find that there are a couple of behaviors that are needed, but no class or object that they neatly associate themselves with, do people sometimes just create a utility class that allows them use the behavior without having an object? Seems like bad design and some reworking should be done, but if we're talking about just one or two behaviors, is a complete redesign really warranted?
It just seems strange, and this could all be from my budding understanding of OO stuff in general, to have a class that is accessible from anywhere in your program to do work on any of your data, but not have an instance of that class anywhere. It just seems to harken back to procedural programming and subroutines (at least, what I understand of subroutines).

Yes, I am extremely Java biased, because it is the first language that I really have sunken my teeth into, and I thoroughly enjoy it. I'm going to be taking several C++ classes, as well as a couple more design classes, so I'm sure along the way my idea of what OO is will be a bit different than it is now, but no better time to start learning than the present!
Thanks again for the great responses, lots of light being shed
Jason
 
Michael Matola
whippersnapper
Posts: 1843
5
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator


It just seems strange, and this could all be from my budding understanding of OO stuff in general, to have a class that is accessible from anywhere in your program to do work on any of your data, but not have an instance of that class anywhere. It just seems to harken back to procedural programming and subroutines (at least, what I understand of subroutines).


Does System.out.println() -- or any other method on System -- trouble you? (Yes I know, println() is a method on out, which is a PrintStream object, but out is a static, making the whole expression fairly static.)
"Accessible from anywhere in your program" -- ok, I'll grant you that. "To do work on any of your data" -- well not just any data. It's data you've passed in as a parameter. I think that's still ok in terms of the Law of Demeter for methods -- but I'll have to read up on that before posting (and tie that in to a response to Ilja's post).


Basically, my question was more in reference to classes that were a hodge-podge of methods. I can see the need for some where the methods are related, like Math. However, if you come up with a design, and find that there are a couple of behaviors that are needed, but no class or object that they neatly associate themselves with, do people sometimes just create a utility class that allows them use the behavior without having an object? Seems like bad design and some reworking should be done, but if we're talking about just one or two behaviors, is a complete redesign really warranted?


Martin Fowler, in Refactoring, takes what appears to be a different tack, and seems to provide some guidelines along the lines you're asking about:
Suppose you're writing some code that uses another class and you find that the code should be pulled together as a method. If you can change the server class, go ahead -- write up the method and put it on the server class. But if you can't add to the server class, add the method to the client class. Fowler calls the method a "foreign method" and the refactoring Introduce Foreign Method. Plus the book indicates 3 steps to this refactoring:
-- Create the method in the client class. Here's an interesting recommendation -- Fowler says that the foreign method should not access any features of the client class. If it needs a value, it should be sent in as a parameter. (Fowler doesn't empasize this point -- but foreign methods do appear to be static.)
-- Make an instance of the server class the first parameter. (Jason -- you and I have seen this trick somewhere.)
-- Comment the foreign method as such.
Fowler goes on to say that if you end up creating too many foreign methods on a server class or find that multiple classes need the same foreign method, then the refactoring Introduce Local Extension is advised.
"Local extensions" are classes -- either a subclass or a wrapper of the original client -- for which you create an instance to get the added functionality. Fowler says that subclassing is generally easier and mroe straightfoward, but it's not always possible (original class may be final). He gives the steps for each in the book.
(Fowler points out that when using the wrapper approach you should have methods on the wrapper delegating back to the original class and some special concerns with the equals() method and methods that take the original class as an argument. But I saw a version of this technique recently that didn't delegate all the other methods -- clients were to use the wrapper only for the new methods and the original for all the original methods.)
So back to Jason's hodge-podge -- I'm guessing Fowler would not favor that approach. I guess the question to ask about the methods you have in mind is whether they are "randomly useful" kinds of things or do they clump together in some fashion. Could subsets of these methods be seen as functionality missing from some existing class, and therefore be a good candidate for a Fowleresque local extension?
I could come up with an example of a local extension with a wrapper, if anyone's interested in seeing that. Anybody else have a utility class whose methods they'd like to discuss?
[This message has been edited by Michael Matola (edited October 14, 2001).]
 
jason adam
Chicken Farmer ()
Posts: 1932
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Ya gotta love Fowler. I need to get his Refactoring book, everything else that I have read by him has been excellent, I hear that is one of top must reads.
The utility classes don't really bother me, I was mainly using them as examples of classes that are groups of often used methods. My main concern is when you can't find a place for just a couple of methods that, at the end of some iteration or whatever, you discover your design needs, but has no nice place to put them. However, looking at the link you provided for local extensions, and the explaination you provided, that appears to be a solution to what I was asking.
If you have time, and have a clear example, I'd love to see it.
Thanks!
Jason
 
With a little knowledge, a cast iron skillet is non-stick and lasts a lifetime.
reply
    Bookmark Topic Watch Topic
  • New Topic