Avoiding redundant code at all cost?

Mainly a subjective question (a bit similar to my previous thread)

Let’s say that I have a 2 classes : Player and Background. (it’s just an example, I don’t have them that way)
Eventually, I’ll have to render them on the screen so they will, at least, both have :

  • int x, int y, int w, int h (position) (or a vector, doesn’t matter)
  • float a, float r, float g, float b (color)
  • more things (…)
    There are lots of way to solve this, but what would be your approach? Make an intermediate class that will hold the values? Extend it? Integrate it as a parameter in both classes? Or simply copy’n’paste all those type of variables in all classes?
    Even tough it’s supposed to be good practice to avoid redundant code mostly for performance and/or evolution issues, we’re just talking about int & float in modern applications here so does it really matter?
    Besides not using an intermediate object makes it easier to access the value from an instance: pl.getX() instead of pl.getPosition().getX() for example. Using intermediate objects for redundant values seems the good way, but somehow when you start to have lots of classes, you just end up calling an intermediate value from another intermediate object from another intermediate object again.

One other thing, are you using interfaces a lot to implement common methods? What I mean by that is, most of the time, I find it easier to just make a Factory/Builder or whatever “Checker” class with statics methods to do the job. I don’t know, for some reason I just enjoy making a pattern where I have ONLY values left, and ONLY methods right, not both in the same class, but is this really a good thing?
For example, instead of implementing an interface that would make my Player class have an “update” method, I’d just create an Updater static class (which will virtually be able to manage all kind of ‘updates’ needed for the game) that will make different things depending on the method I’m calling and with what parameters, like for the print :

  • public void update(Player player)
  • public void update(Background background)
    I just don’t like to have that “@override” method in my Player class, I’d rather have it hold important values only.

Oh and on a side note : HOW THE HELL ARE YOU PROGRESSING IN YOUR PROJECTS?
Most of the time, I just take too damn much time thinking of things like the ones mentioned in this thread, even though I know it’s a bad thing, but I can’t stop >:(
I seriously need to kill that part of my brain…

In Scala, I’d tell you to use a trait, like Positionable, Colorable, MoreThingable :slight_smile: Java will have something similar in 1.8, but since we’re looking for solutions now… For your position/color/more-things needs, your implementation will depend on how generic you’re trying to make your internals. For most games, you can just stick the common code on an abstract GameObject base class and be done with it.

If you’re looking to keep those responsibilities orthogonal, then you’re either going to have to put them on interfaces and copy the implementation to each, or delegate to another object. In fact, even if you use an abstract base, it’s still not a bad idea to still use interfaces and just make the base implement them. The other approach as I mentioned is to delegate to some other object: a lot of game engines separate the Player/Mob/Item/Whatever class from the entity on the map by having them refer to a separate object it calls a “Puck” or a “Pawn”.

There’s certainly nothing incompatible with using interfaces and factory/builder classes. In fact, Java’s Service Provider Interface, used in JDBC among other places, tends to work like that (in that you ask the DriverManager for an instance, you don’t create a Driver yourself). What you’re talking about with your Updater class has little to do with factories and is basically procedural programming. With enough discipline, that can be a sound methodology, but Java isn’t ideally suited for that style. Further, I’d keep away from all that ad hoc overloading, which doesn’t enforce any kind of common contract of types or invariants.

It seems you like to scatter the class data in loads of other classes to avoid redurancy.
For small things this can be smart and stuff, but for bigger projects i would not recomment it.
I dont know how experienced you are with OO pragramming, but you should read some more about it, what you are doing looks more like C programming.
Object should hold their own data, if they share a lot with other classes, then use an extend or interface.

Singletons / Static classes should only be used for common functions like getFileData or loadFile.
If you have an project with 100 classes with all their own draw functions, how are you going to find the right function inside the (static) drawing class if you want to change one?

[quote=“sproingie,post:2,topic:40167”]
Huho, I didn’t think about it that way. Makes sense, I always used to code like that, maybe it’s why I’m having an hard time figuring out things.

Well, It’s not like I don’t understand the point of having methods in a precise class (logic), but for some reason I always end up wondering : “Wait, what if I want that method to do more things? Receive more parameters? Or simply use it from another class?”
Mainly, this is why I’m using lots of “Updater” classes, since I just have to modify it and it won’t have any kind of impacts on my existing classes. I’m sort of looking of a “safe” way to code, maybe. Usually I like to delegate actions to others objects, in the end I have LOTS of objects (or a big object doing all the things), it’s just easier for debugging, I think…?

Funny, I did think about having a big “GameEntity” abstract class, which would be the mother class of all my others game objects, but then I realized that would be just “doing Java in Java”, and thought I was just trying to reinvent some sort of wheel, which is a bad thing. Maybe I should have kept this solution.

Sigh - Seems so, even though I actually never started a project in C or C++, that’s the joke. (but with lots of language like it I admit)

game programming is a lot of hacking and getting things done

if you have an algorithm dont have it twice obviously
if two different things both have x and y, it would kinda overkill to create a class just for that

between that do whatever seems practical, understandable, and easy to handle - now and in the future

redundant code can have its advantages

-when its very unlikely to get changed later
-when its used in complex specific behaviors that would take
a confusingly complex contruct to generalize it
-when there is a performance problem in a heavy loop (repeating the same instruction without looping back
can save some cycles)
-when it has to be edited a lot for specifc small changes (writing it like a cinematic script)

Also, not everything is a natural hierarchy. So dont overstrech the code to somehow
build an inheritance model if you talk about totally different elements.

I didn’t realize people still manually unrolled loops.

Ok, simple hacked testcode here to show the performance difference
while having the same outcome.
The unrolled loop runs about twice as fast as the normal loop on my JVM.

(observe the bytecode)

Did not check that with the Java 7 compiler though.

Unrolling the loop (partly - like a chunk of 5 to 10 repetitions) can make a huge difference when doing very heavy looped calculations.
Such as particle animation or pathfinding that actually impact performance.



public class LoopUnrolling
{

	public static void main(String[] arg)
	{
		long time=System.currentTimeMillis();
		
		
		int a=11;
		a+=1;
		int counta=0;
		
		//rolled
		for(int i=0;i<1000000000;i++)
		{
		
			a+=i;	
			if(a+i==a+i-a) a++;
			a-=i;
			counta++;
		}
		
		//unrolled
		/*
		for(int i=0;i<100000000;i++)
		{
		
			a+=i;	
			if(a+i==a+i-a) a++;
			a-=i;
			counta++;
			
			a+=i;	
			if(a+i==a+i-a) a++;
			a-=i;
			counta++;
			
			a+=i;	
			if(a+i==a+i-a) a++;
			a-=i;
			counta++;
			
			a+=i;	
			if(a+i==a+i-a) a++;
			a-=i;
			counta++;
			
			a+=i;	
			if(a+i==a+i-a) a++;
			a-=i;
			counta++;
			
			a+=i;	
			if(a+i==a+i-a) a++;
			a-=i;
			counta++;
			
			a+=i;	
			if(a+i==a+i-a) a++;
			a-=i;
			counta++;
			
			a+=i;	
			if(a+i==a+i-a) a++;
			a-=i;
			counta++;
			
			a+=i;	
			if(a+i==a+i-a) a++;
			a-=i;
			counta++;
			
			a+=i;	
			if(a+i==a+i-a) a++;
			a-=i;
			counta++;
		}
		*/
		
		System.out.println(a+"  count: "+counta);
		
		System.out.println("ms:"+(System.currentTimeMillis()-time));
		
	}
	
}


Manual loop unrolling can indeed have significant performance differences, even in real world code. It’s good to also keep in mind that the JVM does loop unrolling itself already. I found that after 4 manual repetitions, there was barely any speed increase. But that was with vector processing code. In the end, the smaller the loop-body, the more you’ll gain by manually unrolling it.

TL;DR: don’t do it. :persecutioncomplex:

Its a simple quadratic function.

The amount of saved loop-comparrisions decreases per more repeated functions.

So lets say 5 repetitions should be enough, after that it improves not much.

I would save this loop unrolling to the end of development, when you want to suqeeze some
performance out of it, and dont change this part of the code anymore.

Didn’t you notice that I agreed with your findings? Why explain it further?

I like to brabble ::slight_smile:

Regarding manual loop unrolling, it is really a last resort and you should never ever do it too early.
While it can make a noticeable difference in isolated code, in my experience it can actually hurt performance in larger projects quite a bit.

To give an example: Many years ago I developed emulators. The CPU emulation and rendering loops in particular were performance heavy parts, and quite early on I noticed that I could gain a bit of performance by manual loop unrolling, inlining code and huge look-up tables. I tried every low-level optimisation trick that I could find. Redundancy everywhere, making it difficult to maintain and debug, and making the code huge.
Not that long ago I tried to create another emulator, attempting to make the code as small as possible and avoiding as much redundancy as possible. The CPU emulator was less than about 1/3rd of the size of the old one. Everything was calculated on the fly (no lookup tables for flag registers and such). That code turned out significantly faster than the old code base, and was more accurate to boot.

Also, years ago I even created a generator of a 68000 CPU emulator that generated the code for every single instruction in an attempt to minimize branching and to make every instruction as fast as possible. The generated code was huge and optimal in theory if you consider the individual bits of code that emulated the CPU instructions. I’m pretty sure if you’d profile the individual blocks of CPU instruction emulation code, that it was probably as fast you could get.
In practice however, it was fantastically slow.
Another (hand-written) 68000 emulator that a friend wrote was an order of magnitude faster, so the ‘optimal’ generated CPU was abandoned and replaced by his.

I’m guessing that there are a few things that have caused this slowness:

  1. A JVM has a difficult time deciding what to optimize if the code is huge and uniformly slow/fast. It might just decide not to compile anything if there are no hot-spots or if code blocks are huge.
  2. Huge code might cause cache misses.
  3. Branching code is not always as expensive as you might expect (perhaps a modern CPU often seems to do a pretty good job at branch prediction)
  4. A JVM might usually be better at doing low-level optimisations than yourself.

The morality of this story: Stay away from manual loop unrolling and inlining and such. At least until your project is done and you’ve done your profiling. It’s very difficult to tell what you have to optimize without seeing the big picture.
There are probably much smarter ways to optimize your program than to resort to low level tinkering. It will just leave you with huge blobs of difficult to maintain code.

Unrolling loops can also have a negative impact: increase i-cache requirements, blowing branch predictors, trace-caches, etc.

Roquen said in 1 sentence what I needed wall of text and years of messing around for ;D

Indeed, and hence my original statement. Figured it went against the “write dumb code” mantra. The JVM is supposed to be smart at optimizations these days, and surely loop unrolling is one of the simplest tricks it’s got up its sleeves.

Back to the original topic: data driven + design by composition = win.

I think all programmers go through a period where they question code redundancy. In Java, though, class structure and code redundancy is pretty common place. If we were to do true OOP, every single class would have getters and setters, and each class would be able to be taken from the main program without braking it critically.

I think actively trying to stop redundant code while writing the program is a lot of trouble. It is a lot easier to find redundant code when you are re-factoring and trying to find a better way to write it. Your thinking process should first be trying to get the code working before you even think about how redundant it is.

Even with everything that has been stated here. You are bound to have a bit of redundancy between classes to pass values from one class to another, and also one function to another. Trying to design a game perfectly is a great goal, but one that someone should strive for in timely steps.

Getting projects done is all mental. Like any good book, or game, or outside activity… I have to be in the mood to do it. I try not to force myself to program if my body (or brain) does not feel like it. It prevents me from getting frustrated, and usually when I’m doing other tasks a bolt of inspiration comes to me. At that moment, I try my best to it down somewhere so I can use it the next time I program.

My programming is a lot more productive, and I feel a lot better about myself. It was a lot better than staring at the computer screen for 5 hours with a pencil in my hand trying to solve that 1 bug. If you are not on a deadline, why work your brain and body out like it is? Relax and give yourself time to work out the problems.

Code redundancy is common in Java ?

Getters and setters are a characteristic of true OOP ?

Haha… well a representation of true OOP, yes. I was poking a little bit of fun at the fact that classes are supposed to be 100% modular. Therefore dependencies on other classes would be 0% and each class would therefore have to each hold its own variables accessible by getters and setters.

If you want to see Java code redundancy, then imagine how our each class would look if you couldn’t write the “extend” clause. Every “Object” has the exact same functions… pretty redundant if you ask me.

It is amazing how many teachers I’ve seen teach it this way both in Java and C++.

Do I follow it? No way. Once you leave the confines of the classroom you realize that always following convention results in ridiculously slow code and Java Heap Space errors.