Logic inside an enum - java

My colleagues and I were having a discussion regarding logic in enums. My personal preference is to not have any sort of logic in Java enums (although Java provides the ability to do that). The discussion in this cased centered around having a convenience method inside the enum that returned a map:
public enum PackageType {
Letter("01", "Letter"),
..
..
Tube("02", "Packaging Tube");
private String packageCode;
private String packageDescription;
..
..
public static Map<String, String> toMap() {
Map<String, String> map = new LinkedHashMap<String, String>();
for(PackageType packageType : PackageType.values()) {
map.put(packageType.getPackageCode(), packageType.getPackageDescription());
}
return map;
}
}
My personal preference is to pull this out into a service. The argument for having the method inside the enum centered around convenience. The idea was that you don't have to go to a service to get it, but can query the enum directly.
My argument centered around separation of concern and abstracting any kind of logic out to a service. I didn't think "convenience" was a strong argument to put this method inside an enum.
From a best-practices perspective, which one is better? Or does it simply come down to a matter of personal preference and code style?

Well, I've done this before but that certainly doesn't mean it's the 'best' thing to do.
From my perspective, though, I would prefer to have that logic on the enum, for the same reason you wouldn't move a 'toString' method out to a service. The logic only concerns the enum itself, and its own representation.
I think it would be misleading to move such a method out to a service - by placing it on the enum you are being up front about the fact that the enum has a 'toMap' method. Someone who didn't know about the service and was just looking at the enum may not know that.
It also helps with auto completion in IDE's - I can hit the '.' key and instantly see methods provided by the object.

I think it probably comes down to personal preference and whether or not you think the logic might change in the future.
The best use case for enum logic (since it's pretty static) is for things that aren't going to change. The logic in java.util.concurrent.TimeUnit is a pretty good example of this: the conversion factors between time units are well-defined and won't ever change, so it's a good candidate for static logic to embedded within the enum.

I cannot see any persuasive reason why it is "good practice" ... or "bad practice" ... to do what you are suggesting.
I'm inclined to go for the convenience argument. But frankly, this is not the kind of thing that it is productive to spend man-days debating ... IMO.

I have tried logic in enums a few times, but the only thing I am ever really happy about is something like:
// not compiled, so might have errors...
public enum Foo
{
A,
B;
// not complete, doesn't properly handle invalid cases...
public static Foo fromString(final String str)
{
final String strLower;
final Foo val;
strLower = str.toLowerCase();
if(strLower.equals("a")
{
val = A;
}
else if(strLower.equals("b")
{
val = B;
}
else
{
throw new IllegalArgumentException(/*...*/);
}
return (val);
}
}
Generally once you start adding instance variables/methods you should probably be doing something with a proper class.

I'd start with putting it in the enum. If there will be only one toMap() method in the system, having an extra class is surely unnecessary and will be annoying.
If I had bunch of enums from which I want to create such map, or maybe anticipate such situation, THEN I'll create a static utility class, and a generified utility method to do that.
My personal opinion is, practicality tramps theory.
EDIT: Oh wait, this would be difficult to provide a generic utility method for.. In that case, if the method is going to be that enum specific, I'd definitely go with putting it in the enum. If I were the maintenance programmer, I'd be very dissatisfied if you would have an extra class that I have to look for.

Like anything it would depend on the usage, there are general rules but practicality should always win the argument. What is the map used for? Would you ever need to restrict the contents of the map, e.g. if the map is used to populate a combo box, is there ever the need to remove some choices, say if some carriers only handled certain package types a strategy could be used to populate a map, that would be best done outside of the enum.
Despite that, my preference would be to have a create the map elsewhere, that extra level of indirection is never a hindrance to flexibility and could save a lot of grief and adds little overhead now. And you can also code it so you can get similar functionality with other enums.

Related

Is it okay to expose the state of an Immutable object?

Having come across the concept of immutable objects recently, I would like to know the best practices for controlling access to the state. Even though the object oriented part of my brain makes me want to cower in fear at the sight of public members, I see no technical issues with something like this:
public class Foo {
public final int x;
public final int y;
public Foo( int x, int y) {
this.x = x;
this.y = y;
}
}
I would feel more comfortable declaring the fields as private and providing getter methods for each but this seems overly complex when the state is explicitly read only.
What is the best practice for providing access to the state of an immutable object?
It depends entirely on how you're going to use the object. Public fields aren't inherently evil, it's just bad to default everything to being public. For example the java.awt.Point class makes its x and y fields public, and they aren't even final. Your example seems like a fine use of public fields, but then again you might not want to expose all of the internal fields of another immutable object. There is no catch-all rule.
I have thought the same in the past but usually end up making variables private and using getters and setters so that later on I'll still have the option of making changes to the implementation while keeping the same interface.
This did remind me of something I read recently in "Clean Code" by Robert C. Martin. In chapter 6 he gives a slightly different perspective. For example, on page 95 he states
"Objects hide their data behind abstractions and expose functions that operate on that data. Data structure expose their data and have no meaningful functions."
And on page 100:
The quasi-encapsulation of beans seems to make some OO purists feel better but usually provides no other benefit.
Based on the code sample, the Foo class would seem to be a data structure. So based on what I understood from the discussion in Clean Code (which is more than just the two quotes I gave), the purpose of the class is to expose data, not functionality, and having getters and setters probably does not do much good.
Again, in my experience, I have usually gone ahead and used the "bean" approach of private data with getters and setters. But then again, no one ever asked me to write a book about how to write better code so maybe Martin has something to say.
If your object is of local-enough usage that you don't care about the issues of breaking API changes for it in the future, there is no need to tack getters on top of the instance variables. But this is a general subject, not specific to immutable objects.
The advantage of using getters comes from one extra layer of indirection, which may come in handy if you are designing an object which will be widely used, and whose utility will extend into unforseeable future.
Regardless of immutability, you're still exposing the implementation of this class. At some stage you'll want to change the implementation (or perhaps produce various derivations e.g. using the Point example, you may want a similar Point class using polar coordinates), and your client code is exposed to this.
The above pattern may well be useful, but I'd generally restrict it to very localised instances (e.g. passing tuples of information around - I tend to find that objects of seemingly unrelated info, however, either are bad encapsulations, or that the info is related, and my tuple transforms into a fully-fledged object)
The big thing to keep in mind is that function calls provide a universal interface. Any object can interact with other objects using function calls. All you have to do is define the right signatures, and away you go. The only catch is that you have to interact solely through these function calls, which often works well but can be clunky in some cases.
The main reason to expose state variables directly would be to be able to use primitive operators directly on these fields. When done well, this can enhance readability and convenience: for example, adding Complex numbers with +, or accessing a keyed collection with []. The benefits of this can be surprising, provided that your use of the syntax follows traditional conventions.
The catch is that operators are not a universal interface. Only a very specific set of built-in types can use them, these can only be used in the ways that the language expects, and you cannot define any new ones. And so, once you've defined your public interface using primitives, you've locked yourself into using that primitive, and only that primitive (and other things that can be easily cast to it). To use anything else, you have to dance around that primitive every time you interact with it, and that kills you from a DRY perspective: things can get very fragile very quickly.
Some languages make operators into a universal interface, but Java doesn't. This is not an indictment of Java: its designers chose deliberately not to include operator overloading, and they had good reasons to do so. Even when you're working with objects that seem to fit well with the traditional meanings of operators, making them work in a way that actually makes sense can be surprisingly nuanced, and if you don't absolutely nail it, you're going to pay for that later. It is often much easier to make a function-based interface readable and usable than to go through that process, and you often even wind up with a better result than if you'd used operators.
There were tradeoffs involved in that decision, however. There are times when an operator-based interface really does work better than a function-based one, but without operator overloading, that option just isn't available. Trying to shoehorn operators in anyway will lock you into some design decisions that you probably don't really want to be set in stone. The Java designers thought that this tradeoff was worthwhile, and they might even have been correct about that. But decisions like this don't come without some fallout, and this kind of situation is where the fallout hits.
In short, the problem isn't exposing your implementation, per se. The problem is locking yourself into that implementation.
Actually, it breaks encapsulation to expose any property of an object in any way -- every property is an implementation detail. Just because everybody does this doesn't make it right. Using accessors and mutators (getters and setters) doesn't make it any better. Rather, the CQRS patterns should be used to maintain encapsulation.
I know only one prop to have getters for final properties. It is the case when you'd like to have access to the properties over an interface.
public interface Point {
int getX();
int getY();
}
public class Foo implements Point {...}
public class Foo2 implements Point {...}
Otherwise the public final fields are OK.
The class that you have developed, should be fine in its current incarnation. The issues usually come in play when somebody tries to change this class or inherit from it.
For example, after seeing above code, somebody thinks of adding another member variable instance of class Bar.
public class Foo {
public final int x;
public final int y;
public final Bar z;
public Foo( int x, int y, Bar z) {
this.x = x;
this.y = y;
}
}
public class Bar {
public int age; //Oops this is not final, may be a mistake but still
public Bar(int age) {
this.age = age;
}
}
In above code, the instance of Bar cannot be changed but externally, anybody can update the value of Bar.age.
The best practice is to mark all fields as private, have getters for the fields. If you are returning an object or collection, make sure to return unmodifiable version.
Immunatability is essential for concurrent programming.
An object with public final fields that get loaded from public constructor parameters effectively portrays itself as being a simple data holder. While such data holders aren't particularly "OOP-ish", they are useful for allowing a single field, variable, parameter, or return value to encapsulate multiple values. If the purpose of a type is to serve as a simple means of gluing a few values together, such a data holder is often the best representation in a framework without real value types.
Consider the question of what you would like to have happen if some method Foo wants to give a caller a Point3d which encapsulates "X=5, Y=23, Z=57", and it happens to have a reference to a Point3d where X=5, Y=23, and Z=57. If the thing Foo has is known to be a simple immutable data holder, then Foo should simply give the caller a reference to it. If, however, it might be something else (e.g. it might contain additional information beyond X, Y, and Z), then Foo should create a new simple data holder containing "X=5, Y=23, Z=57" and give the caller a reference to that.
Having Point3d be sealed and expose its contents as public final fields will imply that methods like Foo may assume it's a simple immutable data holder and may safely share references to instances of it. If code exists that make such assumptions, it may be difficult or impossible to change Point3d to be anything other than a simple immutable data holder without breaking such code. On the other hand, code which assumes Point3d is a simple immutable data holder can be much simpler and more efficient than code which has to deal with the possibility of it being something else.
You see this style a lot in Scala, but there is a crucial difference between these languages: Scala follows the Uniform Access Principle, but Java doesn't. That means your design is fine as long as your class doesn't change, but it can break in several ways when you need to adapt your functionality:
you need to extract an interface or super class (e.g. your class represents complex numbers, and you want to have a sibling class with polar coordinate representation, too)
you need to inherit from your class, and information becomes redundant (e.g. x can be calculated from additional data of the sub-class)
you need to test for constraints (e.g. x must be non-negative for some reason)
Also note that you can't use this style for mutable members (like the infamous java.util.Date). Only with getters you have a chance to make a defensive copy, or to change representation (e.g. storing the Date information as long)
I use a lot constructions very similar to the one you put in the question, sometimes there are things that can be better modeled with a (sometimes inmutable) data-strcuture than with a class.
All depends, if you are modeling an object, an object its defined by its behaviors, in this case never expose internal properties. Other times you are modeling a data-structure, and java has no special construct for data-structures, its fine to use a class and make public all the properties, and if you want immutability final and public off course.
For example, robert martin has one chapter about this in the great book Clean Code, a must read in my opinion.
In cases where the only purpose is to couple two values to each other under a meaningful name, you may even consider to skip defining any constructors and keep the elements changeable:
public class Sculpture {
public int weight = 0;
public int price = 0;
}
This has the advantage, to minimize the risk to confuse the parameter order when instantiating the class. The restricted changeability, if needed, can be achieved by taking the whole container under private control.
Just want to reflect reflection:
Foo foo = new Foo(0, 1); // x=0, y=1
Field fieldX = Foo.class.getField("x");
fieldX.setAccessible(true);
fieldX.set(foo, 5);
System.out.println(foo.x); // 5!
So, is Foo still immutable? :)

Partly mutable API class with a generic variable holder for client use

I am building an API. One of its functions is to perform some resource analysis (imagine a document, URI, or DB, not important what) and return a List<Finding> where Finding is a POJO. I want the Finding to be immutable once returned from the API, with all the data returned by the API, however, I would like to have a single setUserNote(String) method for client convenience.
The reason for it is so that a client gets a listing of Findings, it can process them while using setUserNote to save its own data in the object itself, like a plain note. I think that would be a neat convenience preferable to the client having to extend Finding just to add that one variable or encapsulate it as an instance variable and then ExtendedFinding.someMethod() { return this.finding.someMethid(); } for every method in Finding. Furthermore, it would be messy, to say the least, for the client to construct ExtendedFinding out of the Finding he gets from the API. That's why I plan to just simply give them that one field they can use for convenience.
Questions:
Is this bad design and why? I have never done anything like this before nor have I seen API classes come with an arbitrary data holder variable for client convenience.
Let's say this is a bad design. What would be an applicable design pattern to easily propagate Finding to construct ExtendedFinding by the client? Surely, you could have something like public ExtendedFinding(Finding) { /* copy vars one by one */ } but that is far from elegant
First your third point, final in no way makes a class immutable - it signifies that the class cannot be inherited from. So you cannot extend a final class.
For your main problem, why don't you cast your POJO to an interface and return a list of that rather than the underlying POJO. You can then make your actual POJO class package private so that the client cannot cast it back:
public static interface Finding {
//all public getters
void setUserNote();
}
static final class FindingImpl implements Finding {
#Override
public void setUserNote() {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
}
private final Collection<FindingImpl> findingImpls = new ArrayList<>();
public Collection<Finding> getFindings() {
final Collection<Finding> findings = new ArrayList<>();
for (final FindingImpl fi : findingImpls) {
findings.add(fi);
}
return findings;
}
This is not necessarily bad design. It sounds uncommon though. It is important to keep in mind the probable uses of an API when designing it, but I feel this goes a little too far:
It breaks the single-responsibility principle: the class now does both its job of representing Findings and of being a container for user specified data.
It limits the user to String notes instead of arbitrary objects. For example they wouldn't be able to use a Map or a custom POJO if they need to. (This could be easily fixed using generics, though.)
A better solution might be defining the equals and hashCode methods in the Finding class. This way these objects could be used as keys to a Map, and users would be able to store their notes outside of your API.
Another solution might defining a new class to represent the pair of a Finding and user notes. This has a cleaner "feel" than storing notes within the otherwise-immutable Finding class, but the added complexity might make it not worth the effort. Which solution is best really depends on the situation; there is no right or wrong answer.
(By the way, the final keyword doesn't make a class immutable. It just means you can't define subclasses for it. You can create mutable classes that are final - take for example StringBuilder)
I'm confused. If you return a Finding to me, that you consider immutable, how does it make a lick of sense for me to be able to inject a note, one time, into that object? The presumption would be that other people might be shown the same findings, no?
The correct answer here is that you should have another class: FindingComment with the commenter's id, the id of the Finding and a timestamp.
Your instinct that extending the class to glom a comment on is surely correct!

avoid instanceof in Java

I have been told at some stage at university (and have subsequently read in upteen places) that using instanceof should only be used as a 'last resort'. With this in mind, is anyone able to tell be if the following code I have is a last resort. I have had a look around on stack overflow but cannot quite find a similar scenario - perhaps I have missed it?
private void allocateUITweenManager() {
for(GameObject go:mGameObjects){
if (go instanceof GameGroup) ((GameGroup) go).setUITweenManager(mUITweenManager);
}
}
where
mGameObjects is an array, only some of which are GameGroup type
GameGroup is a subclass of abstract class GameObject.
GameGroup uses interface UITweenable which has method setUITweenManager()
GameObject does not use interface UITweenable
I suppose I could equally (and probably should) replace GameGroup in my code above with UITweenable - I would be asking the same question.
Is there another way of doing this that avoids the instanceof? This code cannot fail, as such (I think, right?), but given the bad press instanceof seems to get, have I committed some cardinal sin of OOP somewhere along the line that has me using instanceof here?
Thanks in advance!
I learned about Visitor pattern in Compiler class at university, I think it might apply in your scenario. Consider code below:
public class GameObjectVisitor {
public boolean visit(GameObject1 obj1) { return true; }
.
.
// one method for each game object
public boolean visit(GameGroup obj1) { return true; }
}
And then you can put a method in GameObject interface like this:
public interface GameObject {
.
.
public boolean visit(GameObjectVisitor visitor);
}
And then each GameObject implements this method:
public class GameGroup implements GameObject {
.
.
.
public boolean visit(GameObjectVisitor visitor) {
visitor.visit(this);
}
}
This is specially useful when you've complex inheritance hierarchy of GameObject. For your case your method will look like this:
private void allocateUITweenManager() {
GameObjectVisitor gameGroupVisitor = new GameObjectVisitor() {
public boolean visit(GameGroup obj1) {
obj1.setUITweenManager(mUITweenManager);
}
};
for(GameObject go:mGameObjects){
go.visit(gameGroupVisitor);
}
}
EDIT
There are two primary things you can do here to relieve yourself of this specific instance of instanceof. (pun?)
Do as my initial answer suggested and move the method you are targeting up to the class you are iterating. This isn't ideal in this case, because the method doesn't make sense to the parent object, and would be polluting as Ted has put it.
Shrink the scope of the objects you are iterating to just the objects that are familiar with the target method. I think this is the more ideal approach, but may not be workable in the current form of your code.
Personally, I avoid instanceof like the plague, because it makes me feel like I completely missed something, but there are times where it is necessary. If your code is laid out this way, and you have no way to shrink the scope of the objects you are iterating, then instanceof will probably work just fine. But this looks like a good opportunity to see how polymorphism can make your code easier to read and maintain in the future.
I am leaving the original answer below to maintain the integrity of the comments.
/EDIT
Personally, I don't think this is a good reason to use instanceof. It seems to me that you could utilize some polymorphism to accomplish your goal.
Have you considered making setUITweenManager(...) a method of GameObject? Does it make sense to do this?
If it does make sense, you could have your default implementation do nothing, and have your GameGroup override the method to do what you want it to do. At this point, your code could just look like this then:
private void allocateUITweenManager() {
for(GameObject go:mGameObjects){
go.setUITweenManager(mUITweenManager);
}
}
This is polymorphism in action, but I am not sure it would be the best approach for your current situation. It would make more sense to iterate the Collection of UITweenable objects instead if possible.
The reason why instanceof is discouraged is because in OOP we should not examine object's types from outside. Instead, the idiomatic way is to let object themselves act using overriden methods. In your case, one possible solution could be to define boolean setUITweenManager(...) on GameObject and let it return true if setting the manager was possible for a particular object. However if this pattern occurs in many places, the top-level classes can get quite polluted. Therefore sometimes instanceof is "lesser evil".
The problem with this OPP approach is that each object must "know" all its possible use cases. If you need a new feature that works on your class hierarchy, you have to add it to the classes themselves, you can't have it somewhere separate, like in a different module. This can be solved in a general way using the visitor pattern, as others suggested. The visitor pattern describes the most general way to examine objects, and becomes even more useful when combined with polymorphism.
Note that other languages (in particular functional languages) use a different principle. Instead of letting objects "know" how they perform every possible action, they declare data types that have no methods on their own. Instead, code that uses them examines how they were constructed using pattern matching on algebraic data types. As far as I know, the closest language to Java that has pattern matching is Scala. There is an interesting paper about how Scala implements pattern matching, which compares several possible approaches: Matching Objects With Patterns. Burak Emir, Martin Odersky, and John Williams.
Data in object-oriented programming is organized in a hierarchy of classes. The problem of object-oriented pattern matching is how to explore this hierarchy from the outside. This usually involves classifying objects by their run-time type, accessing their members, or determining some other characteristic of a group of objects. In this paper we compare six different pattern matching techniques: object-oriented decomposition, visitors, type-tests/typecasts, typecase, case classes, and extractors. The techniques are compared on nine criteria related to conciseness, maintainability and performance. The paper introduces case classes and extractors as two new pattern-matching methods and shows that their combination works well for all of the established criteria.
In summary: In OOP you can easily modify data types (like add subclasses), but adding new functions (methods) requires making changes to many classes. With ADT it's easy to add new functions, but modifying data types requires modifying many functions.
The problem with instanceof is that you can suffer from future object hierarchy changes. The better approach is to use Strategy Pattern for the cases where you are likely to use instanceof. Making a solution with instanceof you are falling into a problem Strategy is trying to solve: to many ifs. Some guys have founded a community. Anti-IF Campaign could be a joke but untipattern is serious. In a long term projects maintaining 10-20 levels of if-else-if could be a pain. In your case you'd better make a common interface for all objects of your array and implement setUITweenManager for all of them through an interface.
interface TweenManagerAware{
setUITweenManager(UITweenManager manager);
}
It is always a bit "fishy" to me to mix objects of different classes in the same Collection. Would it be possible / make sense to split the single Collection of GameObjects into multiple Collections, one of mere GameObjects, another of UITweenables? (e.g. use a MultiMap keyed by a Class). Then you could go something like:
for (UITweenable uit : myMap.get(UITweenable.class)) {
uit.setUITweenManager(mUITweenManager);
}
Now, you still need an instanceof when you insert into the map, but it's better encapsulated - hidden from the client code who doesn't need to know those details
p.s. I'm not a fanatic about all the SW "rules", but Google "Liskov Substitution Principle".
You could declare setUITweenManager in GameObject with an implementation that does nothing.
You could create an method that returns an iterator for all UITweenable instances in array of GameObject instances.
And there are other approaches that effectively hide the dispatching within some abstraction; e.g. the Visitor or Adapter patterns.
... have I committed some cardinal sin of OOP somewhere along the line that has me using instanceof here?
Not really (IMO).
The worst problem with instanceof is when you start using it to test for implementation classes. And the reason that is particularly bad is that it makes it hard to add extra classes, etcetera. Here the instanceof UITweenable stuff doesn't seem to introduce that problem, because UITweenable seems to be more fundamental to the design.
When you make these sorts of judgement, it is best to understand the reasons why the (supposedly) bad construct or usage is claimed to be bad. Then you look at you specific use-case and make up whether these reasons apply, and whether the alternatively you are looking at is really better in your use-case.
You could use the mGameObjects container for when you need to do something on all game objects and keep a separate container only for GameGroup objects.
This will use some more memory, and when you add/remove objects you have to update both containers, but it shouldn't be a noticeable overhead, and it lets you loop very efficiently through all the objects.
The problem with this approach is that it doesn't usually appear at one place only in your code and thus makes it more or less painful to add another implementations of the interface in the future. Whether to avoid it depends on your consideration. Sometimes YAGNI can be applied an this is the most straightforward way.
Alternatives had been suggested by others, for example the Visitor pattern.
I have another suggestion of a way to avoid instanceof.
Unless you are using a generic factory, at the moment when you create a GameObject you know what concrete type it is. So what you can do is pass any GameGroups you create an observable object, and allow them to add listeners to it. It would work like this:
public class Game {
private void makeAGameGroup() {
mGameObjects.add(new GameGroup(mUITweenManagerInformer));
}
private void allocateUITweenManager() {
mUITweenManagerInformer.fire(mUITweenManager);
}
private class OurUITweenManagerInformer extends UITweenManagerInformer {
private ArrayList<UITweenManagerListener> listeners;
public void addUITweenManagerListener(UITweenManagerListener l) {
listeners.add(l);
}
public void fire(UITweenManager next) {
for (UITweenManagerListener l : listeners)
l.changed(next);
}
}
private OurUITweenManagerInformer mUITweenManagerInformer = new OurUITweenManagerInformer();
}
public interface UITweenManagerInformer {
public void addUITweenManagerListener(UITweenManagerListener l);
}
public interface UITweenManagerListener {
public void changed(UITweenManager next);
}
What draws me to this solution is:
Because a UITweenManagerInformer is a constructor parameter to GameGoup, you cannot forget to pass it one, whereas with an instance method you might forget to call it.
It makes intuitive sense to me that information that an object needs (like the way a GameGroup needs knowledge of the current UITweenManager) should be passed as a constructor parameter -- I like to think of these as prerequisites for an object existing. If you don't have knowledge of the current UITweenManager, you shouldn't create a GameGroup, and this solution enforces that.
instanceof is never used.

Should my classes restrict developers from doing wrong things with them?

I am trying to understand where good contracts end and paranoia starts.
Really, I just have no idea what good developer should care about and what shall he leave out :)
Let's say I have a class that holds value(s), like java.lang.Integer. Its instances are aggregated by other objects (MappedObjects), (one-to-many or many-to-many), and often used inside MappedObjects' methods. For performance reasons, I also track these relationships in TreeMap (guava MultiMap, doesn't matter) in addition, to be able to get fast iterations over MappedObjects bound to some range of Integer keys.
So, to keep system in consistent state, I should modify MappedObject.bind(Integer integer) method to update my Map like:
class MappedObject {
public void bind (Integer integer) {
MegaMap.getInstance().remove(fInteger, this);
fInteger = integer;
MegaMap.getInstance().add(fInteger, this);
}
...
private Integer fInteger;
}
I could just make abstract MappedObject class with this final method, forcing other to inherit from it, but it is rude. If I will define MappedObject as interface with method bind() and provide skeletal implementation -- other developer might later just forget to include it in object and implement method by himself without Map updating.
Yes, you should force people to do the right thing with your code. A great example of letting people do the wrong thing is the servlet method init( ServletConfig config ) that expected you would store the servlet config yourself but, obviously, a lot of people forgot to store the config and when running their servlets just failed to work.
When defining APIs, you should always follow the open-closed principle, your class should be open for extension and closed for modification. If your class has to work like this, you should only open extension points where they make sense, all the other functionality should not be available for modification, as it could lead to implementation issues in the future.
Try to focus on functionality first and leave all unnecessary things behind. Btw you can't prohibit reflection so don't worry too much on misuse. On the other hand your API should be clear and straightforward so users will have clear idea, what they should and what they shouldn't do with it.
I'd say your classes should be designed for as simple use as possible.
If you allow a developer to override methods you definitely should document the contract as good as possible. In that case the developer opts to override some basic functionality and thus is responsible to provide an implementation that adheres to the contract.
In cases where you don't want the developer to override parts of the functionality - for security reasons, if there is no sensible alternative etc. - just make that part final. In your case, the bind method might look like this:
class MappedObject {
public final void bind (Integer integer) {
MegaMap.getInstance().remove(fInteger);
internalBind( integer );
MegaMap.getInstance().add(fInteger);
}
protected void internalBind( Integer integer ) {
fInteger = integer;
}
...
private Integer fInteger;
}
Here you'd allow the developer to override the internalBind() method but ensure that bind() will do the mapping.
To summarize: Make using and extending classes as easy as (sensibly) possible and don't have the developer to copy lots of boiler plate code (like the map updates in your case) in case he just wants to override some basic functionality (like the actual binding).
At least you should do really everything that prevents bugs but cost no effort.
For example: use primitive types (int) instead of wrappers (Integer) if the variable is not allowed to be null.
So in your bind method. If you not have intended to bind null, then use int instead of Integer as parameter type.
If you think your API users are stupid, you should prohibit wrong usage. Otherwise you should not stand in their way to do things they need to do.
Domumentation and good naming of classes and methods should indicate how to use your API.

Using an untyped wrapper class around objects stored in XML, is this bad?

class MyThing {
protected HashMap<String,Object> fields;
protected MyThing(HashMap<String,Object> newFields){
fields.putAll(newFields);
}
protected Object get(String key){
return fields.get(key);
}
}
Now a little background. I am using this class as a super class to a bunch of different classes which represent objects from an XML file. This is basically an implementation of an API wrapper and I am using this as an adapter between the parsed XML from an API and a database. Casting is delegated to the caller of the get method. If the subclasses need to do something when they are created or when they return a variable, they just call super and then manipulate what gets returned afterwards. eg.:
class Event extends MyThing {
public Event(HashMap<String,Object> newFields){
super(newFields);
// Removes anything after an # symbol in returned data
Pattern p = Pattern.compile("\\#.*$");
Matcher m = p.matcher((String)fields.get("id"));
boolean result = m.find();
if (result)
fields.put("id", m.replaceFirst(""));
}
}
public Object get(String key){
Object obj = super(key);
if (key.equals("name")){
return "Mr./Mrs. " + ((String)obj);
}
}
}
The reason I feel like I should do this is so I don't have to write getId, getName, getWhatever methods for every single subclass just because they have different attributes. It would save time and it is pretty self explanatory.
Now this is obviously "unJavalike" and more like a ducktyped language way of doing things, but is there a logical reason why I should absolutely not be doing this?
If you're going to this level of complexity and mucking up your object model just because you don't want to have getters and setters, do it in Groovy instead.
Groovy is a duck typed dynamic language on the JVM that accepts 98% of valid Java code, so you already know most of the language (you don't lose functionality)...there are "more idiomatic" ways of doing things, but you can pick those up with time. It also already has a built in XmlSlurper, which probably does most of what you're trying to do anyway.
As for the "reasons why you shouldn't", you're introducing all types of maintainability concerns.
New classes will always have to derive from the base class.
They will have to implement a constructor that always calls a base constructor
They will have to override get() [which you're basically using to encapsulate your getters and setters anyway, why not just add that method and delegate to those other methods] and write specific logic which is likely to degrade with time.
Why shouldn't you? It'll work, right? Sure. But it's poor engineering in that you're either creating a maintenance nightmare, or reinventing the wheel and likely to do it wrong.
Obviously, it's not type safe.
Future maintainers won't know what the types are supposed to be and will get generally confused as to why you're not using POJOs.
Instead of constant time, space complexity and performance you have the characteristics of a HashMap.
It become very difficult to write non-trivial getters/setters in future.
Most data binding systems are designed to work with POJOs/Beans (JAXB, JPA, Jackson, etc).
I'm sure there are more, but this will do. Try using some proper OXM libraries and you'll be much better off.

Categories