sever oon

Ranch Hand
+ Follow
since Feb 08, 2004
Merit badge: grant badges
For More
Cows and Likes
Cows
Total received
0
In last 30 days
0
Total given
0
Likes
Total received
0
Received in last 30 days
0
Total given
0
Given in last 30 days
0
Forums and Threads
Scavenger Hunt
expand Ranch Hand Scavenger Hunt
expand Greenhorn Scavenger Hunt

Recent posts by sever oon

Hi all,

I'm writing an EJB3 application, and everything is going great. Except, I decided to split off the entity beans into a separately deployed jar (a persistence archive) because we have several different components that will make use of just the entity layer (each component consists of a layer of local session beans over the entities).

But when I do that, none of my session beans have access to the named queries defined in annotations on the entities. If I package the session beans and entity beans together, no problem. If I don't, I start getting hibernate MappingExceptions (JBoss uses Hibernate to implement the persistence part of the EJB3 spec).

Named queries can only be annotated on entities, so I can't move those annotations onto the session beans themselves and define them there. So what to do? Does anyone have experience here defining named queries for a persistence archive, and somehow making them visible to other components? They're all using the same persistence unit, btw.
Don't extend a class that implements Serializable if you don't want the child class to adhere to that contract as well.

One way to fix this would be to change the parent class. It could provide a final (so that it is non-virtual) method that hands back a serializable wrapper around itself (much like the way Collections hands back wrappers around maps that synchronizes them). Then subclasses are not required to be serializable.

Another approach is to have the child class aggregate an instance of the parent class, duplicate its API and forward the methods. That way, this new class does not have the parent in its hierarchy and claim to meet its contract.

Ironically, one approach you should *not* follow is very similar to the approach I recommended above. Like synchronization, the Collections API in the JDK provides a means of making a map (and other collections) unmodifiable by wrapping them so that methods that cause modifications throw UnsupportedOperationExceptions. This is terrible, and you should definitely not extend a parent class that is serializable and then start throwing these exceptions too.

Think about it...I write a method that takes in a Foo, which is Serializable. You extend Foo with Bar, a class that throws Unsupported OperationExceptions. Then you instantiate a Bar and hand it into my method that takes a Foo. This, of course, works just fine--polymorphically, you've made Bar so that it *is* a Foo.

But then my method, which has every right to expect the passed object to be serializable, gets a nasty surprise when it tries to serialize it. This is not the way to code.
18 years ago
Check out Sun's thoughts on this keyword: http://java.sun.com/docs/books/jls/strictfp-changes.pdf.

By the way, your best bet is to simply google the following search string: strictfp site:sun.com. That will turn up everything you could ever want to know.
18 years ago
My two cents...

Don't use any kind of naming that specifies something about the class or interface. This is the path that results in Hungarian Notation and results in horrible looking names like $_i32_p_fWndHndl. Ugh. People in this thread can't even stand a simple "I" prefix...why do anything that leads down that path?

No, the better solution is to have a good tool. Don't develop in Notepad--use IntelliJ or Eclipse. A good IDE can tell you everything you need to know about a variable...I believe you can even colorize them differently to make it obvious.

The real solution to this problem is proper architecture and design. If a project is written such that dependencies are managed correctly, then that means there are no circular dependencies at any level of granularity (class, package, project, etc). To do this, highly stable parts of the system should be separated from the rest of the code. This can be done by using interfaces, abstract factories, and packaging things properly.

It's nice that the convention of prefixing an "I" can cause developers to notice that things aren't being done correctly, but simply modifying a reference to be of an interface type doesn't really do anything if that interface isn't packaged correctly in the first place.

So I tend to think of this stripped-down kind of Hungarian Notation as a band-aid to mitigate larger problems. Like when someone says, "Prefer composition to inheritance"--this is bad advice--one ought to prefer composition when composition is called for, and inheritance when inheritance is called for. Following this dictum is a means to avoid learning how to properly use composition and inheritance for one more day. If the Holy Grail of OO development was simply doing away with inheritance, the good people at Sun would've taken it out of Java when they designed the language.

This is how I view the "I" prefix. Don't declare the type of your references randomly and you'll never run into a problem where you've accidentally used a class as a reference type instead of an interface.
18 years ago
Oh, and I forgot to add....if a caller wants to lookup a key on this new TwoWayHashMap by value, no problem:

18 years ago
Why not just switch them?

If you require two-way hash-based lookup, then create your own object that aggregates two HashMaps (not Hashtable, by the way--don't use that class over a HashMap unless you have a really good reason).



Instead of this approach, you could also have this class implement the Map interface and simply pass all the Map methods thru to your internal map instance (and populate the reverseMap when necessary). Then just add that one extra getByValue() method to use the reverseMap.

Or, instead of adding that one extra method directly to your TwoWayHashMap API, you could add a method instead that returns an instance of the Map interface backed by the reverseMap. That way you could get all of the Map functionality of the map when looking up forwards or backwards.

If you take this last approach, I highly recommend you return an unmodifiable view of the reverseMap. This forces the caller to modify your TwoWayHashMap through the main API only, not through an obtained reverseMap.



Using this method, it's important to note that this TwoWayHashMap is not thread-safe. That is, if one thread is putting in the main map, and another thread is reading from the view of the reverseMap, it's possible to get weird and inconsistent results. Initializing your internal maps to be synchronized won't help either because you need to sync operations *between* the two internal maps.

Fortunately, the good people at Sun already thought of this. All you have to do is have clients of this object instantiate sync'd TwoWayHashMaps wherever they are needed, using the standard mechanism:

18 years ago
You are incurring the wrath of the dependency monster.

The fact is, if you have code in one project that directly depends upon the API of any single object in another project, then you have a project dependency and they cannot be built separately. What you really want to do is get control over your dependencies, and here's how you do that.

I have a Person object in project A which wants to communicate with another Person object, and it uses a Phone object to do so, from project B. Since Person is using a Phone instance, it has to intimately know the Phone class' API. First, pick up the phone, then wait for a dial tone, then dial a number specifically formatted for input into the phone, loop talking into the microphone and listening at the speaker until the communication is done, then hang up the phone. A highly detailed sequence of interactions that's specific to this Phone object in project B and does not apply to other forms of communication (using IM, smoke signals, semaphore, etc). Furthermore, I cannot build project A unless project B is already built, even if Phone is the only object I use in all of project B. I've created a directional project-level dependency from A to B because of this usage of Phone's API.

Furthermore, it might turn out that to get Phone to compile, it has dependencies all throughout project B. It depends on all sorts of objects in project B, so what this boils down to is: if there's a single problem in any one part of the entire project B, and it doesn't build, I can't build A.

Here's how to fix it. Project A should define what it needs from a communication device API and define an interface. This interface belongs in project A and any two Persons in project A can use it. This API might look like this:



This is off-the-cuff as an example--in a real system it would probably make sense to build it out quite a bit more (for instance, instead of blocking to wait for a response from sendMessage(), it might make more sense to register a listener and receive the responses asynchronously). In any case, this API is defined based upon what the Person object needs from a communication device.

Then, Phone, in project B, can implement this interface. Now, project A doesn't depend on project B, but the other way round. Is this any better? Well...yes and no. Now you can compile project A without B, but not B without A...on the other hand, B is much easier to compile because it doesn't depend on any actual *code* from A, only an interface with no code (and therefore not likely to contain any bugs). Furthermore, project A could package up this interface (and all such interfaces implemented in B) into a jar file and build that jar separately and provide it to project B. This would be called an "SP" jar ("service provider"), so-called because it provides a set of APIs to a service provider (project B) to be implemented.

Or, you could allow the Communicator interface to be in project B, and have B package up all such interfaces separately in a jar. This kind of jar would be called a "client" jar, so-called because it is provided to all clients of B. You might say that in the previous case of an SP jar, A was providing a kind of client jar to B, so what's the difference? You'd be correct...but an SP jar is a specific kind of client jar. It simply denotes the roles of the two projects. In the former case, B is providing a service to A by implementing APIs controlled by A (specified in the SP jar). In the latter, B is in control of and owns the interfaces (specified in the client jar), so it's not implementing a service requested by A.

Or, you could make the interface a completely separate project altogether, project C. Now, both projects A and B depend upon project C, but project C consists of nothing but interfaces--it has no code whatsoever so it's nearly guaranteed to build. In this case, the only output of building project C is to generate a jar (or jars) with highly abstract APIs in it. With this approach, project C plays the role of a specification (or perhaps a "protocol", depending on whether it contains interfaces that define what each project does, or simply the communication between the two projects).

Regardless of what approach you use, you are very wise to recognize that dependencies between projects are something that must be carefully controlled.

For more information on these ideas, read the following articles in this list: Stability and the Dependency Inversion Principle.
18 years ago
You are correct, and very perceptive at that. Just because you've made a variable private and provided getters and setters does not mean your class provides good encapsulation.

*Good* encapsulation has to do with whether the API of your class, as a whole, is consistent. Consistent with itself and with the system as a whole. This gets at the fundamentals of why the class exists. What was it intended to do? Does the API provide those core capabilities? Does it provide capabilities beyond what it makes sense for it to do?

The simple mechanical answer to your question is that providing method-based access to a private variable does give you some level of encapsulation. But it really depends on the variable. Should that variable be accessible through the public API in the first place? If not, then providing a getter breaks encapsulation. Is the object supposed to be immutable? If so, then providing a setter breaks encapsulation. Furthermore, if the method performs a sequence of operations that are not intended to be overridden, and the method is not marked final, that breaks encapsulation. In other words: providing other objects the capability to alter the state of your object in any way your object is not prepared for breaks encapsulation.

In my estimation, blithely providing getters and setters for every variable is a horrible way to program in OO.
You seem to be confusing a "component object model" with a "design pattern". MVC is a component object model. It takes one logical object and splits it up into three physical objects (model, view, and controller). The point is to separate out three different kinds of logic into three physically distinct places. EJB is another instance of a component object model...the point of this one is to split up remote API from location/creation logic from the remotely performed business logic. You can think of a component object model as being a way of "projecting" a single object onto a set of orthogonal axes...breaking it down into parts that can operate independently from one another.

A design pattern is NOT a component object model. A design pattern is a collaboration of different objects intended to solve a particular kind of problem. As such, the "best" design pattern depends on the problem you're trying to solve. The book by the Gang of Four called Design Patterns details these problems and their associated patterns at length--you might want to poke through it for ideas.

Your question is sort of like asking, which is better, a hammer or a screwdriver? It depends...are you trying to put in a nail or a screw?
Here's a list of articles on various design principles. Start with the article called Principles and Patterns and work your way through from there.

I cannot express this enough--these are the best articles written by authorities on the general principles of OO design and analysis that I've ever seen.
I think this is exactly what you're looking for: Object Mentor - Design Principles.

Start with the Principles and Patterns article and go from there.
Direct implementation of an interface, typically an event listener, is what I usually use inner classes for. If you're writing a big class and you've provided a method that should be called when a button is clicked on the UI, you can have your class implement the ButtonListener (or whatever it's called) interface.

But is your class a button listener? Well, obviously it's interested in when a button is clicked for this particular application, but if it doesn't really make sense for it to define itself as a button listener in other contexts, then you probably don't want to identify it as such by having it implement that interface. In my way of thinking, the code that handles a bunch of UI events may happen to be in a class--that doesn't mean that class should implement 20 different event listener interfaces itself. That pollutes the inheritance hierarchy.

Much cleaner is to implement an anonymous inner class that implements the ButtonListener interface and register that inner class as an event handler on the button. The advantage of doing this is that this inner class can now forward to a private method in the enclosing class that handles the event without polluting the enclosing class' inheritance hierarchy.

Other uses for inner classes center around "friend" type relationships in C++, but without all the problems that C++-style friendliness carries along with it.

One thing you should be aware of is that if you define an anonymous inner class in a method, it may not use variables local to that method scope unless they are marked final. If you think about this for a while, it will make sense, but it throws a lot of people at first.
18 years ago
I am confident that this set of articles will exactly address the problem you are experiencing: Object Mentor Articles - Design Principles

Begin by reading this article first: Principles and Patterns
18 years ago
Having static methods or data is decidedly not against OO design principles in and of itself. Like anything else in OOP, though, it can be misused in a non-OO way, just as one can have an Automobile class extend an Engine class or vice versa instead of having Automobile aggregate an Engine instance.

The java.lang.Math class has been the subject of much debate since it was introduced as part of the standard library, and lots of people smarter than me have weighed in on whether it's OO or not, so you'd do well to research what they say and decide for yourself. I think the overall consensus is that it is indeed not in line with the core principles of OOD, and the original designers knew that, but did it anyway for performance reasons.

The main issue that had to be dealt with was this: Java could not be a 100% OO language when it was first introduced because there was a legitimate argument that without primitives of any kind, it would be too slow. So int, char, float, double, all these things made it into the language. Now the problem becomes, we have none objects and we need a sensible way to deal with them. The best thing to do is to encapsulate off to the side a library of functions that look more like code from the procedural world than OO. So that's where Math comes from.

So what have we learned? OO is not a simple boolean state...most languages do not cleanly fall into the category of being "OO" or "not OO". C is an example of a language that does fall neatly into "not OO". Smalltalk is an example of a language that falls neatly into "OO". C++ is a hybrid language that has the *capability* to allow OO programming, but it does absolutely nothing to enforce that OO programming is done. Java is much more OO in that it enforces several basic OO programming principles (no globals, you can't add new primitives, etc), but it cannot be assigned to the "OO" category because of things like ints and java.lang.Math.

I hope this does nothing to denigrate the language in your eyes--it's still what it is, a useful programming language that expresses OO designs simply and clearly.

The moral of this story is: don't mimic the Math library in your own code unless you are dealing exclusively with primitives and encapsulate it off to the side as a bit of functional, procedural code in an OO world. :-)
18 years ago
Okie dokie. Thanks all...replying to Thomas Paul...
19 years ago