Making a Static Free Engine

Static isn’t inherintly evil, it is just something that needs to be used intelligently just like everything else in java. For a beginner it can seem so easy to use static because often in simpler projects it can make all of your problems dissapear. Scaling up those faulty techniques causes the nightmares the OP described. In a properly coded program static will probably be required, however it needs to be used correctly otherwise you’ll have some headaches later.

Static is like any other tool – you should know its purpose and not just reach for it because you’re used to using it. I think a lot of people still confuse convenience with intended purpose though.

And just as many people hold up coding standards taught to them as dogma instead of thinking why they were taught like that. :frowning:

This situation seems eerily similar to what happened to a co-worker of mine who just recently started programming in Java. First you have to consider why you have a static main (entry) method, then once you understand the why, the how (to avoid static hell) becomes clear.

The main method is the bootstrap/entry function that the JVM invokes in your main class to create an instance of that class when your application starts. The only way to have a member of a class exist independently of an instance is to make the member static. Since the main method is called before an instance of your main class has been instantiated, it must be made static.

The error you’re getting “cannot make a static reference to the non-static field” is because you’re trying to access a field within your class that hasn’t been created yet. The only part of your class that is in existence is the static main method and any variables that are created within its scope. Instead of declaring everything static to resolve the error, you need to create a new instance of your class, then reference the member variable/function associated with that instance as so:


public class NonStaticHeaven {
    private final String m_Message = "Hello non-static world!";
    
    public void SayHello() {
        System.out.println(m_Message);
    }		

    public static void main(String[] args) {
        java.awt.EventQueue.invokeLater(
            new Runnable() {
                @Override
                public void run() {
                    new NonStaticHeaven().SayHello();
                }
            }
        );
    }
}

Looking at the number of results returned by Google when you search for the error message, it would appear to be a common stumbling block, and I seem to recall having the same issue myself when I first got into Java years ago. Once you begin to wrap your head around how Java works, it makes a lot more sense.

As for static methods/members being evil, as many have already pointed out, there are places where static makes logical sense, and is the right tool for the job. The only “evil” aspect comes in when it’s misused, and that’s more of a reflection of the misunderstanding of the implementer than on the “righteousness” of the feature. :wink:

I don’t think you can really misuse static. You can merely use it in a way that makes language zealots cross.

Cas :slight_smile:

Any bug that survives Eclipse, Compilation and basic testing I consider a bad bug. The ones that stop you dead in the water and make you start thrashing your code in order to find it, is the type of bug I fear.

One nasty type of bug is the bug that is there all along but works fine initially, is always a horror. Instead of being in the code you just wrote. it is in other code hiding and waiting until the conditions are right or your code has snowballed enough to blow up. By this time your code is big enough for a bug to hide.

Another nasty bug form is the type that exists because of a perceptual understanding that does not match with the actual function of the beast.

My worst static bugs have met both of these criteria. The problem with perceptual understanding of static is subtle. When static creation and dependency gets complex, the order of creation can become critical.

As a simple example here is a class Widget used to build widget objects. It has two errors concealed in the code waiting to blow up as you expand the game.

One error is that using a byte to reference an array of 256 objects is going to work fine until you half fill the array. The game is going to be fairly complex before you reach the level where this is going to break.

The second error I have already stuck in. It is a static error that could not be found without thinking about what static really is and how the java compiler is putting things together.

The second your character trys to place a preSmoggle in the Factory, you are going to get an error. The problem is that the static preSmoggle refers to a smoggle that was defined after the preSmoggle was defined. It is hard enough to find this sort of error when you just added it and it blows up consistently and the issue is laid out in a straight row. If this same sort of issue is spread over several objects, good luck finding it quickly. Even when you know exactly what is blowing up with a null and you know where the offending code is, when the order of the compile can alter the results, the bug can turn into a nightmare.

import java.util.Random;

import com.badbadcode.example.stuff.materials;
import com.badbadcode.example.stuff.products;
import com.badbadcode.example.render.render;
import com.badbadcode.example.game
import com.badbadcode.example.Screen;
import com.badbadcode.example.Factory;
import com.badbadcode.example.Player;
import com.badbadcode.example.Entity;

public class Widget {

public static int clock = 0;
private String destinationFile = "";
protected Random random = new Random();

public static Widget[] widgets = new Widget[256];
public static Widget fneed = new FneedWidget(0);
public static Widget glonger = new glongerWidget(1);
public static Widget wonkafier = new WonkafierWidget(2);
public static Widget smocker = new SmockerWidget(3);
public static Widget preGlonger = new selfMaker(4, glonger);
public static Widget preWonkafier = new selfMaker(5, wonkafier);
public static Widget preSmoggle = new selfMaker(6, smoggle);
public static Widget smoggle = new Smoggle(7);

public final byte id;

public Widget(int id) {
	this.id = (byte) id;
	if (widgets[id] != null) {
		throw new RuntimeException("Duplicate widget issue!");
	}
	widgets[id] = this;
}

public boolean mightShock(Factory factory, int x, int y, Player p) {
	return false;
}
public boolean use(Factory factory, int x, int y, Player p) {
	return false;
}
public boolean mightNeedKicking(Factory factory, int x, int y, Player p) {
	return false;
}
public boolean mightSprayGrease(Factory factory, int x, int y, Entity e) {
	return false;
}
public boolean mightBlowUp(Factory factory, int x, int y, Entity e) {
	return false;
}

}

Every issue is a newbie issue but if you are trying to push your coding skills, Java is huge enough to always provide a new area where you are a newbie. Otherwise solid programmers create eventually obvious but elusive bugs when they found themselves using simple code that they rarely use. Since I usually trying to write code several levels above my skill set, avoiding methods of coding that can sneak compilation issues into the code is just smart.

After I had dealt with the previous bug, I had a bug like this that would work fine one game and blow up the next. I suspect it was the order that the objects were called during game play that made the difference. I finally gave up on finding the bug. I deleted a slew of classes and rewrote them avoiding static. Even with the learning curve of figuring out how to do stuff without static, it took me way less time to recode the classes than I had already spent trying to find the bug.

Troll?

Anyway, if you aren’t a troll:

[quote]Since I usually trying to write code several levels above my skill set…
[/quote]
If this is the problem you find, you shouldn’t be doing this.

Better to make a small building than a huge pile of rubble.

Get it right before you get it advanced.

ROTFL!

I think most of us here won’t reference an index with a byte. That’s pretty stupid.

Your trying to “preach” why static is bad when you’re second guessing how it works?

If I might be constructive…

… one thing I use static declarations is to “seal” independent code.

…Whenever I realize a function does its job without needing other data than the one provided by the function call arguments…

OR

… whenever I need a function to work across different classes without dependencies…

I declare it static and let the compiler slap me silly when I attempt to misuse the function.

I apply that same though process for classes or variables/constants.

Static isn’t OO. You can’t use static methods in interfaces and can’t override them. Static fields are globals: you’re asking one value to work for every single member of the class. All this is rather theoretical, of course. Where you get into trouble in real life is when you make your program more complicated; when a simple stand-alone object becomes part of a complex structure.

Basically, you find a subclass needs to override one of the superclass’s static classes. Or there’s a global value that doesn’t apply to one particular class instance.

However, most of the time statics are easy, avoiding them is difficult, your code is not going to get more complicated, and you’d be nuts to pay a big price to avoid them. If you do get into trouble, you can fix it when you do. But when it is time to fix it, fix it or you will be in Static Hell.

Note: a class defined as “static” in Java is something else completely and not a part of this discussion. (Though sometimes people do use the word to mean a class containing only static methods and fields–which is a part of this discussion.)

In other words what I call ‘stateless’ :wink: Agreed that then you CAN make it static. I’m never ever going to make any statement again about when you SHOULD do it because apparently that is sort of religious in nature.

It was just an example of how static is useful to me, but your mileage may vary.

So what you are saying is that… If you don’t fix parts of your program that are not working right, you’ll end up in trouble.

Really, all you just said could apply to any part of any programming language. :clue:

Seems like you’re picking on static because you personally have had trouble with it, to be honest.

I read the strangest things on forums sometimes.

Cas :slight_smile:

I like static :3

Static’s great. We get games made using static data and classes and methods all over the place. At night, we sleep soundly*, safe in the knowledge that our static hell is keeping the roof over our heads.

Cas :slight_smile:

  • Thanks currently to temazepan but that’s another story

I use static all the time and it’s great. The problem is, it doesn’t scale–in terms of numbers of classes and interfaces and the relationships between them. As your program becomes more complicated, in the parts of the program that become more complicated, the static methods and fields start to get really awkward.

What I’m saying is use statics. But when they start to get awkward in code you intend to enhance, pay the price to get rid of them rather than pile kludge on top of kludge.

This theoretically applies to any programing language, but Java handles complexity so well you’re more likely to notice the problem there. Everywhere else, when you hit static hell you’ll be in so many other hells it will be the least of your worries.

And you can stick to simple programs, even in Java, and forget all this.

Give us at least a example of your "“static hell”

I try to avoid static hell so I’m not that familiar with it close up. The usual problem I encounter is trying to stuff static methods into interfaces. I pass an object that implements an interface to a method, and that method needs static (class) data. The method to get it, in all classes that implement the interface, is, of course, static. At that point, I rework the code. If I kludged it, I imagine I’d be in “static hell”, which I suspect is something like writing in Fortran or C, which I do not want to do ever again.

I have recently come across code where the data for 1000 “objects” is stored in a set of 1000 element arrays. Game characters, for instance, with values for location, speed, health, etc… This is no doubt faster than have a GameChar class with instances in one 1000 element array, but as the game gets more complex, the lack of GameChar instances to pass around gets awkward. And the locking problems if multiple threads try to access individual characters will bring game execution and development to a halt.

There’s nothing wrong with any of this. Lot’s of people frame nice houses with pine 2X4’s. But they know they’re not going to put another 60 stories on top. The problem happens when people come up with a simple solution for a simple problem, then try to stick with it when the problem becomes complex.

On the one hand, what you’re describing is not a problem with static or whatnot… Is a general lack of proper software design.

You are aware that there are no truly universal solutions in software design? Specially with software as demanding as real-time applications (like most games are).

In essence, if you charge straight into implementation without devoting some time to making a decent design, you’ll sooner or later hit a wall (depending on program complexity).

Keep in mind that, when you go to college to study software engineering, there are entire subjects dedicated exclusively to software design, where you don’t get to see a single line of code (and, thus, I hated them with a passion ::))

So yeah, it’s an important part of a complete breakfast.

On the other hand:

[quote=“ralphchapin,post:38,topic:42880”]
This is what’s been bothering me since the start of the thread. All that rethoric about the evils of static data, and yet you don’t have a few case studies to throw around?

I’m sorry if I’m too blunt, but this stinks, as I said earlier, of dogmatic zeal.

For whatever reason you’ve come upon the conclusion that static data is evil and have decided to spread the gospel like a regular door to door preacher.

And just like anyone who has internalized a belief, no amount of rebuttals will sway you from either having said beliefs or refraining from proselytizing them, as evidenced by this very thread, so full of perfectly reasoned examples as to why your position doesn’t hold, which are being conveniently ignored.

Again, sorry for my bluntness, but is my experience that, for any debate to be productive, the participants need to be ready to learn, or, in other words, ready to accept their preconceptions might be wrong.

Anything else is just pointless dick waving that helps no one.

And yes, I’m guilty of those very same sins myself, and it revolts me to realize I’m close minded to0, that’s why I devote so much energy to try and help people break out of that mindset.

Again, I’m not saying I “know” how you think, just saying how it feels from my perspective. I’m no mind reader either.

Jeez, so much rant so early in the morning. Need go code some more.

My issue with static is pretty simple. While coding every so often I manage to create a bug. Most bugs I make cause immediate visible issues in Eclipse. Eclipse will suggest a viable repair to the problem half of the time. Probably one in four, Eclipse either gives me a better way to code what I am trying to code, or gives me a correct example of the parameters I am trying to pass. This is great. After I run the program, most of the remaining bugs quickly show up and I can even see what the line of code that blew up is. If I run the code in debug mode, I can explore some objects and values set.

So when I do create a bug, my programming environment almost always catches it. The remaining bugs, the ones that got through the sieve, are usually fairly simple. The are also usually flaws in program logic. My bad! I fix them and the problem is gone. Sometimes the bug fix requires altering a parameter or creating a int somewhere in another class. Rarely does this involve more that three object needing adjustment. Sometimes a bug is worse.

Sometimes I lose a day of programming joy to a long day of frustration while first having to find the cause and second having to adjust a hundred or so objects after finding the bug. In every case so far, these bugs, these horrid bugs that set me back and make me do a huge rewrite, have been static. In every case so far, when I have created the same bug without static being involved, Eclipse has caught the error for me. I don’t know much about other SDKs. Eclipse does not seem to error check static as well as it does Enum (which is a type of static, but I love me some Enum’s.)

Static is not great for unit testing, it may be the same qualities that make static instances a pain to work around for unit testing, make static instances hard for the basic system tests. For me using static, is like working without a net. If I am walking on the ground, or a thick path, static is fine. If I am on a high tight wire, I need a net. So when the code gets complex, I don’t trust static.

I have but two lights by which to guide my feet, the light of experience and the light of experts experience. When I went out to look for examples of how to reduce my dependence on static, I discovered quite a bit of help. Good code examples and good methods. While I had testing using JUnit I really did not have enough grasp of testing to see the holes in my testing that static variables introduced. This was I admit a bit blind of me but since my tests were simple and based on the Eclipse and Java for Total Beginners tutorial videos. http://eclipsetutorial.sourceforge.net/totalbeginner.html I must confess, that my tests are still pretty simple and only approach quality when I am troubleshooting an issue.

While researching that help, I found quite a few brilliant coders who has strong issues with the use of static. Google, ‘Java static evil,’ and you will find slews of much more advanced Java coders than I, that speak fairly freely about the use of static. There are a few static apologists out there as well, and while their arguments in defense of static seem sound enough, they are still couched carefully and they advise limited use of static.

Looking at the arguments for and against the use of static, it does appear that code that is low static, is more likely to be transportable and reusable. Tests of code that is low static are generally simpler and more thorough. Examples of low static code are going to be better examples of object oriented programming. From my experience and from the experience of many others, static bugs can be nightmare fuel. When a bug moves from being one created by poor syntax, math, or logic to being one created by compilation logistics, bug hunting expands the required understanding and attention to minutia by a rather large factor.

Additionally as I started to embark on writing with as little static code as I can, I found another rather huge advantage to reducing ones dependency on the use of static. The ability to make more than one functional instance of an object. My original player object was brim full of static variables. A lot of these did not need to be static, but I figured that static variables might take less clock time for the final code so I left them that way on purpose. It was also loaded with a rather large share of static methods. I could reproduce the player object, but since the player object interacted with just about everything, static was everywhere. The very thought of trying to introduce a functioning second player was horrific. My weak attempt involved copying the player class and making the secondPlayer class. This was bad however since half the critical data in the game was passed by public static variables or methods. After making my code static free, my poor planning for the future was not really an issue. The only complexity was getting the control inputs to control the correct player and that was easy enough to resolve.

As a clarification, what I mean by low static is no static except where I have not come up with a reasonably elegant and clear way to not use static at all. By my best understanding this is a positive step toward writing much better code. It has already made my coding easier.