How To Get Out Of Main And Reduce Static
Published: 2022-08-31 18:50:26

This is part of a brief series on [Good Habits For Java Programmers](https://dev.to/mbrubin56/good-habits-for-new-java-programmers-1n2).

## In the beginning...
When you write your first program in Java, you encounter the need to have a method with the signature
```java
public static void main(String args[])
```
that serves as the entry point for your program. When you run your program, somehow the Java runtime finds this magic entry point, calls into, and you're off to the races. You'll have to house this method in a class, because that's just how it works.

Then, whatever you learn next, you'll probably be reading and writing short programs that exercise the new Java language bits inside that `public static void main` method. Maybe you're learning how to iterate with a `for` loop, and so read or write a little program to sum up all the evens between 0 and 10.
```java
public static void main(String args[]) {
    int sumOfEvens = 0;
    for (int even = 0; even <= 10; even += 2) {
        sumOfEvens += even;
    }
    System.out.println("The sum of evens from 0 to 10 is " + sumOfEvens);
}
```
It makes sense to keep that code in `main` from a teaching and learning standpoint: it's the simplest place to put the code, and by introducing no additional complexity, the instructor and you get to focus on the other concepts being taught -- say, how a for loop works or how to use a local variable (`sumOfEvens`) or how the algorithm works (adding 2 each time takes us to the next even). I have no problem with this teaching methodology. In fact, I think it's a good idea to leave you to code in `main` while you focus on other things. 

## main is simply an entry point. It is not for modeling your data or problem space.
But let's move forward some number of weeks in your learning. You're starting to learn how to use classes to model a domain, and your assignment is to create a program that asks you to hardcode the length of the side of a square, and print out the area and the perimeter. So you create something like this:
```java
public class Square {
    public static void main(String args[]) {
        float sideLength = 4.0;
        System.out.println("The area of the square is " + sideLength * sideLength);
        System.out.println("The perimiter of the square is " + 4 * sideLength);
    }
}
```
This is a good start. It does what's asked. And it's somewhat nice that the class is named `Square`. The name of the class tells me that we're doing something related to a Square in this class, but we're not really doing much modeling of a Square here. There's no representation of a side's length in the `Square` class and there are no methods that we'd expect on a `Square` class. We _call_ the class `Square`, but since all of the logic for the squarey things we do live in `main`, there actually isn't much that's squarey about this class, other than that the magic Java program entry point, `main`, is packed with a series steps that relate to doing some operations on a square.

Let's dwell on this. The `main` method is not the best place to put your algorithms or to model the problem domain you're modeling: the need for a `main` comes from a contract between the Java runtime and you about how to _start_ your program. That's it. It's how the Java runtime finds a place to start your program, and that is its primary role. It's not for modeling your problem space or writing interesting algorithms: _that_ modeling and those interesting algorithms belong in the distinctive methods and and fields of your classes. Treat `main` solely as an entry point for the Java runtime to find, and put interesting work into your class methods.

## Don't get stuck in the `static` trap
So you learn about class methods and class fields, and you rewrite your `Square` class:
```java
public class Square {
    private static float sideLength = 0.0f;

    public static void main(String args[]) {
        setSideLength(3.2f);
        System.out.println("The area of the square is " + getArea());
        System.out.println("The perimiter of the square is " + getPerimeter());
    }

    public static void setSideLength(float length) {
        sideLength = length;
    }

    public static float getArea() {
        return sideLength * sideLength;
    }

    public static float getPerimeter() {
        return 4 * sideLength;
    }
}
```
This is an improvement. I can see more why this class is named `Square`: it stores a side length, and it has methods to calculate the area and perimeter of a square, using the correct algorithms for them based on a square's side's length.

But there's something funny here. Why is _everything_ `static`? The field `sideLength` is `static`, and so are `getArea` and `getPerimeter`? In my experience, this is not so much a conscious choice, but a carry over from the fact that `main` is `static`. `main` has to be `static` because that's the contract with the Java runtime. And students get stuck then figuring out how to not carry on that `static`. They find that they can't call directly a method named `setSideLength` from their `static` `main` unless `setSideLength` is `static`, too. And then a `static` `setSideLength` can't set a value on that field `sideLength` unless _it's_ `static`.

So there are two big issues here. The first is whether we want all these to be `static`. We don't, and I'll explain why. But more than that, the bigger conceptual issue is that it's not that students have made a _choice_ I disagree with to make the field and the methods of `Square` `static`: it's that students feel that they are forced into it by their `static` `main`.

There's a big difference between `static` fields and non-`static` (instance or member) fields and a big difference between `static` methods and non-`static` (instance or member) methods. The difference I want to focus on for now is that a `static` field is _shared_ among all instances of `Square`s, where each instance of `Square` has its own private copy of non-`static` fields. Conceptually, do we want to make it so that _all_ `Square`s have the side length 3.2 when I set that value, or that just a particular `Square` has a side length of 3.2? Or put more broadly, do we want the `Square` class to model squares as if they all share the same side length, or do we want to allow it to model that different squares have different side lengths? The second, for sure. In that case, we don't want `sideLength` to be `static`.

Okay, so we don't want that field to be `static`, but as I said, most students don't choose to make it `static`: they feel forced into it because of the call to `setSideLength` in their `public void static main`, which itself is seemingly forced into being `static`

The solution is to create an _instance_ of `Square`, and call a method on that:
```java
public class Square {
    private float sideLength = 0.0f;

    public static void main(String args[]) {
        Square square = new Square();
        square.setSideLength(3.2f);
        System.out.println("The area of the square is " + square.getArea());
        System.out.println("The perimiter of the square is " + square.getPerimeter());
    }

    public void setSideLength(float length) {
        sideLength = length;
    }

    public float getArea() {
        return sideLength * sideLength;
    }

    public float getPerimeter() {
        return 4 * sideLength;
    }
}
```
Much better! We now have made `sideLength` a non-static, instance field, and we access it through non-static, instance members. We should probably add a constructor to `Square` that takes an argument for the side length, too, but let's leave it at this.

## Summary
There are two lessons here I want to summarize:
* It's very easy to feel stuck having to make everything in a class `static` because you start calls to it from a `static` method, `public static void main`. But you don't have to be stuck: within your `main`, you can create an _instance_ of your class and then make instance method calls on that instance. Those instance methods can access instance fields. If you _want_ to make a field or method on your class `static` because that's appropriate, too, then great! But you don't have to.  
* `public static void main` serves as a rendezvous point between the Java runtime and your program. It is a contract between you and Java about how to start your program. That's it. It's not the place to put parts of your modeling or algorithms specific to your classes and their desired behaviors.

Here's a related post about where [`main` should live](https://dev.to/mbrubin56/where-should-main-live-244h).