The scenario. I'm writting game-related code. In that game a Player(its also a class) has a list of Item. There are other types of items that inherit from Item, for example ContainerItem, DurableItem or WeaponItem.
Obviously it is very conveniant for me to just have List<Item>. But when I get the players items, the only way for me to distinguish between what type of item is by using the instanceof keyword. I'm sure I've read that reliaing on it is bad practice.
Is it ok to use it in this case? Or should I rethink all of my structure?
Let's say I am writing some inventory code:
public void showInventory(List<Item> items) {
for (Item item : items) {
if (item instanceof ContainerItem) {
// container display logic here
}
else if (item instanceof WeaponItem) {
// weapon display logic here
}
// etc etc
}
}
That will compile and work just fine. But it misses out on a key idea of object oriented design: You can define parent classes to do general useful things, and have child classes fill in specific, important details.
Alternate approach to above:
abstract class Item {
// insert methods that act exactly the same for all items here
// now define one that subclasses must fill in themselves
public abstract void show()
}
class ContainerItem extends Item {
#Override public void show() {
// container display logic here instead
}
}
class WeaponItem extends Item {
#Override public void show() {
// weapon display logic here instead
}
}
Now we have one place to look, the show() method, in all our child classes for inventory display logic. How do we access it? Easy!
public void showInventory(List<Item> items) {
for (Item item : items) {
item.show();
}
}
We are keeping all the item-specific logic inside specific Item subclasses. This makes your codebase easier to maintain and extend. It reduces the cognitive strain of the long for-each loop in the first code sample. And it readies show() to be reusable in places you haven't even designed yet.
IMHO using instanceof is a code smell. Simply put - it makes your code procedural, not object oriented. The OO way of doing this is using the visitor pattern.
The visitor pattern also allows you to easily build decorators and chain of responsibility on top of it, thus achieving separation of concerns, which results in shorter, cleaner and easier to read and test code.
Also do you really need to know the exact class ? Cant you take advantage of polymorphism ? After all Axe IS a Weapon just as Sword is.
You should rethink maybe and try to use polymorphism to implement your List<Item> idea.
Here is some references for your problem that can probably help :
Prefer polymorphism over instanceof and downcasting
instanceof versus getClass in equals Methods (Interview with Josh Bloch)
Polymorphism and Interfaces (see section about When to use instanceof)
(References from Is instanceof considered bad practice? If so, under what circumstances is instanceof still preferable? )
You should rethink your structure, instanceof in non-meta code is almost always a sign for an anti-pattern. Try to define the behaviour all Items have in common (like having a picture, a description and something happening when you click on them) in the Item-class/interface, making use of the abstract-keyword if appropiate, and then use polymorphism to implement the specifics.
It's ok if it's easy for you to understand.
Moving branching logics from where they naturally belong all to subclasses is not necessarily a good idea. It may create the wrong dependency; it may cause bloated classes, and it may be hard to navigate and understand.
In the end, it's all about how to physically organize our code with multiple dimensions of concerns in a one dimensional space. It's not a trivial problem, it is subjective, and there is no panacea.
In particular, our industry inherited a lot of rules of thumbs that were made in the last century based on technical and economical constraints of that era. For example, tooling were very limited; programmers were highly expensive; applications evolved slowly.
Some of these rules may no longer apply today.
I don't necessarily think instanceof is bad for coders who know what they are doing and use it to avoid having to write more complicated code to get around it. There is a use for everything, and also a mis-use.
With that said, the description you provide does not require instanceof. There are various ways you can implement this without instanceof, and (the most important thing) the alternate solution must be better than using instanceof. Don't just go with a non-instanceof solution to avoid instanceof because you heard it is bad.
I think that for your scenario an non-instanceof solution has benefits in making the solution more easily extensible.
for (Item i: items) {
if (ItemTypes.WEAPON_ITEM.equals(i.getType)) {
processWeaponType(i);
}
}
or
for (Item i: items) {
if (WeaponItem.class.equals(i.getType)) {
processWeaponType(i);
}
}
Related
The problem I am having is quite specific, and a bit difficult to explain. Let me know if you need more details about anything. I have an abstract class called System. To hold my System objects, I have a SystemManager which contains an list of Systems, and some functions for manipulating it. Inside it contains:
List<System> systems = new ArrayList<System>();
Now, I want to create another abstract class which is a specific type of System called RenderSystem. This will inherit from System but have a few more functions. I also want to create a RenderSystemManager which should do everything SystemManager does, except with a few extra features. Also, instead of having a list of System in the manager, I would like it to have a list of RenderSystem to ensure that the programmers don't put any regular System objects in it. My initial instinct was to inherit SystemManger, and just change the type of the list to RenderSystem:
systems = new ArrayList<RenderSystem>();
Java doesn't allow this as systems is type System not RenderSystem. I would have assumed it would be OK considering RenderSystem inherits from System. One way I can think of to resolve this issue is to copy and paste all the code from SystemManager into RenderSystemManager and just change the line of code to be:
List<RenderSystem> systems = new ArrayList<RenderSystem>();
My other instinct would be to override the addSystem(System system) function to ensure that it only handles RenderSystem, but the programmers might think they are allowed to do it even if it doesn't work.
#Override
public void addSystem(System system)
{
if (system instanceof RenderSystem)
{
super.addSystem(system);
}
}
These doesn't seem very elegant though. Anybody have any suggestions?
Your managers have the same type-safety requirements as the list they wrap. They should thus follow the same strategy, and be generic types:
public class BaseSystemManager<T extends System> {
private List<T> systems = new ArrayList<>();
public void addSystem(T system) {
systems.add(system);
}
// common methods
}
public class SystemManager extends BaseSystemManager<System> {
// methods specific to System handling
}
public RenderSystemManager extends BaseSystemManager<RenderSystem> {
// methods specific to RenderSystem handling
}
I think your second instinct to add protection into the addSystem call is the correct one. That way SystemManager can still operate on the list of Systems. However I would change the implementation of addSystem to instruct developers in the proper usage:
#Override
public void addSystem(System system)
{
if (system instanceof RenderSystem)
{
super.addSystem(system);
}
else
{
throw new IllegalArgumentException("Only RenderSystem objects can be added to a RenderSystemManager");
}
}
Your SystemManager could have a a list of System objects, and the list could be private, and the only way to add an object to that list would be a function that only took a RenderSystem as an argument. You're trying to manhandle generics into a use for which they probably are not appropriate.
But I think you have bigger problems.
I think this happens to many of us when we start trying to design "from the inside out", i.e., you are taking programming constructs and trying to string them together at a level of detail that ignores (or forgets) what the code is trying to do from a higher level. It's like saying "I want a while loop inside a do loop that has a switch statement with try-catch-finally-whatever, but I don't want to nest all these damn braces."
Take a few steps back and think about the external functionality you want to accomplish, and progress in small steps through design and implementation details from there...
In an e-commerce application, below are the high level API
interface Order{
public List<PaymentGroup> getPaymentGroups();
}
interface PaymentGroup{}
class PaymentGroupImpl implements PaymentGroup{}
class CreditCard extends PaymentGroupImpl{}
class GiftCard extends PaymentGroupImpl{}
class OrderManager{ //Manager component used to manipulate Order}
There is a need to add some utility methods like hasGiftCard(), hasCreditCard(), getGiftCards(), getCreditCards()
Two approaches -
1) Add these in Order. However, this would result in coupling between Order and PaymentGroup implementors (like CreditCard, GiftCard) Example -
interface Order {
public List<GiftCard> getGiftCards();
}
2) Move these to OrderManager.
class OrderManager{
public List<GiftCard> getGiftCards(Order order){}
}
I personally prefer 2), am just curious would there be any reason to choose 1) over 2)
I have two answers. One is what I'll call Old Skool OOP and the other I'll call New Skool OOP.
Let's tackle New Skool first. The GoF and Martin Fowler changed the way people look at OOP. Adding methods like hasGiftCard() leads to adding conditional logic/branching into the code. It might look something like this:
if (order.hasGiftCard()) {
//Do gift card stuff
} else {
//Do something else
}
Eventually this kind of code becomes brittle. On a big application, lots of developers will be writing predicate methods. Predicate methods assert something and return true or false. These methods usually start with the word "has", "is" or "contains". For example, isValid(), hasAddress(), or containsFood(). Still more developers write conditional logic that uses those predicate methods.
To avoid all of this conditional logic software engineers changed how they thought about object-orientation. Instead of predicate-methods-and-conditional-logic, they started using things like the strategy pattern, visitor pattern, and dependency injection. An example from your problem domain might look like this:
//Old Skool
if (this.hasCreditCard()) {
orderManager.processCreditCard(this.getCreditCards());
}
Here is another approach to solving the same problem:
//New Skool
for(PaymentItem each : getPaymentItems()){
each.process(this);
}
The New Skool approach turns the problem on its head. Instead of making the Order and OrderManager responsible for the heavy lifting the work is pushed out to the subordinate objects. These kind of patterns are slick because:
they eliminate a lot of "if" statements,
the code is more supple and it is easier to extend the application, and
instead of every developer making changes to Order and OrderManager, the work is spread out among more classes nd code merges are easier.
That's New Skool. Back in the day, I wrote a lot of Old Skool object-oriented code. If you want to go that route, here are my recommendations.
IMHO, you don't need both a PaymentGroup interface and a PaymentGroupImpl class. If all payment classes extend PaymentGroupImpl, then get rid of the interface and make PaymentGroup a class.
Add methods like isCreditCard(), isGiftCertificate() to the PaymentGroup class. Have them all return "false".
In the subclasses of PaymentGroup, override these methods to return true where appropriate. For example, in the CreditCard class, isCreditCard() should return "true".
In the Order class, create methods to filter the payments by type. Create methods like getCreditCards(), getGiftCertificates(), and so on. In traditional Java (no lambdas or helper libraries), these methods might look something like this
List getCreditCards() {
List list = new ArrayList();
for(PaymentGroup each : getPaymentGroups()){
if(each.isCreditCard()) {
list.add(each);
}
return list;
}
-In the Order class, create predicate methods like hasCreditCards(). If performance is not an issue, do this:
boolean hasCreditCards() {
return !getCreditCards().isEmpty();
}
If performance is an issue, do something more clever:
boolean hasCreditCards() {
for(PaymentGroup each : getPaymentGroups()){
if(each.isCreditCard()) {
return true;
}
return false;
}
}
Realize that if you add a new payment group, a code must be added in a lot of places in the Old Skool paradigm.
I am developing a game in which the user can turn on / off certain effects. These effects cause a drain on the users' energy and various parts of the program must be able to check if an affect is active. Currently, I'm using an enum type to store and check the effects:
public static enum Effects { SUPER_FIRE, FIRE_SHIELD }
if (someEffect == Effects.SUPER_FIRE) {
// Breath fire etc..
}
Saying this, I have to store other variables for each effect - such as the level required to use it or the rate at which it drains energy. So, the other method I thought of was to use a class:
public class SuperFire extends Effect {
public static int levelRequired = 10;
public static int drainRate = 5;
public boolean active() {
// Check if it's active
}
public boolean activate() {
}
public boolean deactivate() {
}
}
SuperFireEffect sfe = new SuperFire();
sfe.activate();
if (sfe.active()) {
energyLevel -= sfe.drainRate;
}
sfe.deactivate();
Which implementation (or any other) is the best for this situation?
I hesitate to say "best" in any case, but it would appear that your second example is "better" in the "more flexible" meaning of the word.
Of course, from your very small code snippets, you are not encapsulating the functionality very well, so it would appear you may wish to do some more design work first.
In the end, you want to have the game code think in terms of the Effect base class and what it can do, and not have to know anything about the implementation of things like SuperFireEffect.
I would probably choose the second one as it is more "object-oriented" in my opinion. Plus if you start to add a lot of effects it will be more easily maintainable, and you can benefit from inheritance for super-effects.
The 2nd implementation is better since you mention about the effects which are specified with their own set of features / properties / fields / attributes like "levelRequired, drainRate". So following this approach, you should well define your classes / entities and their features and common characteristics. Object Oriented Programming principles should be conveyed.
I'm doing a bit of playing about to learn a framework I'm contributing to, and an interesting question came up. EDIT: I'm doing some basic filters in the Okapi Framework, as described in this guide, note that the filter must return different event types to be useful, and that resources must be used by reference (as the same resource may be used in other filters later). Here's the code I'm working with:
while (filter.hasNext()) {
Event event = filter.next();
if (event.isTextUnit()) {
TextUnit tu = (TextUnit)event.getResource();
if (tu.isTranslatable()) {
//do something with it
}
}
}
Note the cast of the resource to a TextUnit object on line 4. This works, I know it's a TextUnit because events that are isTextUnit() will always have a TextUnit resource. However, an alternative would be to add an asTextUnit() method to the IResource interface that returns the event as a TextUnit (as well as equivalent methods for each common resource type), so that the line would become:
TextUnit tu = event.getResource().asTextUnit;
Another approach might be providing a static casting method in TextUnit itself, along the lines of:
TextUnit tu = TextUnit.fromResource(event.getResource());
My question is: what are some arguments for doing it one way or the other? Are there performance differences?
The main advantage I can think of with asTextUnit() (or .fromResource) is that more appropriate exceptions could be thrown if someone tries to get a resource as the wrong type (i.e. with a message like "Cannot get this RawDocument type resource as a TextUnit - use asRawDocument()" or "The resource is not a TextUnit").
The main disadvantages I can think of with .asTextUnit() is that each resource type would then have to implement all the methods (most of which will just throw an exception), and if another major resource type is added there would be some refactoring to add the new method to every resource type (although there's no reason the .asSomething() methods would have to be defined for every possible type, the less common resources could just be cast, although this would lead to inconsistency of approach). This wouldn't be a problem with .fromResource() since it's just one method per type, and could be added or not per type depending on preference.
If the aim is to test an object's type and cast it, then I don't see any value in creating / using custom isXyz and asXyz methods. You just end up with a bunch of extra methods that make little difference to code readability.
Re: your point about appropriate exception messages, I would say that it is most likely not worth it. It is reasonable to assume that not having a TextUnit when a TextUnit is expected is symptom of a bug somewhere. IMO, it is not worthwhile trying to provide "user friendly" diagnostics for bugs. The person that the information is aimed at is a Java programmer, and for that person the default message and stacktrace for a regular ClassCastException (and the source code) provides all of the information required. (Translating it into pretty language adds no real value.)
On the flip-side, the performance differences between the two forms are not likely to be significant. But consider this:
if (x instanceof Y) {
((Y) x).someYMethod();
}
versus
if (x.isY()) {
x.asY().someYMethod();
}
boolean isY(X x) { return x instanceof Y; }
Y asY(X x) { return (Y) x; }
The optimizer might be able to do a better job of the first compared with the second.
It might not inline the method calls in the second case, especially if it is changed to use instanceof and throw a custom exception.
It is less likely to figure out that only one type test is really required in the second case. (It might not in the first case either ... but it is more likely to.)
But either way, the performance difference is going to be small.
Summary, the fancy methods are not really worth the effort, though they don't do any real harm.
Now if the isXyz or asXyz methods were testing the state of the object (not just the object's Java type), or if the asXyz was returning a wrapper, then the answers would be different ...
You could also just go
if (event instanceof TextUnit) {
// ...
}
and save yourself the trouble.
To answer your question regarding whether to go asTextUnit() vs. TextUnit.fromResource, the performance difference would depend upon how you actually implement these methods.
In the case of the static converter you would have a to create and return a new object of type TextUnit. However, in the case of the member function you could simply return this casted or you could create an return a new object - depends upon your use case.
Either ways, seems like instanceof is probably the cleanest way here.
What if your filter were extended - or wrapped - to return only text unit events? In fact, what if it returned only the resources of text unit events? Then your loop would be much simpler. I would think the clean way to do this would be a second filter, which simply returned just the text unit events, followed by, let's say, an Extractor, which returned the properly cast resource.
If you have a common base class, you can have a single asXMethod there for every derived class, and needn't refactor all derived classes:
abstract class Base {
A asA () { throw new InstantiationException ("not an A"); }
B asB () { throw new InstantiationException ("not an B"); }
C asC () { throw new InstantiationException ("not an C"); }
// much more ...
}
class A extends Base {
A asA () { /* hard work */ return new A (); }
// no asB, asC requiered
}
class B extends Base {
B asB () { /* hard work */ return new B (); }
// no asA, asC required
}
// and so on.
looks pretty clever. For a new Class N, just add a new Method to Base, and all derived classes get it. Just N needs to implement asN.
But it smells.
Why should a B have a method asA if it will always fail? That's not a good design. Exceptions in the generator are cheap, if they aren't triggered. Only thrown exceptions might be costly.
Yes, there are differences. Creating new immutable elements is better then casting. Pass all serializable data (non transient or computable data) to a Builder and build appropriate class.
I have a java class with a thousand line method of if/else logic like this:
if (userType == "admin") {
if (age > 12) {
if (location == "USA") {
// do stuff
} else if (location == "Mexico") {
// do something slightly different than the US case
}
} else if (age < 12 && age > 4) {
if (location == "USA") {
// do something slightly different than the age > 12 US case
} else if (location == "Mexico") {
// do something slightly different
}
}
} else if (userType == "student") {
if (age > 12) {
if (location == "USA") {
// do stuff
} else if (location == "Mexico") {
// do something slightly different than the US case
}
} else if (age < 12 && age > 4) {
if (location == "USA") {
// do something slightly different than the age > 12 US case
} else if (location == "Mexico") {
// do something slightly different
}
}
How should I refactor this into something more managable?
You should use Strategies, possibly implemented within an enum, e.g.:
enum UserType {
ADMIN() {
public void doStuff() {
// do stuff the Admin way
}
},
STUDENT {
public void doStuff() {
// do stuff the Student way
}
};
public abstract void doStuff();
}
As the code structure within each outermost if branch in your code looks pretty much the same, in the next step of refactoring you might want to factor out that duplication using template methods. Alternatively, you might turn Location (and possibly Age) into a strategy as well.
Update: in Java4, you can implement a typesafe enum by hand, and use plain old subclassing to implement the different strategies.
The first thing I would do with this code is create the types Admin and Student, both of which inherit from the base type User. These classes should have a doStuff() method where you hide the rest of this logic.
As a rule of thumb, any time you catch yourself switching on type, you can use polymorphism instead.
Thousands? Maybe a rules engine is what you need. Drools could be a viable alternative.
Or a Command pattern that encapsulates all the "do something slightly different" logic for each case. Store each Command in a Map with the concatentation of age, location, and other factors as the key. Lookup the Command, execute it, and you're done. Nice and clean.
The Map can be stored as configuration and read in on start up. You can add new logic by adding new classes and reconfiguring.
First - use enums for userType and location - then you can use switch statements (improves readability)
Second - use more methods.
Example:
switch (userType) {
case Admin: handleAdmin(); break;
case Student: handleStudent(); break;
}
and later
private void handleAdmin() {
switch (location) {
case USA: handleAdminInUSA(); break;
case Mexico: handleAdminInMexico(); break;
}
}
Further, identify duplicate code and put it in extra methods.
EDIT
If someone forces you to code Java without enums (like you're forced to use Java 1.4.2), use 'final static's instead of enums or do something like:
if (isAdmin(userType)) {
handleAdmin(location, age);
} else if (isStudent(userType)) {
handleStudent(location, age));
}
//...
private void handleAdmin(String location, int age) {
if (isUSA(location)) {
handleAdminInUSA(age);
} else if (isUSA(location)) {
handleAdminInMexico(age);
}
}
//...
private void handleAdminInUSA(int age) {
if (isOldEnough(age)) {
handleAdminInUSAOldEnough();
} else if (isChild(age)) {
handleChildishAdminInUSA(); // ;-)
} //...
}
The risk of this is not just that it is unsightly, but that it is very error prone. After a while, you could run into a risk of overlaps in your conditions.
If you can really distinguish the condition by user type, you can at the minimum break the body of each condition into a separate function. So that you check based on the type, and call an appropriate function specific to that type. A more OO solution is to represent each user as a class, and then override some calculation method to return a value based on the age. If you can't use classes but can at least use enums, then you will be able to do a nicer switch statement on the enums. Switches on Strings will only come in Java 7.
What worries me is situations of overlaps (e.g., two user types with some shared rules, etc.). If that ends up being the case, you might be better off representing the data as some external file (E.g., a table) which you would read and maintain, and your code will essentially operate as a driver that does the appropriate lookup in this data set. This is a common approach for complex business rules, since nobody wants to go and maintain tons of code.
I would probably first check whether you can parametrize the code doStuff and doSimilarStuff.
You may use Chain of Responsibility pattern.
Refactor if-else statements into classes with an interface IUserController for instance.
Initialize your chain within a list or a tree or any suitable data structure, and execute desired functionality in this chain. You may use Builder pattern to create mentioned data structure. It resembles to strategy pattern but in chain of responsibility pattern, an instance in the chain can call linked instance(s).
Moreover, you can model location specific functionality by using strategy pattern. Hope it helps.
If the code in the blocks fits within a few standard patterns, I would create a table with columns (type, location, minAge, maxAge, action), where 'action' is an enum indicating which of several types of processing to do. Ideally, this table would be read from a data file or kept in SQL.
Then, you can just do a table lookup in the Java code to determine the action to take for a user.
You could make userType an enum, and give it a method that performs all of your "do something slightly different" actions.
without more information there is no good answer
but fair guess would be this: use OO
first define a User, define Admin, Student and all other types of users and then let polymorphism take care of the rest
Based just on the variable names, I'm guessing that you should subclass User (or whatever it is that has a userType variable) into AdminUser and StudentUser (and possibly others) and use polymorphism.
Take a look at the Visitor pattern. It makes use of polymorphism but is a little more flexible in that it is easier to add new cases later.
The downside is you'd need some way to convert the state info into different instances. The benefit is a cleaner way to add behavior without having to modify your inheritance hierarchy.
You really need to break these cases into object methods. I'm assuming these strings and numbers are being pulled out of a database. Instead of using them in their raw form in giant nested conditional logic, you need to use these pieces of data to construct objects that model the desired interactions. Consider a UserRole class with a StudentRole and AdminRole subclasses, a Region class with USA and Mexico subclasses, and an AgeGroup class with appropriate partitioned subclasses.
Once you have this object oriented structure in place, you'll be able to make use of well understood object oriented design patterns to re-factor this logic.
Use OOP Concepts:
This is dependent of the rest of the design, but maybe you should have a user interface, Student,Admin interfaces the extends it and UsaStudent,MexicoStudent,UsaAdmin,MexicoAdmin implementation that do some stuff. Hold a User instance and just call its doStuff method.