I am new to programming and was working on a project that calculates an entire "diet plan" as well as a projected weight goal for each week.
There are three objects that all have methods called on them to print the details for their weight loss plan. Each "person" object contains a name, a current body weight, desired weeks for program, and their current maintenance calories.
The code works how I want it to in terms of the actual output. My main issue is with the projected weight per week method from the program. The goal of this method is to store the weights into an array and print them in order.
Each week the person should lose 1 pound. So, after each week the expected weight should go down 1 pound from the last week.
As a new programmer I am looking for ways to improve the performance of this method. As of right now I am using separate .add(); statements from the array list class. This method also only prints out 12 weeks of expected weights. So if the weeks variable in the object is anything higher than 12 then everything after the 12th week does not get printed.
I was hoping someone could critique the "projectedWeightPerWeek" method. My gut tells me I should be able to use some type of loop to add each weight without using tons of add statements. Additionally, I would think the same would be true for the print statements.
My goal is to be able to minimize the number of .add() statements and print the correct number of expected weights based of the number of weeks with the correct week label.
Here is the program:
https://pastebin.com/hSiSNs2r (I didn't know if the link would be better to use)
import java.util.ArrayList;
public class calculations {
public static void main(String[] args) {
new calculations("Caleb", 185.0, 12, 3200);
calculations.userGreet();
calculations.getCuttingCalories();
calculations.getCarbs();
calculations.getFats();
calculations.getProtien();
calculations.projectedWeightPerWeek();
new calculations("kyle", 190.0 , 16, 3400);
calculations.userGreet();
calculations.getCuttingCalories();
calculations.getCarbs();
calculations.getFats();
calculations.getProtien();
calculations.projectedWeightPerWeek();
new calculations ("Christian", 182, 12, 3200);
calculations.userGreet();
calculations.getCuttingCalories();
calculations.getCarbs();
calculations.getFats();
calculations.getProtien();
calculations.projectedWeightPerWeek();
}
static String name;
static double expextedWeight;
static double startingWeight;
static int weeks;
static double protien;
static double carbs;
static double fats;
static int cuttingC;
static int maintC;
calculations(String userName, double sw, int length, int MC) {
name = userName;
startingWeight = sw;
weeks = length;
maintC = MC;
}
static void userGreet() {
System.out.println("Hello " + name +" here are your future diet constraints:\n");
}
static void getCuttingCalories() {
cuttingC = maintC -400;
System.out.println("you need to eat " + cuttingC + " calories");
}
static void getProtien() {
double protien = cuttingC * 0.26428571428 / 4;
int protienReal = (int) Math.round(protien);
System.out.println("you need to eat " +protienReal + " grams of protien each day.");
}
static void getCarbs() {
double carbs = cuttingC * 0.43035714285 / 4;
int carbsReal = (int) Math.round(carbs);
System.out.println("You need to eat " + carbsReal + " grams of carbs each day.");
}
static void getFats() {
double fats = cuttingC * 0.305 / 9;
int fatsReal = (int)Math.round(fats);
System.out.println("You need to eat " +fatsReal+ " grams of fat each day.");
}
static void projectedWeightPerWeek(){
ArrayList <Double> weightsCalc = new ArrayList<Double>();
weightsCalc.add(startingWeight * 1);
weightsCalc.add(startingWeight - 1);
weightsCalc.add(startingWeight - 2);
weightsCalc.add(startingWeight - 3);
weightsCalc.add(startingWeight - 4);
weightsCalc.add(startingWeight - 5);
weightsCalc.add(startingWeight - 6);
weightsCalc.add(startingWeight - 7);
weightsCalc.add(startingWeight - 8);
weightsCalc.add(startingWeight - 9);
weightsCalc.add(startingWeight - 10);
weightsCalc.add(startingWeight - 11);
weightsCalc.add(startingWeight - 12);
System.out.println("At the start you should weigh: " +weightsCalc.get(0) +" pounds");
System.out.println("After week one you should weigh: " +weightsCalc.get(1) +" pounds");
System.out.println("After week two you should weigh: " +weightsCalc.get(2) +" pounds");
System.out.println("After week three you should weigh: " +weightsCalc.get(3) +" pounds");
System.out.println("After week four you should weigh: " +weightsCalc.get(4) +" pounds");
System.out.println("After week five you should weigh: " +weightsCalc.get(5) +" pounds");
System.out.println("After week six you should weigh: " +weightsCalc.get(6) +" pounds");
System.out.println("After week seven you should weigh: " +weightsCalc.get(7) +" pounds");
System.out.println("After week eight you should weigh: " +weightsCalc.get(8) +" pounds");
System.out.println("After week nine you should weigh: " +weightsCalc.get(9) +" pounds");
System.out.println("After week ten you should weigh: " +weightsCalc.get(10) +" pounds");
System.out.println("After week eleven you should weigh: " +weightsCalc.get(11) +" pounds");
System.out.println("After week twelve you should weigh: " +weightsCalc.get(12) +" pounds \n");
}
}
1 Answer 1
Pedantic
You make at least two spelling mistakes. You consistently misspell protein and also expextedWeight
should be expectedWeight
.
Prefer interfaces over implementations as types
ArrayList <Double> weightsCalc = new ArrayList<Double>();
could be
List<Double> weightsCalc = new ArrayList<>();
Then if you want to change the implementation while retaining the interface, you only have to change it one place.
Naming
Your method names are not idiomatic. userGreet
would more commonly be greetUser
. projectedWeightPerWeek
should be projectWeightsByWeek
. Because methods actively do things and should be represented by verbs (with objects in these two cases). Objects and classes should be nouns. And none of your get
methods are actually getters. They display the information rather than retrieving it. So go ahead and call them displayWhatever
instead. Or see the next section for another option.
We would also normally give classes initially-capitalized names like Calculations
. Or in this case, perhaps Diet
.
Separation of concerns
One of the SOLID principles is single responsibility. This means that your class should only have one reason to change. But in your case, you are mixing data and output. One solution would be to break these into two classes. One would handle display and the other would handle the data. This is much more flexible, as you can retrieve the data and then transform it before displaying it. Currently, you would have to add new methods to do that. But if you return data, you could do
System.out.println("You need to eat " + calculations.calculateProtein() + " grams of protein each day.");
Note that I also renamed getProtien
to calculateProtein
. Again, a getter just returns a value. What you are doing is calculating the value. So call it what it does.
Indentation
Your indentation is non-standard. As a general rule, put things at the same scope at the same indentation. Add indentation when entering a new scope. Remove indentation when leaving a scope. Do not add indentation otherwise.
The compiler won't care (at least not in Java; it would in Fortran or Python), but it makes it easier to read if you follow the normal conventions.
Don't use static
for object variables and methods
You made your object variables static
. The static
keyword means that they are the same for every object. So when you make a new object, you are writing over the values of the previous object. If you remove the static
, then you can have two separate objects with different values.
Then assign your constructors. E.g.
Calculations caleb = new calculations("Caleb", 185.0, 12, 3200);
Or even better
Calculations[] people = {
new Calculations("Caleb", 185.0, 12, 3200),
new Calculations("Kyle", 190.0 , 16, 3400),
new Calculations("Christian", 182, 12, 3200)
};
Which you would use like
people[0].greetUser();
And this is another place where a for
loop would be helpful.
Do specify a visibility
Many of your methods and properties (object/class variables) do not have a visibility specified. As a result, they will use the default of package-protected. This means that they are visible in the same package but not outside the package. While there are reasons to use that visibility, it is rare. Far more common is to make methods public
and properties either protected
or private
. I would suggest that while you are learning, that you simply make all your methods public
and all your properties private
. When you find that limiting, you can learn more about it and make a more informed choice.
So
private int maintC;
public Calculations(String userName, double sw, int length, int MC) {
Later, you can learn more about when you might make a method private
or protected
or make a property public
or protected
. And if you ever have a reason to use package protected, you can learn how to indicate that that is a deliberate choice.
for
loops
Your code could be much shorter with for
loops. E.g.
String[] weeks = {"one", "two", "three", "four", "five", "six",
"seven", "eight", "nine", "ten", "eleven", "twelve"};
int target = (int)startingWeight;
System.out.println("At the start you should weigh: " + target + " pounds");
for (String week : weeks) {
target -= 1;
System.out.println("After week " + week + " you should weigh: " + target + " pounds");
}
System.out.println();
-
1\$\begingroup\$ Thank you so much for the feedback. It was VERY helpful \$\endgroup\$Caleb Wallace– Caleb Wallace2022年05月30日 04:07:18 +00:00Commented May 30, 2022 at 4:07