Proper Java Conventions

This is how my team has been building TimedRobot programs for a few years now, but I was learning about all sorts of fancy stuffs in Java (instance vars, class fields, statics, finals, constructors, super, etc.). Are there any important differences in where variables are initialized and how constructors are used in a TimedRobot program?

Standard Code
public class Robot extends TimedRobot {
  private int num;
  private Victor m_motor;
  private Climber m_climber; // a class we created ; see below

  @Override
  public void robotInit() {
    num = 10;
    m_motor = new Victor(0);
    m_climber = new Climber();
    m_climber.climberInit();
  }
}
public class Climber {
  private Victor m_otherMotor;
  
  public void climberInit() {
    m_otherMotor = new Victor(1);
    // Assume that we know better than to have conflicts from
    //  multiple Victors allocating the same PWM Port resource...
  }
}

Given the above example code, is there any reason we can’t declare and initialize the int, Victor, and Climber in the class rather than in robotInit() like so:?

Single-Line Declaration/Initialization
public class Robot extends TimedRobot {
  private int num = 10;
  private Victor m_motor = new Victor(0);
  private Climber m_climber = new Climber();

  @Override
  public void robotInit() {
    m_climber.climberInit();
  }
}

Further, is there any reason we should be declaring a separate climberInit() method when we could just use the object constructor like so:?

Using Constructor
public class Climber {
  private Victor m_otherMotor;
  
  public Climber() {
    m_otherMotor = new Victor(1);
  }
}

We were basing it off of the use of robotInit() in TimedRobot. But furthermore, can’t we also apply single-line declaring/initializing here?

No Constructor; Just Declare/Initialize
public class Climber {
  private Victor m_otherMotor = new Victor(1);
}

Because that would result in the next code, which is short, simple, and easy to read and understand. I know in the outside world, variables can be initialized with the declaration in Java, but in the TimedRobot file, the comment right before robotInit() is This function is run when the robot is first started up and should be used for any initialization code. So is there a reason to not initialize before robotInit()?

Final Condensed Code
public class Robot extends TimedRobot {
  private int num = 10;
  private Victor m_motor = new Victor(0);
  private Climber m_climber = new Climber();

  @Override
  public void robotInit() {
    // empty and sad
  }
}

Especially because we can reset variables to desired values when calling autonomousInit() and teleopInit(), which always run before autonomousPeriodic() and teleopPeriodic(). Obviously it’s not the same when we come to robotInit() and robotPeriodic().

Has anyone looked into this, or can point me to a prior discussion or documentation of this, or have I gone too far into Java and broken it?

If a member variable’s initialization does not depend on a constructor parameter, it should be initialized where it is declared.

Init functions that do work that could be done in the constructor are usually an antipattern; only do this if the constructor is unreadably long otherwise, and do not name it fooInit. robotInit is useful for things that must be done after everything is instantiated, and should be used only for those things.

1 Like

I’ve stopped using robotInit in our programs because it doesn’t allow for final members to be initialized. My vote would be to remove robotInit, but I think that would probably confuse people.

I think there used to be a reason. If I remember a couple of seasons ago some things weren’t initialized before robotInit(). I believe that has changed now.

There’s no advantage to having a public init method you must call after your constructor. If you are making a Climber class, you really shouldn’t create a public void climberInit() method because that just adds an additional method that you might forget to call when you’re initializing your Climber.

Usually I’ll initialize my motor controller objects in the constructor, just because I’m also configuring them below it. Sometimes I’ll just declare it on the same line, but it depends. I think like @Oblarg said, the general rule is to initialize it in the constructor if it actually needs an argument from the constructor. But IntelliJ doesn’t complain so I usually do whatever unless IntelliJ starts complaining.

If my constructor gets too long, I usually create private init methods that do certain things to separate my code better. But these methods don’t initialize values, they usually configure values that are already initialized. I do this because I really like to use the final keyword.

There’s no “right” way to write a robot program, just guidelines that some of us follow and some of us don’t. There’s also this thread which discusses variable naming conventions: Why do many teams put a "m_" in front of many variable names

1 Like

@Oblarg, thanks for the reply! If I’ve read this correctly, you’d be fine with the last code snippet, i.e.

Last Code Snippet
public class Robot extends TimedRobot {
  private int num = 10;
  private Victor m_motor = new Victor(0);
  private Climber m_climber = new Climber();

  @Override
  public void robotInit() {
    // still empty and sad
  }
}

So then what exactly would you put into robotInit()? Would those be functions to set up objects on the robot like gyros (e.g. m_gyro.calibrate())? On the other hand, is there a reason we couldn’t call that outside of robotInit()?

Calling Method After Initialization
public class Robot extends TimedRobot {
  private int num = 10;
  private Victor m_motor = new Victor(0);
  private Climber m_climber = new Climber();
  private AnalogGyro m_gyro = new AnalogGyro(0);
  m_gyro.calibrate();

  @Override
  public void robotInit() {
    // empty and sad
  }
}

You can’t call methods from outside of a function body, in general, unless they are static methods used as part of a member assignment or part of a static block.

robotInit() is good for initial tasks that you want to be sure are executed after the rest of the framework has been initialized correctly. This is usually a minority of tasks; most can be done in the constructor.

1 Like

@retrodaredevil, thanks for the explanation! Some things that we do in our robotInit() method include inverting motors, setting up SendableChooser options, and starting camera streams. Where do you put those instead?

I’ve also seen the thread on variable naming conventions. I know what it’s like because my team has three programmers, and I can tell who programmed what because we have very distinct styles of naming and coding. :laughing:

You should work on standardizing this. Different conventions across a codebase can lead to disaster when new people have to read the code.

1 Like

Can I at least instantiate an object outside of robotInit() for example, Climber m_climber = new Climber() in public class Robot extends TimedRobot ? Or what if the constructor calls a method, like m_servo.set(180)?

And the different code styles isn’t quite that drastic. I can tell because I know my friends and my code. For example, putting else with the bracket vs. putting it after.

Yes, both will work.

+1. My first standard when working on someone else’s code is always “maintain same”. Don’t induce a new “evil” due to a style manual or a personal preference.

Absolutely highly recommend the formatter built into VS Code - fully functional, customization, a few keystrokes away… easy way to ensure folks at least do their whitespace very similarly.

Keeping the same patterns throughout the code is what enables you to quickly flag “out of pattern” things, which are often bugs.

That being said, the fact that a chunk of the code is repeated in multiple files means it’s “boilerplate”, and could have been created by an automated process (compiler, script, etc.), so no human has to think about it. I think this becomes one of the main arguments for less-boilerplate languages like Kotlin. However, I’m old and crotchety, so I stick with things like Java for now. Get off my lawn ya darn software hippies.

1 Like