Best Way to collect complex logging objects during task execution - java

I would like to discuss different ways to collect data that occurs during execution of (a lot) java code, that is not needed to proceed but shall be stored. Additional difficulty in my situation, storing the side Objects needs another object that would otherwise be unneccessary in all the sub methods.
Basically I have one class (TaskExecutor) delegating a coplex task to another component (Delegate). One Object (ImportantObject c) is only necessary to save the side objects (List<Hint>). These hints are not necessary to proceed task execution and are only for logging complex data to my database. But they are linked to this ImportantObject c.
#Component
public class TaskExecutor {
#Autowired
private Delegate delegate;
public void execute() {
Object a = new Object();
Object b = new Object();
ImportantObject c = new ImportantObject(); // only needed to save hints
Object result = delegate.performTask(a, b);
}
}
public class Delegate {
public Object performTask(Object a, Object b) {
method1(a);
Object result2 = method2(a);
Object result3 = method3(a, b, result2);
return result3;
}
private void method1(Object a) {
new Hint();
}
private Object method2(Object a) {
new Hint();
return new Object();
}
private Object method3(Object a, Object b, Object result2) {
new Hint();
return new Object();
}
}
public class DbService {
public void saveHints(List<Hint> hints, ImportantObject c) {
// How to call this?
}
}
What would be a nice codestyle solution for this problem?
Idea 1: Pass object everywhere
Trivial would be passing Object c into the TaskExecution and all its submethods, so I can save a Hint right when it occurs. Would work but I feel like its bad style.
private Object method3(Object a, Object b, Object result2, ImportantObject c) {
dbService.saveHint(new Hint(), c);
return new Object();
}
Idea 2: Pass List everywhere
I could also pass a list everywhere to collect the Hints. So I would have to only have to bring this list and ImportantObject c together. Also feels like bad coding style.
public class TaskExecution {
public Object performTask(Object a, Object b) {
List<Hint> hints = new ArrayList<>();
method1(a, hints);
Object result2 = method2(a, hints);
Object result3 = method3(a, b, result2, hints);
return result3;
}
Idea 3: Use some cache
I thought about putting the Hints to a cache and read them in the TaskExecutor. However if I don't cache them linked to the instance of ImportantObject c they loose their meaning. I could not determine if an object from cache is linked to my current instance of ImportantObject.
Idea 4: field variable (if no Spring)
If I wouldn't use spring and would always create a new instance of Delegate this would be a solution
public class Delegate {
private List<Hint> hints = new ArrayList<>();
// ...
}
But, well... Spring is there for a reason :-)

Related

In my constructor, is it bad practice to set class variables by calling getters on an object I pass into a constructor?

So imagine I have a simple class with three variables which are ultimately derived from another object. I could insert that other object in the constructor like:
public class A {
private int x;
private int y;
private List<> list;
public A(B b) {
this.x = b.getX();
this.y = b.getY();
this.list = b.getList();
}
}
public class B {
private int x;
private int y;
private int z;
private String string;
private Set<> set;
private List<> list;
//constructor, setters and getters
}
A colleague has suggested I should instead do the following:
public class A {
private B b;
public A(B b) {
this.b=b
}
}
Now in the application using their option will require a lot of refactoring from
a.getX() to a.getB().getX() or a.getList() to a.getB().getList() for example.
What I'm struggling to find is what is there some best practice defined in this scenario and why.
My argument is I don't want objects that use A to be coupled to any class structure imposed by B. I think my colleague is concerned that my constructor should not be accepting B as an argument only to call getters on it's variables within the constructor of A.
An alternative would be to use a factory or something to create A from B but that isn't really feasible with my use case. (In my specific use case A is being constructed in a HQL query and B is an Entity class)
EDIT:
I typed this question out on my phone but realise I missed some details so will add them here.
A consists of a subset of properties from B. A also consists of a subset of properties of another class C. The properties of C are currently individually assigned in the constructor in what you would consider a normal manner (because there are only a few). Because A takes a lot of properties from B I am inserting it in the manner illustrated above.
B and C are Entity classes that represent a row from two separate (but related) tables.
A is a class which is we use to do some business logic with somewhere else.
Maybe this is what you are looking for. A is a more general type and B is a more specialize type of A. For example, a Person class and a Student class.
public class A {
private int x;
private int y;
private List<> list;
public A(int x, int y, List<> list) {
this.x = x;
this.y = y;
this.list = b.getList();
}
}
public class B extends A {
private int z;
private String string;
private Set<> set;
public B(int x, int y, List<> list, String string, Set<> set){
super(x,y,list);
this.string = string;
this.set = set;
}
}
With all the information that you have given, your colleague's suggestion of having B object as a class field of A is a bad design. As well as passing B on the A constructor.
The main problem here is on the A class constructor, not it's field.
Passing B object directly to A constructor is a bad design/practice even if A takes a lot of properties from B. If someone were to construct an A object that takes B as an argument, most of the time they would assume that A uses B or that they have a strong relationship. If your concern here is avoiding a lengthy constructor, then you're better off using A setters to take the B properties as shown below:
A aClass = new A();
aclass.setX(bClass.getX());
aclass.setY(bClass.getY());
Another way is creating a method in class A that takes required properties from B by taking B as an argument like:
public class A {
\\fields
public void setRequiredPropertiesFromBClass(B bClass) {
this.x = bClass.getX();
\\\other getters
}
}
That way the intent of your code is clear, which is A needs certain properties from B not B itself. The example above can still be improved. I couldn't think of much better method name since I don't really know the complete implementations of these classes. Lastly, you mentioned that B and C are related so you can turn the method into a generic one so it can take B and C.
If all of these suggestions are still not helpful. Just search for Transfer Object Pattern on the internet.
So I resolved this by creating a static mapper like this;
public class Mapper {
public static A mapToA(B b) {
return A.builder()
.x(b.getX())
.y(b.getY())
.list(b.getList())
.build();
}
}
Obviously the mapper holds the relationship between A and B (and in my case also C).
As mentioned above A is a DTO and B and C are database entities. The existing application was actually quite poorly written with the Repository interfaces directly returning the DTO A as part of a HQL query. I changed these to directly return B and C and then mapped these to A in the service classes.

Java - store objects in a hierarchy that follows their class inheritance

I need to store lots of objects that belong to different classes:
ClassA {...}
ClassA1 extends ClassA {...}
ClassA2 extends ClassA {...}
ClassA2a extends ClassA2 {...}
ClassB {...}
Now I need to find a way to store all these objects in a way that allows me to efficiently get all objects that belong to a particular class and its inherited child classes. For example, this imaginary code
getObjects(ClassA2)
would return a list of all stored objects that belong to ClassA2 or ClassA2a.
I believe a tree collection of some sort would be suitable, but I can't think of any way to implement it. Any ideas?
(Background: I am creating a simple java game, in which there's number of sprites that I need to manage, while some of those sprites share similar properties. When I check for events like collisions, I need to get all objects that extend EnemySprite and compare their coordinates with the player's sprite.)
There are several ways how to approach this. One would be, e.g., to generate strings like ParentClass1:ChildClass2:ChildClass1: for every object and use them as a key to a TreeMap or Trie which you would then traverse.
Here is a simpler solution, though. The following class contains a map from class to all objects implementing it. The only trick is adding an object to all buckets where it belongs:
public class HierarchyMap {
private final Map<Class<?>, List<Object>> map = new HashMap<>();
public void add(Object o) {
Class<?> clazz = o.getClass();
while (clazz != Object.class) {
List<Object> list = map.computeIfAbsent(clazz, c -> new ArrayList<>());
list.add(o);
clazz = clazz.getSuperclass();
}
}
public List<Object> getByClass(Class<?> clazz) {
return map.get(clazz);
}
}
Usage:
public class A { public String toString() { return "A"; } }
public class B extends A{ public String toString() { return "B"; } }
public class C extends B { public String toString() { return "C"; } }
// ...
HierarchyMap hierarchyMap = new HierarchyMap();
hierarchyMap.add(new A());
hierarchyMap.add(new B());
hierarchyMap.add(new C());
System.out.println(hierarchyMap.getByClass(B.class));
// prints [B, C]
Mifeet seems to have literally answered your question, but I suspect you shouldn't be trying to do what you're proposing to do. Why not just have a master list of all objects that might collide, then filter it as needed using instanceof?
This is conceptually a lot easier than what you're proposing to do, and the efficiency impact probably isn't that big. (In general, you will probably hear or have heard the mantra: Don't try to optimize too early.)
To be honest, I'm not sure you realize that filtering for EnemySprite will get you all object instances of its subclasses as well.
public class CollisionChecker(){
private List colliders;
public CollisionChecker(){
colliders = new ArrayList<Object>();
}
public void addCollider(Object o){
colliders.add(o);
}
public List<EnemySprite> getEnemySprites(){
List<EnemySprite> enemies = new ArrayList<EnemySprite>();
for (Object o : colliders)
if (o instanceof EnemySprite)
enemies.add((EnemySprite)o);
return enemies;
}
}
If you're storing the objects in a List<Object>, call Class#isInstance() on each element, adding them to another List if isInstance() returns true.
List<Object> objects = new ArrayList<>();
public <T> List<T> getObjects(Class<T> desiredClass) {
List<T> desiredObjects = new ArrayList<>();
for (Object o : objects)
if (desiredClass.isInstance(o))
desiredObjects.add((T)o);
return desiredObjects;
}
getObjects(EnemySprite.class); // call it like this
If you just want collision detection, then I would add them to a static collection in the ancestor class. This would be the most efficient solution.
If you want to all descendants for a class you should check out the reflection APIs. Yes, they're said to be slow, but I have doubts that it matters enough for things that aren't computed for every frame. And for things that you need in every frame tree traversal would inefficient anyway. (#Miffet's suggestion of string comparison would probably be even slower than regular reflection.)

Java: Is setters should make `Clone` or it's up to caller pass `new` copy?

What considered to be the best & common practice if I want to make sure that after setter is called the object cannot be modified from outside? In the code there is detailed simple self explained example, With 2 options dilemma.
//caller scope
CustomObject original = new CustomObject(params...); //original state 1
MyClass mMyClass = new MyClass(original);
original.modifyMe(params...); //original state 2
mMyClass.setCustomObject(original);
original.modifyMe(params...); //original state 3
/*!!!REQUIREMENT: mMyClass.CustomObject should be in state 2!!!*/
class MyClass {
private CustomObject mObject;
public MyClass() {
this.mObject = new CustomObject();
}
public MyClass(CustomObject obj) {
this.mObject = obj.Clone();
}
//mObject is private, modified only through setter
public getCustomObject() {
return this.mObject;
}
public setCustomObject(CustomObject obj) {
//Option 1 in the caller
//mMyClass.setCustomObject(new CustomObject(params...));
this.mObject = obj;
//Option 2 in the caller
//mMyClass.setCustomObject(callerCustomObject);
this.mObject = obj.Clone();
}
}
I wouldn't use clone here. Rather than making inefficient defensive copies, try making CustomObject immutable. You can modify state by adding withXXX methods (roughly equivalent to setXXXX) but they create a new instance of the host object (rather than the Object being passed in). Project lombok comes with some handy preprocessor annotations for creating Immutable objects with Withers. Also see the Immutables 2.0 project.
#AllArgsConstructor
class CustomObject {
#Wither #Getter
private final int state;
}
CustomObject one = new CustomObject(1);
CustomObject two = one.withState(2);
assertThat(one.getState(),equalTo(1));
assertThat(two.getState(),equalTo(2));
By using genuine Immutable Objects you will incur much less memory (& GC) and CPU overhead than with defensive copies - as well as much simpler code.

Using existing instance if constructed with same values

I have to create a class/constructor which allows the following:
Object a = new Object("test");
Object b = new Object("test");
a == b // should be true
So Object a and b should not only be the same according to their values but also should use the same reference and reference the same memory.
The constructor should find out if an instance with the given values already exists and if yes just take the reference and point it to the existing object.
Is there some way to get all created instance of a specific class?
Can someone give me a short hint where to start? I have no idea...
This isn't possible using plain constructors, as these always entail a memory allocation. Typically, you would use a static factory method in order to have better control over object creation.
Use something similar to the Singleton pattern, but with an Object pool of its own type as a data member, and then go through getInstance() to make new instances. Within getInstance(), check the pool for matching Object already existing, and if so, just pull a reference to hand back; if not, call the private constructor to make a new one, add it to the pool, and then return it.
public class A {
static ArrayList<A> existingAs =new ArrayList<>();
private String val;
private A(String value)
{
this.val=value;
}
public A getInstance(String value)
{
A newA=null;
for(A a: existingAs)
{
if(a.getVal().equals(value))
return a;
}
newA=new A(value);
existingAs.add(newA);
return newA;
}
public String getVal() {
return val;
}
public void setVal(String val) {
this.val = val;
}
}
new always creates a new instance. You could use a static factory method which internally pools the instances.

Is there any way to mark an object to indicate it has been through a process?

Take, for example, immutability. How could I modify an object to indicate that it has been made immutable already and need not be wrapped again?
Let us assume we do not want to use reflection to scan for setters as that would be inefficient and insufficient.
Example:
// Deliberately chosing lowercase because it is a system attribute.
interface immutable {
// Nothing in here I can think of.
}
// immute - have I invented a new word?
// What can I do with the return type to indicate immutability?
public static <T> List<T> immute(List<T> list) {
// If it's not an immutable
if (!(list instanceof immutable)) {
// Make it so - how can I stamp it so?
return Collections.<T>unmodifiableList(list);
}
// It is immutable already.
return list;
}
Further playing with the idea produced this foul solution - it is horrible and almost any other trick would be better but I felt I should post. Please please find a better solution:
public class Test {
// Deliberately chosing lowercase because it is a system attribute.
interface immutable {
// Nothing in here I can think of.
}
// immute - have I invented a new word?
// What can I do with the return type to indicate immutability?
public static <T> List<T> immute(List<T> list) {
// If it's not an immutable
if (!(list instanceof immutable)) {
// Make it so - how can I stamp it so?
return Hacker.hack(Collections.<T>unmodifiableList(list),
List.class,
immutable.class);
}
// It is immutable already - code DOES get here.
return list;
}
public void test() {
System.out.println("Hello");
List<String> test = new ArrayList<>();
test.add("Test");
test("Test", test);
List<String> immutableTest = immute(test);
test("Immutable Test", immutableTest);
List<String> immutableImmutableTest = immute(immutableTest);
test("Immutable Immutable Test", immutableImmutableTest);
}
private void test(String name, Object o) {
System.out.println(name + ":" + o.getClass().getSimpleName() + "=" + o);
}
public static void main(String args[]) {
new Test().test();
}
}
class Hacker {
// Hack an object to seem to implement a new interface.
// New interface should be instanceof testable.
// Suggest the additional type is an empty interface.
public static <T> T hack(final Object hack,
final Class<T> baseType,
final Class additionalType) {
return (T) Proxy.newProxyInstance(
Thread.currentThread().getContextClassLoader(),
new Class[]{baseType, additionalType},
new InvocationHandler() {
#Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// Always invoke the method in the hacked object.
return method.invoke(hack, args);
}
});
}
}
If the check will be done on the same location, you could use a set or map, where you put all your wrapped objects, and check them later on in almost constant time. To avoid memory leaks, you could wrap them using weak references .
If the introduction of AOP is a (rather heavyweight) option, you could solve your problem using inter type declarations via AspectJ. This way, you could just add a private member with the reference to the corresponding wrapped instance to the Collection interface, if I remember correctly something like this:
aspect Unmodifieable {
private Collection java.util.Collection.unmofifieableWrapper = null;
public Collection java.util.Collection.getUnmodifieable() {
if (unmofifieableWrapper == null) {
unmofifieableWrapper = somehowRetrieveUnmodifieableCollection(this);
}
return unmofifieableWrapper;
}
}
You can do this with naming conventions in your classes.
interface MyObject;
class MyMutableObject implements MyObject;
class MyImmutableObject implements MyObject;
In my current project, I do something similar. I have an interface that needs to have a setter, but one of the implementing classes is immutable. When you call its setter it throws an Exception (it's setter should never be called, but it's there just to be safe).
The "information" you're looking for is more for the programmer than the compiler, so you don't need a language implemented "stamp".
The Collections.unmodifiable* methods return subtypes of UnmodifiableCollection so you could check UnmodifiableCollection.class.isAssignableFrom(list) then test the concrete types.
Without using instrumentation, I think you're stuck checking types.

Categories