Organizing Your FTC Code for Debuggability and Growth

Why Code Organization Matters

Good code organization makes your programs easier to debug, maintain, and expand. In FTC, it's especially important to avoid large, monolithic files. Instead, break your code into small, focused classes and methods.

Modularizing Hardware Initialization in Your OpMode

To keep your OpMode organized and easy to debug, move hardware initialization into a separate function within your OpMode class. This keeps your main logic clean and makes it easier to update or troubleshoot hardware mapping without touching the rest of your code.

Example: Hardware Initialization Function

private DcMotor leftMotor, rightMotor;

private void initHardware() {
    leftMotor = hardwareMap.get(DcMotor.class, "left_drive");
    rightMotor = hardwareMap.get(DcMotor.class, "right_drive");
}

Using the Hardware Initialization Function in Your OpMode

@TeleOp
public class ModularOpMode extends LinearOpMode {
    private DcMotor leftMotor, rightMotor;
    @Override
    public void runOpMode() {
        initHardware();
        waitForStart();
        while (opModeIsActive()) {
            leftMotor.setPower(0.5);
            rightMotor.setPower(0.5);
        }
    }

    private void initHardware() {
        leftMotor = hardwareMap.get(DcMotor.class, "left_drive");
        rightMotor = hardwareMap.get(DcMotor.class, "right_drive");
    }
}

Naming Conventions and File Structure

Use clear, descriptive names for your classes, methods, and variables. Organize your files so that related code is grouped together. This helps you and your teammates find and fix bugs faster.

Tips for Good Code Organization

  • Keep each file focused on one purpose (e.g., hardware, drive logic, sensors).
  • Use consistent naming conventions.
  • Document your code with comments and JavaDoc.
  • Avoid duplicating code—use helper methods or classes instead.
  • Review and refactor your code regularly.

Documenting Your Code

Comments and documentation help you remember your logic and make it easier for others to help debug. Use JavaDoc for methods and classes, and add inline comments for tricky logic.

JavaDoc Example

/**
 * Sets the power for both drive motors.
 * @param power The power level (-1.0 to 1.0)
 */
public void setDrivePower(double power) {
    leftMotor.setPower(power);
    rightMotor.setPower(power);
}

Using Version Control for Debugging

Version control lets you track changes and revert to working code. While OnBot Java doesn't have built-in Git, you can still keep backups and use comments to mark changes. For more on version control in FTC, see FTC Docs: Programming Resources.

Practice: Refactor a Monolithic OpMode

Take a long OpMode file and break it into at least two classes (e.g., hardware and logic). Add comments and JavaDoc to your methods. Test that your code still works.

  • Identify sections of code that can be moved to helper classes.
  • Refactor the code and update your OpMode to use the new classes.
  • Add JavaDoc and comments to explain your logic.
// Example of a monolithic OpMode (all logic and hardware in one class)
@TeleOp
public class MonolithicOpMode extends LinearOpMode {
    private DcMotor leftMotor, rightMotor;
    private Servo clawServo;
    @Override
    public void runOpMode() {
        leftMotor = hardwareMap.get(DcMotor.class, "left_drive");
        rightMotor = hardwareMap.get(DcMotor.class, "right_drive");
        clawServo = hardwareMap.get(Servo.class, "claw_servo");
        waitForStart();
        while (opModeIsActive()) {
            double leftPower = -gamepad1.left_stick_y;
            double rightPower = -gamepad1.right_stick_y;
            leftMotor.setPower(leftPower);
            rightMotor.setPower(rightPower);
            if (gamepad1.a) {
                clawServo.setPosition(1.0);
            } else if (gamepad1.b) {
                clawServo.setPosition(0.0);
            }
            telemetry.addData("Left Power", leftPower);
            telemetry.addData("Right Power", rightPower);
            telemetry.addData("Claw Position", clawServo.getPosition());
            telemetry.update();
        }
    }
}

Further Reading Resources

Open full interactive app