basically what needs to happen is that it needs to check what the type of Champion is, and compare it to challenges to see if it can actually do that challenge, its quite hard to explain...
a wizard can fight "magic" and "mystery"
a warrior can fight "fight" and "mystery"
a dragon can fight "fight" and "mystery(only if the dragon talks)"
what I have come up with is this...
public boolean canFight(String nme, int id)
{
Challenge chal = getChallengeObj(id);
Champion champ = getChampionObj(nme.toLowerCase());
if(champ.getType().equals("wizard") && (chal.getTypeAsString().equals("magic") || chal.getTypeAsString().equals("fight"))) {
return true;
} else if(champ.getType().equals("warrior") && (chal.getTypeAsString().equals("fight") || chal.getTypeAsString().equals("mystery"))) {
return true;
} else if((champ.getType().equals("dragon") || champ.getType().equals("dragon") && champ.isMystery()) && (chal.getTypeAsString().equals("fight") || chal.getTypeAsString().equals("magic"))) {
return true;
} else {
return false;
}
}
I thank anyone who has a go at helping me, I am open to any response, even complaints on how complicated the code is!!
(It is checking everything toLowerCase() btw, just in case this isnt clear in the code, as it is in the methods that are called in different classes.
THANKS!!
EDIT
The problem is is that it keeps returning false, and I am a second year university student, so if you could give examples of what you mean by your answers, that would be greatly appreciated :)
Thanks again
The best way to get different behaviour from different types in Java is using polymorphism - basically, put a virtual method into your Champion type with different implementations in Wizard, Warrior, Dragon etc subtypes
A chain of if-else's based on the type of an object is a bit of an anti-pattern in Java - crying out to be refactored into a single call to a virtual method.
Why not use a 2D array to map FightCompatilibity between Challenge and Champ. Model each Champ and Challenge as enum. Maybe, take a look at Visitor Pattern. It might be useful.
This is exactly something, which should be done by class hiearchy. Like if you know, someone is Wizard, you should already known what he can attack or not, therefore you should move responsibility into that Wizard class instead of testing it externally.
I did an example with 4 classes :
In this enum are listed all attack types
public enum AttackTypes {
Magic, Meele, Ranged;
}
This is abstract class, it only helps you define behaviour that is same for all classes. I supposed that every class has some subset of "attack types" (or something similar). In my example, I just suppose, that each class can fight only against some types of attack. In constructor, I get all the attack I can fight and then I can chack it with this canAttack.
public abstract class Champion {
private List<AttackTypes> attackTo;
public Champion(AttackTypes... attack) {
this.attackTo = new ArrayList<>();
this.attackTo.addAll(Arrays.asList(attack));
}
public boolean canAttack(AttackTypes attackType){
for (AttackTypes attack : attackTo){
if (attack == attackType){
return true;
}
}
return false;
}
}
This is simple Warrior class, in my example, it can fight only Magic and Meele :
public class Warrior extends Champion{
public Warrior(){
super(AttackTypes.Magic, AttackTypes.Meele);
}
}
And similar to Warrior, here is Wizard :
public class Wizard extends Champion{
public Wizard(){
super(AttackTypes.Ranged, AttackTypes.Magic);
}
}
This approach is important, because it is extremely easy to add new class (like Ranger for example). You just add him and thats all, you dont have to anything in your already finished code.
Then you can use it as following :
Champion wizard = new Wizard();
Champion warrior = new Warrior();
AttackTypes attackType = AttackTypes.Ranged;
System.out.println("can wizard attack? : " + wizard.canAttack(attackType));
System.out.println("can warrior attack? : " + warrior.canAttack(attackType));
This having this output :
can wizard attack? : true
can warrior attack? : false
A much more flexible approach would be to use a pair of enums. Something like this would be a good start. I haven't exactly implemented your logic because there is a flaw in it:
enum Champion {
Wizard(EnumSet.of(Challenge.Fight, Challenge.Magic)),
Warrior(EnumSet.of(Challenge.Fight, Challenge.Mystery)),
Dragon(EnumSet.of(Challenge.Fight, Challenge.Magic)) {
#Override
public boolean canFight(Champion enemy, Challenge attack) {
// For demonstration.
return susceptible.contains(attack) && enemy == Champion.Dragon;
}
};
protected final Set<Challenge> susceptible;
Champion(Set<Challenge> susceptible) {
this.susceptible = susceptible;
}
public boolean canFight(Champion enemy, Challenge attack) {
return susceptible.contains(attack);
}
}
enum Challenge {
Magic,
Fight,
Mystery;
}
You flaw is in (champ.getType().equals("dragon") || champ.getType().equals("dragon") && champ.isMystery()) which doesn't make sense.
Related
I have the following method:
private boolean reserveSeat(int selectedRow, int selectedSeat) {
if (show.getRows().get(selectedRow).getSeats().get(selectedSeat).getReservationStatus()) {
return false;
} else {
show.getRows().get(selectedRow).getSeats().get(selectedSeat).reserve();
setRowNumber(selectedRow);
setSeatNumber(selectedSeat);
return true;
}
}
which resides in a Reservation class. This class has a Show Object (show), A show has Rows (another object), Rows have Seats (another object).
My question is could this method be improved? I have read about LoD and worried that my dot signals a bad design though I think it is logical. It is the Seat object that knows if it is reserved or not. However is going from Show to Seat talking to strangers? or is it ok because of the way each object contains the next object?
Apologies if my questing is not clear. What seems to happen with me (probably because I am self taught) is I design stuff that works then I read some OOP design principles and think crap, it works but it is not good design!
Any advice appreciated.
Yes, that chain of calls is way too long.
If show is in charge of the seats,
then it would be better if it's fully in charge.
Right now it's not fully in charge,
because seats can be reserved without the show's knowing.
This fragmentation of responsibilities is strange.
You can put show fully in charge by not exposing Seat to the Reservation,
by hiding the seat status manipulations behind helper methods:
private boolean reserveSeat(int selectedRow, int selectedSeat) {
if (show.isSeatReserved(selectedRow, selectedSeat)) {
return false;
} else {
show.reserveSeat(selectedRow, selectedSeat);
setRowNumber(selectedRow);
setSeatNumber(selectedSeat);
return true;
}
}
Or, if you don't want show to be in charge of the seats,
then it should not be aware of the seats at all,
so then you would access seats not through show,
but another class that's in charge of that.
You're using show as a data object, and putting all the logic for handling that data in the class that contains it. This makes Show a data class and the enclosing class a god class.
The logic for handling data inside of show should really be inside the Show class itself (data is smart).
You could make a method in the Show class for reserving a seat. And equally, you could make a method in the Row class for reserving a seat.
Then one just passes on the message to the next until you get to Seat.
What if you changed the implementation of Show to use a 2D array for instance? That would break the code in your reservation class.
By doing these long chained calls, and not letting classes handle their own data. You are making the user classes dependent on the implementation the used data structures.
If you wanted to change one, you would have to update all the user classes, instead of just the one class that contains the data structure.
So thanks for the suggestions, the feedback really helped with my learning. So what I went on to do was the following, based on the relationsip--> A Reservation (now called Booking) has a Show, A Show has a Row, A Row has a Seat(s).
In the Booking class I now have this: Thanks #janos
private boolean reserveSeat(int selectedRow, int selectedSeat) {
if (show.isSeatReserved(selectedRow, selectedSeat)) {
System.out.println("Sorry, that seat has already been booked");
return false;
} else {
show.reserveSeat(selectedRow, selectedSeat);
setRowNumber(selectedRow);
setSeatNumber(selectedSeat);
System.out.println("This seat has now been booked.");
return true;
}
}
In the Show class I have this:
public boolean isSeatReserved(int selectedRow, int selectedSeat) {
if (getRow(selectedRow).getSeatStatus(selectedSeat)) {
return true;
} else
return false;
}
and in the Row class I have
public boolean getSeatStatus(int selectedSeat) {
return getSeat(selectedSeat).getReservationStatus();
}
I thought it may be useful to other people just starting out (like me) to show this graphically using before and after diagrams taken from the jarchitect tool which shows what a mess my code was in! I used the same logic to tidy up some other classes that "knew too much".
I'm new to Java and I hope Java experts will not vote down my question just because it may seem rather primitive to them. So, this is something I want to achive in semi-pseudo code:
class Big {
? magic_field;
? magic_method (int _idx){
if (_idx == 1){
magic_field = new Object_1();
}
else if (_idx == 2){
magic_field = new Object_2();
}
...
else if (_idx == N){
magic_field = new Object_N();
}
return magic_field;
}
}
I've already tried to ask this question, but in the context of a real world class, real fields and procedures, but did not get an answer to my question. Practically all answers reused the idea of generics and started with something like
class Big <T extends Something>
But I want stress it heavily thousands of times - Object_1, Object_2, ..., Object_N may be drastically different classes that do not relate to each other - they are not subclasses of some parent class, they are not subclasses of each other. They are absolutely different and in fact are black boxes for each other. So, the idea of T extends Something does not work, because there is nothing to extend. Though, I've provided a semi-pseudo example, in an answer I wish to see a real class - and for simplicity let it be generalized on two arbitrary classes. Thanks!
Magic field simple should be an Object if there is no relation between the types (everything is an Object!)
Something like this:
class Big {
private Object magic_field;
public Object magic_method (int _idx){
if (_idx == 1){
magic_field = new Object_1();
}
else if (_idx == 2){
magic_field = new Object_2();
}
...
else if (_idx == N){
magic_field = new Object_N();
}
return magic_field;
}
}
class Object_1 {
//...
}
class Object_2 {
//...
}
class Object_N {
//...
}
Java is a strong, statically typed programming language. What you ask is first of all is not vary natural in the java context if you do not want to use generics. Maybe you can port it to a dynamically typed language like Ruby, Racket, Python vs or you can extend a type system for the Java language.
So you can write it like that as Johan Graham suggested.
Object magicField;
magicField = new ClassA();
magicField = new ClassB();
Then you should store also the type that you have bidden to your magicField variable because you need reflection to extract data from it.
I've got a Java class, here's an example:
public class Car {
private int fuelType;
private Date made;
private String name;
.
.
. // and so on
Now let's say I have two car objects and I want to compare if all their variables are equal.
Right now, I've solved this by overriding method equals(Object o) and I check if all the variables match in both objects.
The problem here is that if I have 20 classes, I'll have to override equals(Object o) in every single one of them.
Is there a way create some sort of universal method that could compare any of the two objects that I pass to it and let me know if they match in every single variable or not?
You have a few options for automating Equals & Hashcode (option #3 BLEW MY MIND!):
Your IDE. I would not recommend it for most objects as they can slowly drift out of date with the actual class definition. They also look ugly and pollute your codebase with boilerplate code.
Apache Commons has a bunch of stuff for making this easier, including a reflective version so no risk of drifting out of date with the class definition. It is better than #1 unless you require a speedy equals/hashcode, but still too much boilerplate for my liking.
Project Lombok and annotation processing. Whack an EqualsAndHashCode annotation on ya class and be done with it. I recommend using Project Lombok. It adds a touch of magic into the build (but not much) and so requires a plugin for your IDE to behave nicely but they are a small price to pay for no boilerplate code. Lombok is an annotation processor that run at compile time so you have no runtime performance hit.
Using a different language that supports it out the box, but also targets the JVM. Groovy uses an annotation and Kotlin supports data classes. Unless your existing code can quickly be converted, I would avoid this.
Google's Auto has an AutoValue. Like Project Lombok this is an annotation processor, however has less magic at the expense of little more boilerplate (thanks to Louis Wasserman)
you can use :
org.apache.commons.lang.builder.CompareToBuilder.reflectionCompare(Object lhs, Object rhs);
it uses reflection to compare the fileds
here is the javadoc : javadoc
I'll take the dissenting opinion to the majority (use apache commons with reflection) here: Yes, this is a bit code you have to write (let your IDE generate really), but you only have to do it once and the number of data classes that need to implement equals/hashcode is generally rather manageable - at least in all of the large projects (250k+ LOC) I worked on.
Sure if you add a new member to the class you will have to remember to update the equals/hashcode functions, but that's generally easy to notice, at the latest during code reviews.
And honestly if you use a simple little helper class that's even in Java7, you can cut down the code that Wana Ant showed immensely. Really all you need is:
#Override
public boolean equals(Object o) {
if (o instanceof Car) { // nb: broken if car is not final - other topic
Car other = (Car) o;
return Objects.equals(fuelType, other.fuelType) &&
Objects.equals(made, other.made) &&
Objects.equals(name, other.name);
}
return false;
}
similar for hashcode:
#Override
public int hashCode() {
return Objects.hash(fuelType, made, name);
}
Not as short as the reflection solution? True, but it's simple, easy to maintain, adapt and read - and performance is orders of magnitude better (which for classes that implement equals and hashcode is often important)
Typically you can generate equals/hashCode methods by your IDE - all big players in this field are capable of that (Eclipse, IntelliJ Idea and Netbeans).
Generally you can create some code that will use reflection but I don't recommend this one as objective approach is clearer and more maintainable. Also reflection won't be as fast as "standard" way. If you really want to go this way, there exist utilities like EqualsBuilder and HashCodeBuilder.
Just for your information, there are JVM-based languages that already support these features, e.g. Kotlin data classes, which can be pretty nicely used in existing Java projects.
I'll just throw in a plug for my favorite solution to this problem: #AutoValue.
This is an open-source project from Google that provides an annotation processor that generates a synthetic class that implements equals and hashCode for you.
Since it's auto-generated code, you don't have to worry about accidentally forgetting a field or messing up the equals or hashCode implementation. But since the code is generated at compile time, there's zero runtime overhead (unlike reflection-based solutions). It's also "API-invisible" -- users of your class can't tell the difference between an #AutoValue type and a type you implemented yourself, and you can change back and forth in the future without breaking callers.
See also this presentation which explains the rationale and does a better job comparing it to other approaches.
Theoretically you could use reflection to create some kind of util, as many people suggest you in comments. Personally I don't recommend you to do it. you will end up with something which is partially working.
Many things in Java rely on equal or hashCode, for example method contains which you can find in anything which implements Collection.
Overriding equal (and hashCode) is recommended solution. By addition, i think any decent IDE will have option to generate them for you. Hence you can do it quicker than by using reflection.
That's the way I would do it:
#Override
public boolean equals(Object obj) {
if (obj instanceof Car) {
return internalEquals((Car) obj);
}
return super.equals(obj);
}
protected boolean internalEquals(Car other) {
if(this==other){
return true;
}
if (other != null) {
//suppose fuelType can be Integer.
if (this.getFuelType() !=null) {
if (other.getFuelType() == null) {
return false;
} else if (!this.getFuelType().equals(other.getFuelType())) {
return false;
}
} else if(other.getFuelType()!=null){
return false;
}
if (this.getName() != null) {
if (other.getName() == null) {
return false;
} else if (!this.getName().equals(other.getName())) {
return false;
}
}
else if(other.getName()!=null){
return false;
}
if (this.getDate() != null) {
if (other.getDate() == null) {
return false;
} else if (!this.getDate().getTime()!=(other.getDate().getTime())) {
return false;
}
}
else if(other.getDate()!=null){
return false;
}
return true;
} else {
return false;
}
}
EDIT
Simplified version
public class Utils{
/**
* Compares the two given objects and returns true,
* if they are equal and false, if they are not.
* #param a one of the two objects to compare
* #param b the other one of the two objects to compare
* #return if the two given lists are equal.
*/
public static boolean areObjectsEqual(Object a, Object b) {
if (a == b){
return true;
}
return (a!=null && a.equals(b));
}
public static boolean areDatesEqual(Date a, Date b){
if(a == b){
return true;
}
if(a==null || b==null){
return false;
}
return a.getTime() == b.getTime();
}
}
#Override
public boolean equals(other obj) {
if(this == other){
return true;
}
if(other == null){
return false;
}
if (other instanceof Car) {
return internalEquals((Car) other);
}
return super.equals(obj);
}
protected boolean internalEquals(Car other) {
//suppose fuelType can be Integer.
if (!Utils.areObjectsEqual(this.getName(), other.getName()){
return false;
}
if (!Utils.areObjectsEqual(this.getName(), other.getName()){
return false;
}
if (!Utils.areDatesEqual(this.getDate(), other.getDate()){
return false;
}
return true;
}
}
Also don't forget about hashcode, they code hand in hand.
We have App A as main app. Now we build from it App B which uses a subset of App A's functionality.
App A stays like it is whereas app B only uses a subset of A
So I want to refactor the function without or with as little dublication as possible and with maximum readability.
So the function looks like this (it is actually longer, this is an excerpt):
class SomeClass {
Data prepareData() {
if (this.bothId==1 || this.appAid=2 /*or only relevant for appA*/) {
if(this.data==null) { /*appA*/
appAdoSmth(); /*appA*/
}
boolean merge=false; /*appA*/
if (this.data==null) { /*appA*/
merge=appAanalyze(data); /*appA*/
}
bothPrepare(merge);
} else if (bothIsRelevant()) {
if(appArelevant()) { /*appA*/
data=appAprepare(); /*appA*/
} else {
data=prepareBoth();
}
bothUpdateSomeValue();
}
}
How would you do it?
Other Answers address the general question of how to refactor code. They offer good advice, but I don't think it is what you are asking.
I think you are asking about possible refactorings of the code in your question.
It is hard to give an answer that is generally applicable, or even specifically applicable. (The sample code isn't your real code, and it is a little difficult to understand what it actually "means").
AndreasD gives one approach: break the big complicated nested if into separate methods.
Another approach is to use the Stragegy design pattern. Separate the code that is specific to each app into strategy classes. For example:
interface Strategy {
Data prepareData();
}
class GeneralStrategy implements Strategy {
Data prepareData() {
// do general preparation
}
}
class App1Strategy extends GeneralStrategy {
Data prepareData() {
// do app1-specific preparation
super.prepareData();
// do more app1-specific preparation
}
}
and so on.
I ideal world develop unit test that validates that existing implementation of your function works.
Then start changing code incrementally and run your test after every change.
It is hard to give your formal recommendation without knowing your code structure. But generally try to find duplicate code fragments, write methods that implement this logic with parameters and replace the duplicate fragments to your new method. Etc, etc.
Good luck.
Readbility can be improved by extracting some logic in separate methods. That is a refactoring method.
Data prepareData() {
if (this.bothId==1 || this.appAid=2 ) {
handleCase1(); // <- you'll find better names for the methods
} else if (bothIsRelevant()) {
handleCase2();
}
}
private void handleCase1() {
if(this.data==null) {
appAdoSmth();
}
boolean merge=false;
if (this.data==null) {
merge=appAanalyze(data);
}
bothPrepare(merge);
}
private handleCase2() {
if(appArelevant()) {
data=appAprepare();
} else {
data=prepareBoth();
}
bothUpdateSomeValue();
}
This doesn't reduce the number of if/else, of course, but it keeps the "main" method simple.
If I were you I would run a coverage report on this class. (e.g. http://ecobertura.johoop.de/ or http://www.eclemma.org/) This way Eclipse can show covered lines green and this helps you to identify the cases. With this aid it's much easier to separate green lines and pull them into methods.
Here is the normal way I would do things in C++:
class object
{
public:
enum
{
STATE_ACTIVE = 0,
STATE_INACTIVE,
OBJ_NUM_STATES,
}
int m_State;
virtual void UpdateState ()
{
switch(this->m_state)
{
case STATE_ACTIVE: /* do stuff*/ break;
case STATE_INACTIVE: /* do stuff*/ break;
}
}
}
class SpecialGameObject : public Object
{
public:
enum
{
STATE_SPECIAL_A = OBJ_NUM_STATES + 1,
STATE_SPECIAL_B,
SPECIAL_NUM_STATES,
}
virtual void UpdateState ()
{
Object::UpdateState();
switch(this->m_State)
{
case STATE_ACTIVE: /* do extra stuff */ break;
case STATE_SPECIAL_A: /* do special stuff*/ break;
case STATE_SPECIAL_B: /* do special stuff*/ break;
}
}
}
I am trying to figure out to get all of this functionality to work in java. Specifically I need working:
1) Ability for derived classes to have state values that automatically line up after the derived state values. That way I can add new state values to the base class without worrying about them overlapping the rage of state values used in any of the derived classes.
2) Ability to use the state values as cases in switch statements.
I looked into using static final ints to implement my state values. But those can't be used as case statements. Then I looked into extending enums, but that isn't allowed.
Does anyone have any suggestions for me?
Thank you
You need to implement the state pattern in Java. This might help you. Wikipedia also has a simple and easy to understand example in Java.
Is this enough to get you going?
final class GameObject {
enum State { ACTIVE, INACTIVE };
State state;
void updateState()
{
switch(state) {
case ACTIVE :
// update state
break;
case INACTIVE:
// update STATE
break;
default:
assert false : "never get here";
}
}
}
Note that in Java, enums are final so you can't extend an enum directly. (Reference this SO question.) If you really need to extend the notion of state into specialized subclasses, things are probably complicated enough that you should consider using polymorphism rather than switch statements (see also here) to get what you want. Alternatively, you could bundle the "super" state with specialized substates in a wrapper super- and sub-classes, perhaps with defined interfaces.
And, if you want to get seriously warped, you could do something like this. It's very cool that Java enums can implement interfaces, but I think this counts as a particularly ugly way of using that feature for your question...
final class GameObject {
ActiveStateful state;
interface ActiveStateful {
State activeState();
}
enum State implements ActiveStateful {
ACTIVE, INACTIVE;
public State activeState() {
return this;
}
};
enum SubState implements ActiveStateful {
SPECIAL_A(State.ACTIVE), SPECIAL_B(State.ACTIVE);
SubState(final State activeState) {
this.activeState = activeState;
}
final State activeState;
public State activeState() {
return activeState;
}
}
}
But those can't be used as case statements.
If I told you this was incorrect, that would solve your problems, yes? This is incorrect: you can switch on static final int constants.
I'd recommend using an enum and its ordinal values for switch statements. That's what enum was born for.
Please consider getting rid of switch altogether. It is a horrible abomination that should have ceased decades ago but didn’t. Read the excellent “Abandoning switch In Three (And A Bit) Steps” article for more information.