a method validating objects from different roots repeats most of checks - java

please is there a way how to make the code more concise -
to avoid repeating similar/same actions -
I have a method doing object validations, but most parameters
are similar/same, like using some sort of lambda expression for that,
but objects are not from the same tree.
My use-case is like this:
validate.( car );
and somewhere else I do:
validate.( person );
Right now I am doing the validation like this:
public boolean validate( Object obj ) {
if ( obj instanceof Car ) {
Car car = (Car) obj;
if ( car.getAge() <= 0 ) return false;
// many other checks which are repeated below
} else if ( obj instanceof Person ) {
Person person = (Person) obj;
if ( person.getAge() <= 0 ) return false;
// many other check which are repeating those above
}
// here I would like to do checks for both objects, but objects are from different roots
return true;
}

You can use method overloading :
public boolean validate(Car car) {
if ( car.getAge() <= 0 ) return false;
return validate((Master)car);
}
public boolean validate(Person p) {
if ( p.getAge() <= 0 ) return false;
return validate((Master)p);
}
public boolean validate(Master m) {
// common validations
return true;
}
Master is the common parent of Person and Car (I assume there is a common parent interface/class).

"Do not"s:
First of all, I would strictly suggest you to try your best to avoid designing your method as you are doing it now;
Person and Car have nothing in common from the logical, modelling, or conceptual perspective. Nor they do share any similar characteristics in the real life;
Do not accept Object as an argument in your method. You will have hard times of managing your bugs and/or maintaining unpredictable behaviour.
"Do"s:
Define your method by following Single Responsibility Principle;
Consider from your model object perspective - what your method should be as a behaviour? what ONE problem it should solve?
Try to separate concerns in their respective classes/files/block-units and try not to overlap them.
If you want to your method to behave based on what is the actual instance of the argument, best way is to use instanceof checks.
What you can do instead, however, is to design some proper inheritance and accept a supertype, as a method argument. Then polymorphism would kick in and you will only have one logic in your method.

Related

How to optimize code below by getting rid of redundant?

My code below is to calculate ProductFunction based on some values of Object Product. Method getProductFunctions in InternalProductMapper and ExternalProductMapper call functions in ProductFunctionCalculator to calcuate the value of ProductFunction. According to me its not possible to have a single function in ProductFunctionCalculator, because two different mappers call it. How can I optimize the code below? Also, If I have two functions, i am not sure what to name the other as both calculate function for two different mappers.
public class InternalProductMapper{
public EnumSet<ProductFunction> getProductFunctions(Product p){
return productFunctionCalculator.get(p);
}
}
public class ExternalProductMapper{
public EnumSet<ProductFunction> getProductFunctions(Product p){
return p!=null ? productFunctionCalculator.calculate(p):
return EnumSet.of(Function.BUSINESS,Function.MARKET);
}
}
public class ProductFunctionCalculator{
public EnumSet<ProductFunction> calculate(Product p){
if(p.brand() == "ABC" && p.id.equals("1") && p.value > 100){
return EnumSet.of(Function.BUSINESS, Function.LOCAL);
}
}
public EnumSet<ProductFunction> get(Product p){
if(p != null && p.location.equals("NY")){
return EnumSet.of(Function.BUSINESS);
}
return EnumSet.of(Function.BUSINESS, Function.MARKET);
}
}
"Also, If I have two functions, i am not sure what to name the other as both calculate function for two different mappers."
You can name one calculateInternal and the other calculateExternal or similar, unless I misunderstand what you mean to say.
You can also add an Identifier on your Product object, to ascertain if it is internal or external(Could be a new field, boolean/enum or otherwise). You would need to set the value of this field on initialization of the Product object, when you most probably know what kind of Product it is. This could allow for a new single method of calculating, because now your method would know how to handle the different scenarios(As you have this new 'type' field), possibly via an if-else statement such as:
//This should not be allowed if you can help it and you should try and get
//rid of the scenario this comes in as null - just check it before calling this method
if(product != null) {
if(product.isInternal()) {
//Internal product logic
} else {
//External product logic
}
}

Java 8 avoiding lots of if/else statements

I have something that looks like this:
public boolean isValidObject(SomeObject obj){
if(obj.getField() == null){
LOG.error("error code 1");
return false;
}
if(obj.getField().getSize() > 500){
LOG.error("error code 2");
return false;
}
......
if(someCondition()){
log something
return false;
}
return true;
}
What is the cleanest way of writing this in java 8 with lambdas?
Use polymorphism for this. Create a class for every logical validator and chain them in the list. Here is nice answer with something you need:
https://stackoverflow.com/a/23501390/1119473
public interface Validator<SomeObject>{
public Result validate(SomeObject object);
}
implementation:
public class SomeFieldSizeValidator implements Validator<SomeObject> {
#Override
public Result validate(SomeObject obj) {
// or you can return boolean true/false here if it's enough
return obj.getField().getSize() > 500 ? Result.OK : Result.FAILED;
}
}
Calling validation chain:
List<Validator> validators = ... create ArrayList of needed Validators
for (Validator v : validators) {
if (!v.validate(object)) {
... throw exception, you know validator and object here
}
I might return the error but this would still use a few if's
public String isValidObject(SomeObject obj){
if (obj.getField() == null) return "error code 1";
if (obj.getField().getSize() > 500) return "error code 2";
......
if (someCondition()) return "something";
return OK;
}
This way you could unit test this method to see if it return the error you expect for different invalid objects.
I want to get rid of 50 if/else statements.
If you have 50 conditions and they all value different results you will need to do 50 checks. You could change the structure like this.
static final Map<Predicate<SomeObject>, String> checks = new LinkedHashMap<>();
static {
checks.put((Predicate<SomeObject>) o -> o.getField() == null, "error code 1");
checks.put((Predicate<SomeObject>) o -> o.getField().getSize() > 500, "error code 2");
}
public String isValidObject(SomeObject obj) {
for (Predicate<SomeObject> test : checks.keySet())
if (test.test(object))
return checks.get(test);
return OK;
}
However, personally this is not clearer and would be harder to debug e.g. breakpoint.
Use java.util.function.Predicate interface:
Predicate<SomeObject> p1 = (SomeObject so ) -> so.getField()!=null;
Predicate<SomeObject> p2 = (SomeObject so ) -> so.getField().getSize() > 500;
...
SomeObject someObject = new SomeObject();
Predicate<SomeObject> fullPredicate = p1.and(p2).and( ...
boolean result = fullPredicate.test(someObject);
Except this will give you 50 Predicate one-line definitions, they'll just be a bit more compact.
I recommend a solution that uses a different approach: consider using Validator objects. Meaning: instead of putting all your checks into the same method, you put each check in its own class!
You define some Validator interface that provides a validate method. When validation fails, that method is supposed to throw some ValidationException (and that exception could contain an error code + message).
And then you create many small classes, each one implementing that interface.
Final step: you create a list in which you put one object of each impl class. And now your code boils down to iterating that list, and applying each impl after the other.
This decouples your validation steps, and adding new/other checks becomes super easy.
If you specifically wish to use lambdas, they mesh nicely with an enum:
public enum SomeValidators {
E1 (1, o -> o.getField() == null),
E2 (2, o -> o.getField().getSize() > 500)
;
final int code;
final Predicate<SomeObject> predicate;
SomeValidators(int code, int predicate) {
this.code = code;
this.predicate = predicate;
}
}
You can then use it to replicate your if-else if flow as follows:
boolean isValidObject(SomeObject o) {
Optional<SomeValidators> firstError =
Arrays.stream(SomeValidators.values())
.filter(v -> v.predicate.apply(o))
.findFirst();
firstError.ifPresent(e -> LOG.error("error code " + e.code));
return firstError.isPresent();
}
I'm not sure how lambdas can be useful here.
If you are using lot of 'if else' to handle lot of business rules then one option is to try some rule engines. One easy and best option is EasyRules
Easy rules are handy and easy to implement. This will make your business logic code look very clean.

Hibernate proxy as a key in HashMap

Today I spent some time debugging an issue with hibernate, simplified example would look like:
Map<Cat, Owner> catsMap = new HashMap();
List<Owner> owners = ownerRepo.getOwners();
for (Owner owner : owners) {
// cat is Lazy, according to its nature :)
catsMap.put(owner.getCat(), owner);
}
Cat cat = catRepo.findOne("meow");
Owner meowOwner = catsMap.get(cat);
at this moment meowOwner is null because it is not found in catsMap keyset. It took sometime to figure out why because in debug window I see that the Cat with name 'meow' exists in keyset of catsMap, moreover, if I write an expression
catsMap.keySet().iterator().next().equals(cat)
it returns true, hashcodes are the same, same values, though
catsMap.get(cat)
still returns null in the same expressions window.
At last I called
catsMap.keySet().iterator().next().getClass()
and finally found out that it is long.path.to.package.Cat_$$_jvstaea_41, so it is a proxy and equals fails on the step when it checks class equality.
The solution is, of course, obvious, but the question is why do I have
catsMap.keySet().iterator().next().equals(cat)
returning true? I tried also reversed case
cat.equals(catsMap.keySet().iterator().next())
and this one returns false, which is breaking the equals() convention of transitivity.
PS: in all the examples I assume that currently there is only one cat and one owner in DB
Cat cat = catRepo.findOne("meow") should return the same instance, unless your Map is outside of the initial transaction. If you want to store an Entity outside of a transaction, make sure to unproxy it before storing it.
public T unproxy(T proxied)
{
T entity = proxied;
if (entity instanceof HibernateProxy) {
Hibernate.initialize(entity);
entity = (T) ((HibernateProxy) entity)
.getHibernateLazyInitializer()
.getImplementation();
}
return entity;
}
You have to make sure you use the right syntax for your equals and hashCode overrides. This is an example of implementation:
#Override
public boolean equals(Object obj) {
if (obj == this)
return true;
if (!(obj instanceof MyEntityClass))
return false;
MyEntityClass other = (MyEntityClass) obj;
return Objects.equals(getId(), other.getId());
}
#Override
public int hashCode() {
return Objects.hash(getId());
}
Note: Do not use the fields directly this.id, prefer the getter to allow for Hibernate's proxy to resolve the entity when necessary. Also, prefer instanceof to getClass() != obj.getClass(), the first will handle implementations and extends correctly, not the second.

A cleaner if statement with multiple comparisons [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
The following statement just looks very messy when you have a lot of terms:
if(a.equals("x") || a.equals("y") || a.equals("z") || Any number of terms...... )
//Do something
Is there a cleaner way of performing the same action, I would like my code to be as readable as possible.
NOTE: x, y and z are just placeholders for any string of any length. There could be 20 string terms here of variable length in if condition each being OR'd together
What do you think looks "unclean" about it?
If you have a bunch of complicated boolean logic, you might separate the different parts of it into individual boolean variables and refer to them in the if statement.
Or you could create a function that takes your 'a' variable and returns a boolean. You'd just be hiding your logic in the method, but it would clean up your if statement.
Set<String> stuff = new HashSet<String>();
stuff.add("x");
stuff.add("y");
stuff.add("z");
if(stuff.contains(a)) {
//stuff
}
If this is a tight loop you can use a static Set.
static Set<String> stuff;
static {
stuff = new HashSet<String>();
stuff.add("x");
stuff.add("y");
stuff.add("z");
}
//Somewhere else in the cosmos
if(stuff.contains(a)) {
//stuff
}
And if you want to be extra sure nothing is getting modified while you're not looking.
Set<String> test = Collections.unmodifiableSet(new HashSet<String>() {
{
add("x");
add("y");
add("z");
}
});
If you just want to get some logic in there for a handful of hard coded conditions then one of the switch or if statement with newlines solutions might be better. But if you have a lot of conditions then it might be good to separate your configuration from logic.
Alternatively, if you are using Java 7+ you can use strings in switch/case. For example (I extracted this from an Oracle doc and modified)
switch (str) {
case "x":
case "y":
case "z":
//do action
break;
default:
throw new IllegalArgumentException("argument not matched "+str);
}
Here is the link
Use a regular expression
If (a.matches("[xyz]")){
// matches either "x", "y", or "z"
or, for longer strings,
If (a.matches("one|two|three")){
// matches either "one", "two" or "three"
But this is computationally expensive, but probably not much worse than instantiating a set etc. But it's the clearest way I can think of.
But in the end, the nicest way is probably to leave things as they are, with an adjustment to the formatting:
if (a.equals("x") ||
a.equals("y") ||
a.equals("z")
){
There is then absolutely no ambiguity in what the code is doing and so your code will be easier to maintain. If performance matters, you can even put the most likely occurrences towards the top of the list.
Reaching for semantics
On a semantic level, what you are checking for is set membership. However, you implement it on a very low level, basically inlining all the code needed to achieve the check. Apart from forcing the reader to infer the intent behind that massive condition, a prominent issue with such an approach is the large number of degrees of freedom in a general Boolean expression: to be sure the whole thing amounts to just checking set membership, one must carefully inspect each clause, minding any parentheses, misspellings of the repeated variable name, and more.
Each loose degree of freedom means exposure to not just one more bug, but to one more class of bugs.
An approach which uses an explicit set would have these advantages:
clear and explicit semantics;
tight constraint on the degrees of freedom to look after;
O(1) time complexity vs. O(n) complexity of your code.
This is the code needed to implement a set-based idiom:
static final Set<String> matches =
unmodifiableSet(new HashSet<>(asList("a","b","c")));
...
if (matches.contains(a)) // do something;
*I'm implying import static java.util.Arrays.asList and import static java.util.Collections.unmodifiableSet
Readability Is Mostly Formatting
Not readable...
if(a.equals("x") || a.equals("y") || a.equals("z") || Any number of terms...... )
//Do something
Now easy to real...
if(a.equals("x") ||
a.equals("y") ||
a.equals("z") ||
Any number of terms...... )
//Do something
Readability is very subjective to the person reading the source code.
If I came across code that implements collections, loops or one of the many other complicated answers here. I'd shake my head in disbelieve.
Separate The Logic From The Problem
You are mixing two different things. There is the problem of making the business logic easy to read, and the problem of implementing the business logic.
if(validState(a))
// Do something
How you implement validState doesn't matter. What's important is that code with the if statement is readable as business logic. It should not be a long chain of Boolean operations that hide the intent of what is happening.
Here is an example of readable business logic.
if(!isCreditCard(a)) {
return false;
}
if(isExpired(a)) {
return false;
}
return paymentAuthorized(a);
At some level there has to be code that processes basic logic, strings, arrays, etc.. etc.. but it shouldn't be at this level.
If you find you often have to check if a string is equal to a bunch of other strings. Put that code into a string utility class. Separate it from your work and keep your code readable. By ensuring it shows what you're really trying to do.
You can use Arrays.asList().This is the simplest approach and less verbosity.
Arrays.asList("x","y","z"...).contains(a)
For performance reason if your collection is too big you could put data in a HashSet cause searching there is in constant time.
Example make your own util method
public final class Utils{
private Utils(){}//don't let instantiate
public static <T> boolean contains(T a,T ... x){
return new HashSet<>(Arrays.asList(x)).contains(a);
}
}
Then in your client code:
if(Utils.contains(a,"x","y","z","n")){
//execute some code
}
With a little bit of help, you can get the syntactic sugar of a nicer if-statement with just a tiny bit of overhead. To elaborate on Tim's recommendation and Jesko's recommendation a tad further...
public abstract class Criteria {
public boolean matchesAny( Object... objects ) {
for( int i = 0, count = objects.length; i < count; i++ ) {
Object object = objects[i];
if( matches( object ) ) {
return true;
}
}
return false;
}
public boolean matchesAll( Object... objects ) {
for( int i = 0, count = objects.length; i < count; i++ ) {
Object object = objects[i];
if( !matches( object ) ) {
return false;
}
}
return true;
}
public abstract boolean matches( Object object );
}
public class Identity extends Criteria {
public static Identity of( Object self ) {
return new Identity( self );
}
private final Object self;
public Identity( Object self ) {
this.self = self;
}
#Override
public boolean matches( Object object ) {
return self != null ? self.equals( object ) : object == null;
}
}
Your if-statement would then look like this:
if( Identity.of( a ).matchesAny( "x", "y", "z" ) ) {
...
}
This is sort of a middle ground between having a generic syntax for this sort of conditional matching and having the expression describe a specific intent. Following this pattern also lets you perform the same sort of matching using criteria other than equality, much like how Comparators are designed.
Even with the improved syntax, this conditional expression is still just a little bit too complex. Further refactoring might lead to externalizing the terms "x", "y", "z" and moving the expression into a method whose name clearly defines its intent:
private static final String [] IMPORTANT_TERMS = {
"x",
"y",
"z"
};
public boolean isImportant( String term ) {
return Identity.of( term ).matchesAny( IMPORTANT_TERMS );
}
...and your original if-statement would finally be reduced to...
if( isImportant( a ) ) {
...
}
That's much better, and now the method containing your conditional expression can more readily focus on Doing One Thing.
Independent of what you are trying to achieve, this
if(a.equals("x") || a.equals("y") || a.equals("z") || Any number of terms...... )
//Do something
is always messy and unclean. In the first place it is just too long to make sense of it quickly.
The simplest solution for me would be to express your intend instead of being explicit.
Try to do this instead:
public class SomeClass{
public void SomeMethod(){
if ( matchesSignificantChar(a) ){
//doSomething
}
}
private bool matchesSignificantChar(String s){
return (s.equals("x") || s.equals("y") || s.equals("z") || Any number of terms...... )
}
}
This simplifies the scope of your conditional statement and makes it easier to understand while moving the complexity to a much smaller and named scope, that is headed by your intend.
However, this is still not very extensible. If you try to make it cleaner, you can extract the boolean method into another class and pass it as a delegate to SomeClass'es Constructor or even to SomeMethod. Also you can look into the Strategy Pattern for even more exensiblity.
Keep in mind that as a programmer you will spend much more time reading code (not only yours) than writing it, so creating better understandable code will pay off in the long run.
I use following pattern
boolean cond = false; // Name this variable reasonably
cond = cond || a.equals("x");
cond = cond || a.equals("y");
cond = cond || a.equals("z");
// Any number of terms......
if (cond) {
// ...
}
Note: no objects created on the heap. Also you can use any conditions, not only "equals".
In ruby you can use operator ||= for this purpose like cond ||= a.equals("x").
The Set answer is good. When not comparing for membership of a collection you can also separate out some or all of the conditional statement into methods. For example
if (inBounds(x) && shouldProcess(x) ) {
}
If a is guaranteed to be of length 1, you could do:
if ("xyz".indexOf(a) != -1)
One really nice way to do something like this is to use ASCII values, assuming your actual case here is where a is a char or a single character string. Convert a to its ASCII integer equivalent, then use something like this:
If you want to check that a is either "t", "u", "v", ... , "z", then do.....
If (val >= 116 && val <= 122) {//code here}
I prefer to use regexp like few guys wrote upper.
But also you can use next code
private boolean isOneMoreEquals(Object arg, Object... conditions) {
if (conditions == null || arg == null) {
return false;
}
for (int i = 0, d = conditions.length; i < d; i++) {
if (arg.equals(conditions[i])) {
return true;
}
}
return false;
}
so your code will be next:
if (isOneMoreEquals(a, "x", "y", "z") {
//do something
}
Assuming that your "x", "y", and "z" can be of arbitrary length, you can use
if (0 <= java.util.Arrays.binarySearch(new String[] { "x", "y", "z" }, a)) {
// Do something
}
Just make sure that you list your items in lexicographic order, as required by binarySearch(). That should be compatible all the way back to Java 1.2, and it should be more efficient than the solutions that use Java Collections.
Of course, if your "x", "y", and "z" are all single characters, and a is also a character, you can use if (0 <= "xyz".indexOf(a)) { ... } or
switch (a) {
case 'x': case 'y': case 'z':
// Do something
}
If x,y,z... is Consecutiveļ¼Œ you can use if(a >= 'x' && a <= '...'), if not, you can use ArrayList or just Arrays.
I think that cleanest and fastest way is to put values in array.
String[] values={"value1","value2","value3"};
for (string value : values) {
if (a.equals(value){
//Some code
}
}

get object property by finding its class

I have game objects in an array collection, but they can be different classes. I can find the object by its coordinates:
Object obb = grid.getCellContent(insertObjectX, insertObjectY);
What I need to do is to find if obb.canBeSubmerged == true and then simply move it to another array.
The problem is that I canot get a property of that object "canBeSubmerged" because compilier does not know which class I used.
I wonder if there is a quicker way to do it then to go through "obb.getClass() == myClass.class" statements for each of the possible object classes.
.
.
EDIT: based on stuckless suggestion here is a working solution:
try {
java.lang.reflect.Field f1 = obb.getClass().getField("canBeSubmerged");
java.lang.reflect.Field f2 = obb.getClass().getField("subObject");
if (f1 != null) {
canBeSubmerged = f1.getBoolean(obb);
f2.setBoolean(obb, canBeSubmerged);
}
}catch (Exception e) { }
//enter it into the submerged grid level and remove from the top grid level
if (canBeSubmerged){
grid.removeObject(insertObjectX, insertObjectY);
grid.putSubObjectInCell(insertObjectX, insertObjectY, obb);
}
If your obb object that contains the canBeSubmerged property is always of a particular class type, such as MyOBB.class, then you can do this...
if (obb instanceof MyOBB.class) {
if (((MyOBB)obb).canBeSubmerged) {
// do your work
}
}
========= OR ============
Using Reflection (which will be slower)
try {
Field f = obb.getClass().getField("canBeSubmerged");
if (f!=null && f.getBoolean(obb)) {
// do your work
}
} catch (Exception e) {
}
Your objects should probably all extend a common superclass or implement a common interface which defines a method
public boolean canBeSubmerged();
You should not use public fields. And also note that
if (obb.canBeSubmerged() == true)
can be written as
if (obb.canBeSubmerged())
which is more logical and readable.
If you are only interested in one attribute of the object your could extract that to an interface
public interface Submergable {
boolean isSubmerged();
}
And let all objects that may submerge implement it.
Then you can do Object instanceof Submergable

Categories