I've come across the following code at work and it raised a question in my mind.
\\Option 1
public class MyObjectRegistry
{
private MyObjectMapper mapper = new MyObjectMapper();
public void StoreMyObjects (List<MyObject> myObjectList)
{
mapper.StoreMyObjects(myObjectList);
}
}
public class MyObjectMapper
{
public void StoreMyObjects(List<MyObject> myObjectList)
{
for (MyObject myObj : myObjectList)
{
//Store Object In Database
}
}
}
vs
\\Option 2
public class MyObjectRegistry
{
private MyObjectMapper mapper = new MyObjectMapper();
public void StoreMyObjects (List<MyObject> myObjectList)
{
for (MyObject myObj : myObjectList)
{
mapper.StoreMyObject(myObj);
}
}
}
public class MyObjectMapper
{
public void StoreMyObject(MyObject myObject)
{
//Store Object In Database
}
}
Option 1 is currently what is in the code base. My question is: Is one of these approaches better than the other? Are there any conventions or best practices regarding a situation like this regarding where the iteration should take place?
The first one should definitely be preferred. The second example keeps calling an external method which is much more resource demanding than the first due to the abstraction involved. The lower level you can keep your iterations the better.
The way it is now, with a List in the method signature, should definitely be preferred because the performance of database insertion is dramatically better with insert batching. With the code designed as in the second example, batching would be a great pain to implement, which means it probably wouldn't be implemented.
Related
So, this element of code has the potential to get pretty ugly. There is the potential of adding multiple elements to the list in each if statement as well as many more if/else statements. What would be the best pattern or way of going about designing this piece of code. I was thinking about the chain of responsibility but that means be passing the list round everywhere which isn't the best or even the builder pattern? Any thoughts??
List<String> aList = new ArrayList<>();
if (something.contains(Effect.HARD)) {
aList.add("");
}
if (something.contains(Effect.REFLECT)) {
aList.add("");
aList.add("");
} else {
aList.add("no reflect");
}
if (something.contains(Effect.OUTLINE)) {
aList.add("something");
}
if (something.contains(Effect.GRADIENT)) {
aList.add("gradient");
} else {
aList.add("no gradient");
}
Use a visitor (link to wikipedia page).
Here is some lighthearted example code:
public interface Visilator
{
// Process the stuff and, maybe, add an element to the kerplungy list.
void doStuff(Stuff stuff, List<Kerplungy> kerplungyList);
}
public class Kerplungilator
{
// Actually create this however you choose.
#Autowired
private List<Visilator> visilatorList;
public List<Kerplungy> processStuffs(final Stuff stuff)
{
final List<Kerplungy> returnValue = LinkedList<>(); // ArrayList is for chumps.
for (final Visilator current : visilatorList)
{
current.doStuff(Stuff, returnValue);
}
return returnValue;
}
}
public clss HootVisilator
implements Visilator
{
public void doStuff(
#NotNull final Stuff stuff,
#NotNull final List<Kerplungy> kerplungyList)
{
if (stuff.hoot())
{
final Kerplungy hootKerplungy = new Kerplungy("hoot");
kerplungyList.add(hootkerplungy);
}
else
{
System.out.println("not hoot");
}
}
}
Normally you'd look at replacing those ugly conditionals with polymorphic code, but that won't work well here as the conditions (something.contains(...)) are not based on the type of the object. You could turn them into objects, but this would not be an elegant solution either. Builder and Visitor could be used, but I doubt very much you code would more readable at all.
I am making a storehouse system(use OOP) and of course there are many goods in it. I want to have a ArrayList(or some other containers) to hold those goods, so I can change less code when the goods change from lights to cups(subclass of goods). It seems can be fulfilled by extends/implements the class Goods. But when I get the input of user, it seems I have to use many if-else if I have many subclass.
like this:
if(name == Light){list.add(new Light(...)}
if(name == Cup){list.add(new Cup(...)}
...
And when I get the goods from the list, it seems that I have to use instanceof
like this:
if(goods instanceof Light){}
if(goods instanceof Cup) {}
...
So the code become not so elegant at all.
So my question is how can I solve this problem.
The questions from the comments are certainly justified: When you store the Goods as Goods, at which point in time (and why) is it relevant what type these elements have?
Of course, one could imaginge scenarios where this information is necessary. But one should definitely consider a different structure when this is the primary way of using these classes. For example, one then might consider something like a
Map<Class<?>, List<?>> mapFromClassToListOfObjectsWithThisClass;
that can be maintained (in a type-safe way) internally - but that's just a first, rough idea.
In any case, you should avoid many instanceof clauses. Particularly when the intention is to extend this system with other types later. You certainly do not want to be forced to re-compile your code when some client introduces a new subtype of Good.
You could then consider to use a method that allows extracting the objects of a particular type from a given list:
import java.util.ArrayList;
import java.util.List;
public class TypeListFilterTest
{
public static void main(String[] args)
{
List<Number> list = new ArrayList<Number>();
list.add(Integer.valueOf(12));
list.add(Double.valueOf(12.34));
list.add(Float.valueOf(23.45f));
list.add(Integer.valueOf(34));
list.add(Float.valueOf(34.56f));
List<Float> floats = filter(list, Float.class);
System.out.println("Floats : "+floats);
List<Integer> integers = filter(list, Integer.class);
System.out.println("Integers: "+integers);
}
private static <T> List<T> filter(Iterable<?> list, Class<T> t)
{
List<T> result = new ArrayList<T>();
for (Object object : list)
{
if (t.isInstance(object))
{
result.add(t.cast(object));
}
}
return result;
}
}
In the best case, this method could replace the instanceof tests, and would allow treating different types, leaving the responsibility to be aware of these types to the client code. This way, the classes could handle new types, without having to be recompiled with new instanceof checks.
But based on the current problem description, this is also only a first idea, that may or may not be applicable in your case.
As OO thingking: DO NOT program to see what object do you have, just use them.
Don't tell what to do when you calling an object, they should know the method themselves.
In following demo, the CupLight is a kind of Goods, and you can have more kinds of Goods.
When you use them, just tell them do the job, I mean call the method saySomething().
No if-else is needed in this situation
public class Test {
public interface Goods {
public void whoAmI();
}
public static class Light implements Goods {
#Override
public void whoAmI() {
System.out.println("I'm a Light");
}
}
public static class Cup implements Goods {
#Override
public void whoAmI() {
System.out.println("I'm a Cup");
}
}
public static class CupLight extends Light {
public void saySomething() {
whoAmI();
}
}
public static void main(String[] args) {
new CupLight().saySomething();
}
}
I propose you trade your "if-else" statements for Chain of Responsibility pattern.
Chain of responisibility on wikipedia
Enjoy :)
I have the below use case where I get events containing JsonString1, I have have to do some processing/transformation to get to Object1 through Object 4. As of now I only have one such case and its likely that in future there there might more such hierarchies (atmost 2-3).
I am unable to decide on what would an elegant way to code this.
JsonString1
|
JsonString2
/ \
JsonString3 JsonString4
| |
Object1 Object2
|
Object3
I could just have an Abstract class for processing JsonStrings 1 to 4 and concrete implementation for each type of the event. Something like
public abstract class AbstractEventProcessor {
public AbstractEventProcessor(String jsonString1) {
// Do processing to get JsonString2, JsonString3 and JsonString4
}
}
public class Event1Processor extends AbstractEventProcessor {
Event1Processor(String str) {
super(str);
}
Object1 getObject1() {
}
Object2 getObject2() {
}
Object3 getObject3() {
}
}
And similar implementations more events as they come along.
Is there a better way to do this ?
Also for now two things are constant, but in a rare case might change.
All events will have JsonString1 .. JsonString4 but the number of Objects at the end will vary. But in future this might change.
Although its very unlikely (but not impossible) that the format of the strings might change (say from json to xml)
Do I accomodate for such changes as well by providing interfaces for string transformations, or it this an overkill ?
Usually I am stuck at such places where I am trying to figure out the most elegant way to do this and end up spending a lot of time ? Is there any general advice as well for this ? :)
Thanks
It's not very clear what you exactly want. However, even without it, when I see your hierarchy, it smells. Usually, during my code reviews, whenever I see too fancy hierarchy like yours, there is something wrong in the design.
Try considering using decorators to avoid the inheritance hell. Thus you may create any combinations you may need in the near and far future. Get some inspiration in the standard java class java.io.Reader and its subclasses.
For your case it would mean something like this (at least how I understand your description):
public interface EventProcessor {
public BaseObject processJsonString(String jsonString);
}
public abstract class AbstractEventProcessor implements EventProcessor {
final private EventProcessor processor;
public AbstractEventProcessor(EventProcessor processor) {
this.processor = processor;
}
}
public class SpecialObject1 extends/implements BaseObject { ... }
public class SpecialObject2 extends/implements BaseObject { ... }
public class SpecialObject3 extends/implements BaseObject { ... }
// Each your future processor will look like this
public class Event1Processor extends AbstractEventProcessor implements EventProcessor {
public Event1Processor(EventProcessor processor) {
super(processor);
}
public SpecialObject1 processJsonString(String jsonString) {
final SpecialObject1 result = (SpecialObject1) super.processJsonString(jsonString);
// here you add this Event processor specific stuff
...
return result;
}
// Maybe more methods here
}
public class Client {
public void useEventProcessor() {
final EventProcessor processor1 = new Event1Processor(new Event2Processor(new Event3Processor(null)));
final SpecialObjectX object1 = processor.processJsonString(jsonString);
final EventProcessor processor2 = new Event51Processor(new Event20Processor(new Event2Processor(null)));
final SpecialObjectY object2 = processor2.processJsonString(jsonString);
}
}
Ok, assume I have a class, X and X is something which has an aggregate relationship with other objects. Lets pretend X is a soccer stadium.
X is full of class spectators. However, the behaviour of each spectator for a particular activity differs. Instead of IF statements, I want the different behaviour to be within the spectator class, so that I can use dynamic binding.
However, the problem is that the behaviour the spectator performs affects the "soccer stadium" class. So I was thinking of passing "this" from the soccer stadium class, through a method, to the Spectator class, so that the spectator class can do something to the Soccer Stadium class?
public class SoccerStadium{
SpecatorInterface s = new Spectator();
public void SpectatorBehaviour(){
s.doSomething(this);
}
public void doSomethingthingBySpecator(){
}
}
public class Spectator implements SpecatorInterface{
public void doSomething(SoccerStadium s){
s.doSomethingthingBySpecator();
}
}
I only want to do this so that I can use dynamic binding and alter the behaviour in Specator.doSomething() so that I can have lots of different types of SpectatorSuperClass as an attribute passed to SoccerStadium and then have the different behaviour.
EDIT: What if I passed the reference of the Stadium to the Specator through the Spectator constructor, instead of passing this?
This isn't so much "bad oo programming" as it is tightly coupled. There's nothing inherently wrong with passing around this pointers, but it can become a mess very very quickly. We can't really say more without more information.
I see no problem with the usage of this as a parameter. Nevertheless, I don't like the new Spectator() call that was hard coded in your SoccerStadium class. I believe you should have a Factory with a createSpectator method that could receive a parameter indicating which type of spectator you intend to create.
To me, this kind of two-way circular relationship is bad news. What if Spectators want to go to the Theatre instead?
I'd decouple the relationship by making the Stadium a subscriber to Spectator dispatched events.
public class SoccerStadium
{
ISpectator s = new Spectator();
public SoccerStadium()
{
s.DidSomething+=DoSomethingthingBySpecator;
}
public void SpectatorBehaviour()
{
s.DoSomething();
}
public void DoSomethingthingBySpecator(object sender,EventArgs e)
{
Console.WriteLine("spectator did something");
}
}
public interface ISpectator
{
event EventHandler DidSomething;
void DoSomething();
}
public class Spectator:ISpectator
{
public event EventHandler DidSomething;
public void DoSomething()
{
var ev=DidSomething;
if(ev!=null)
{
ev(this,EventArgs.Empty);
}
}
}
...and so the Spectator now has a means of communicating to anything that's interested, but doesn't need to know a thing about it.
As people have said, there's absolutely nothing wrong tight tight coupling and what you are doing. However, if you want a little bit of decoupling, use the classic visitor pattern.
public interface SpectatorVisitor {
...
void visit(Spectator spectator);
}
public class Spectator {
...
public void accept(SpectatorVisitor visitor) {
visitor.visit(this);
}
}
public class Stadium {
...
spectator.accept(new StadiumSpectatorVisitor());
}
The visit method signature could be altered to accept some kind of state object as well if you need to. Otherwise you could simply define the relevant methods on the Spectator class, and make the visitor collect up the information needed to alter the stadium.
For instance:
public class Spectator {
private Team supports;
public Team getSupports() {
return supports;
}
public void accept(SpectatorVisitor visitor) {
visitor.visit(this);
}
}
public class SupportedTeamVisitor {
private Map<Team, AtomicLong> supportCount = new HashMap<Team, AtomicLong>();
public void visit(Spectator spectator) {
Team supports = spectator.getSupports();
if (! supportCount.contains(supports)) {
supportCount.put(team, new AtomicLong(0));
}
supports.get(team).incrementAndGet();
}
public Map<Team, AtomicLong> getSupportCount() {
return supportCount;
}
}
public class Stadium {
public long getSupportCount(Team team) {
SupportTeamVisitor visitor = new SupportedTeamVisitor();
for (Spectator spectator : spectators) {
spectator.accept(visitor);
}
AtomicLong count = visitor.getSupportCount().get(team);
return (count == null) ? 0 : count.get();
}
}
Make sense?
Your implementation is absolutely fine, I have seen that kind of thing before. Yes you can hold on to the Stadium reference, by passing it through the Spectator constructor, that would probably be cleaner than sending through the reference every time you need it.
However, I don't like it very much; I prefer inner classes. It's not completely clear what you're trying to do, but something like this is possible:
public class Outer {
private int someVariable=0;
public void someMethod(){
ExtendsInner ei = new ExtendsInner();
ei.innerMethod();
System.out.println(someVariable);
}
private void anotherMethod(){
someVariable++;
}
public abstract class Inner {
public abstract void innerMethod();
}
public class ExtendsInner extends Inner{
public void innerMethod(){
anotherMethod();
someVariable++;
}
}
public static void main(String[] args){
Outer o = new Outer();
o.someMethod();
}
}
Unfortunately, you would then have to have all of your "spectator" classes inside your other class, which could lead to one really long file, and thus, ugly code.
However, I think you should definitely avoid doing both things, as it will most definitely make your code overly complicated.
As Matt said, what you are describing is the visitor pattern. Nevertheless, I don't think that's your best alternative (As Falmarri said, that kind of design tends to be tightly coupled, and you end up putting to much logic in your business object, breaking SoC, SRP, etc..).
The fact that the behavior of each spectator for a particular activity differs, doesn't mean that the logic should be included (nor pass) through the spectator class. There are a lot of different ways to avoid those IF statements. I'd suggest you go with something like this link suggest which is far more powerfull than the if statements, visitor pattern, or all the other alternatives, and it's really easy to implement it in another class, and maintain all those goods OOP principles (which are there for a reason).
When programming with C/C++ or Python I sometimes used to have a dictionary with references to functions according to the specified keys. However, I don't really know how to have the same -- or at the very least similar -- behavior in Java allowing me dynamic key-function (or method, in Java slang) association.
Also, I did find the HashMap technique somebody suggested, but is that seriously the best and most elegant way? I mean, it seems like a lot to create a new class for every method I want to use.
I'd really appreciate every input on this.
You don't need to create a full, name class for each action. You can use anonymous inner classes:
public interface Action<T>
{
void execute(T item);
}
private static Map<String, Action<Foo>> getActions()
{
Action<Foo> firstAction = new Action<Foo>() {
#Override public void execute(Foo item) {
// Insert implementation here
}
};
Action<Foo> secondAction = new Action<Foo>() {
#Override public void execute(Foo item) {
// Insert implementation here
}
};
Action<Foo> thirdAction = new Action<Foo>() {
#Override public void execute(Foo item) {
// Insert implementation here
}
};
Map<String, Action<Foo>> actions = new HashMap<String, Action<Foo>>();
actions.put("first", firstAction);
actions.put("second", secondAction);
actions.put("third", thirdAction);
return actions;
}
(Then store it in a static variable.)
Okay, so it's not nearly as convenient as a lambda expression, but it's not too bad.
The short answer is you need to wrap each method in a class - called a functor.