11
\$\begingroup\$

I have this program for counting calories. There isn't a whole lot to it yet. It's a moderately sized project, so I'll do my best to make it as short as possible, posting only the main of the program and my global variables. It's a Windows Forms project.

Before anyone tells me, yes, I should fix the global variables. I'd like to take it one step at a time. I was thinking of implementing them locally and passing them around, but of course that will require some code reconstruction, so I was hoping for advice on the structure and overall cleanliness of the code first so I can move on from there.

As a side note, what is the best way to avoid global variables?

Variables:

public struct FoodRelated
{
    //Variabled directly linked to food or the creation of the food table.

    static Dictionary<int, string> foodNameList = new Dictionary<int, string> ();

    public static Dictionary<int, string> FoodNameList {
        get {
            return foodNameList;
        }
        set {
            foodNameList = value;
        }
    }

    static Dictionary<int, float> servingSizeList = new Dictionary<int, float> ();

    public static Dictionary<int, float> ServingSizeList {
        get {
            return servingSizeList;
        }
        set {
            servingSizeList = value;
        }
    }

    static Dictionary<int, float> caloriesPerServingList = new Dictionary<int, float> ();

    public static Dictionary<int, float> CaloriesPerServingList {
        get {
            return caloriesPerServingList;
        }
        set {
            caloriesPerServingList = value;
        }
    }

    static Dictionary<int, string> definersList = new Dictionary<int, string> ();

    public static Dictionary<int, string> DefinersList {
        get {
            return definersList;
        }
        set {
            definersList = value;
        }
    }

    static readonly float totalCaloriesPerDay = 2140f;

    public static float TotalCaloriesPerDay {
        get {
            return totalCaloriesPerDay;
        }
    }

    public static float Calories {
        get;
        set;
    }

}

public struct GlobalVariables
{
    //Misc global variables

    public static int SelectedListItem {
        get;
        set;
    }

    public static bool ExactSearch {
        get;
        set;
    }

    public static bool AddItem {
        get;
        set;
    }

    static readonly DateTime nowDate = DateTime.Now;

    public static DateTime NowDate {
        get {
            return nowDate;
        }
    }

    public static DateTime dateReset;

    static readonly string registryAppenedValue = "SOFTWARE\\Wow6432Node\\";

    public static string RegistryAppenedValue {
        get {
            return registryAppenedValue;
        }
    }

    const string weightWatchingProgram = "Weight Watching Program+";

    public static string registryMainValue = weightWatchingProgram;

    public static Form mainForm {
        get;
        set;
    }
}

Program:

using System;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Windows.Forms;
using Microsoft.Win32;


namespace Weight_Watching_Program
{
/// <summary>
/// Main Window and all tabs.
/// </summary>
public partial class MainForm : Form
{
    public MainForm ()
    {
        //
        // The InitializeComponent() call is required for Windows Forms designer support.
        //
        InitializeComponent ();

        //
        GlobalVariables.mainForm = this;
        Functions.InitializeForms (foodList, calorieRadioButton, timeRadioButton, caloriesLabel, Seperator1, Seperator2, howManyServingsLabel, searchBar, deleteSelectedFoodItemButton,
            clearSearchBarButton, foodNameEditBox, definerEditBox, servingSizeEditBox, caloriesPerServingEditBox, manualCalorieEditBox);

        //
    }

    //MAIN//
    protected internal virtual void SearchBarTextChanged (object sender, EventArgs e)
    {
        if (!string.IsNullOrEmpty (searchBar.Text) && !Equals (searchBar.Text, " ")) {
            Functions.find (0, searchBar.Text, null, GlobalVariables.ExactSearch, foodList);
            return;
        }
        foodList.ClearSelected ();
    }

    protected internal void searchBarFocusGranted (object sender, EventArgs e)
    {
        searchBar.Clear ();
        clearSearchBarButton.Enabled = true;
        Font tempfont = new Font ("Times New Roman", 10f);
        searchBar.Font = tempfont;
    }

    protected internal void clearSearchBarButtonClicked (object sender, EventArgs e)
    {
        searchBar.Clear ();
        clearSearchBarButton.Enabled = false;
        Font tempfont = new Font ("Microsoft Sans Serif", 8.25f, FontStyle.Italic);
        searchBar.Font = tempfont;
        searchBar.Text = "Click Here to Search the Food List";
        searchBar.TextAlign = HorizontalAlignment.Center;
    }

    protected internal virtual void foodListSelectedIndexChanged (object sender, EventArgs e)
    {
        if (foodList.SelectedIndex > -1) {
            GlobalVariables.SelectedListItem = foodList.SelectedIndex;
            howManyServingsLabel.Text = string.Format ("How many {0}s do you plan on eating?", FoodRelated.DefinersList [foodList.SelectedIndex]);
            foodNameEditBox.Text = FoodRelated.FoodNameList [foodList.SelectedIndex];
            foodNameEditBox.TextAlign = HorizontalAlignment.Center;
            servingSizeEditBox.Text = FoodRelated.ServingSizeList [foodList.SelectedIndex].ToString ();
            servingSizeEditBox.TextAlign = HorizontalAlignment.Center;
            definerEditBox.Text = FoodRelated.DefinersList [foodList.SelectedIndex];
            definerEditBox.TextAlign = HorizontalAlignment.Center;
            caloriesPerServingEditBox.Text = FoodRelated.CaloriesPerServingList [foodList.SelectedIndex].ToString ();
            caloriesPerServingEditBox.TextAlign = HorizontalAlignment.Center;
        }
    }

    protected internal void foodListLeaveFocus (object sender, EventArgs e)
    {
        if (Equals (deleteSelectedFoodItemButton.Enabled, true) && foodList.Items.Count <= 0) {
            deleteSelectedFoodItemButton.Enabled = false;
        }
        foodList.ClearSelected ();
    }

    protected internal void foodListEnterFocus (object sender, EventArgs e)
    {
        GlobalVariables.SelectedListItem = foodList.SelectedIndex;
        if (Equals (deleteSelectedFoodItemButton.Enabled, false) && foodList.Items.Count > 0) {
            deleteSelectedFoodItemButton.Enabled = true;
        }
    }

    protected internal void deleteFoodItemFromTable (object sender, EventArgs e)
    {
        Functions.dumpFoodPropertiesList (foodNameEditBox, servingSizeEditBox, caloriesPerServingEditBox, definerEditBox);
        FoodRelated.FoodNameList.Remove (GlobalVariables.SelectedListItem);
        Storage.writeFoodTable ("Text Files\\", "food.table", new string[] {
            null,
            null,
            null,
            null
        }
        );
        Functions.refresh_foodList (foodList);
    }

    protected internal void setFoodPropertiesButtonClicked (object sender, EventArgs e)
    {
        string oldtext = foodNameEditBox.Text;
        Functions.foodPropertiesSwitch (foodList, foodNameEditBox, servingSizeEditBox, caloriesPerServingEditBox, definerEditBox, newItemCheckbox);
        Functions.find (0, oldtext, null, true, foodList);
    }

    protected internal void subtractCalories (object sender, EventArgs e)
    {
        float tempcalories = Functions.modifyCalories (userServingInputTextBox, false);
        bool safetosubtract = false;
        if (FoodRelated.Calories - tempcalories < 0) {
            DialogResult dialogResult = MessageBox.Show ("The amount of calories that are about to be subtracted would put you below your daily limit! Continue?", "You're overeating!", MessageBoxButtons.YesNo, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2);
            switch (dialogResult) {
            case DialogResult.Yes:
                safetosubtract = true;
                break;
            }
        } else {
            safetosubtract = true;
        }
        switch (safetosubtract) {
        case true:
            FoodRelated.Calories = FoodRelated.Calories - tempcalories;
            break;
        }
        Storage.writeRegistry (GlobalVariables.RegistryAppenedValue, GlobalVariables.registryMainValue, false);
        Validation.checkCurrentRadioButton (timeRadioButton, calorieRadioButton, caloriesLabel);
        userServingInputTextBox.Value = 1;

    }

    protected internal void addCalories (object sender, EventArgs e)
    {
        float tempcalories = Functions.modifyCalories (userServingInputTextBox, true);
        if (FoodRelated.Calories + tempcalories > 2140f) {
            ErrorHandler.errorMessageBox ("The amount of calories that you are trying to add would put you over your daily limit, and is not allowed.", addCaloriesButtonMain, 1, false);
        } else {
            FoodRelated.Calories = FoodRelated.Calories + tempcalories;
        }
        Storage.writeRegistry (GlobalVariables.RegistryAppenedValue, GlobalVariables.registryMainValue, false);
        Validation.checkCurrentRadioButton (timeRadioButton, calorieRadioButton, caloriesLabel);
        userServingInputTextBox.Value = 1;
    }

    protected internal void findNextSearchItem (object sender, EventArgs e)
    {
        if (string.IsNullOrEmpty (searchBar.Text) || Equals (searchBar.Text, " ")) {
            return;
        }
        if (GlobalVariables.SelectedListItem >= foodList.Items.Count - 1) {
            Functions.find (0, searchBar.Text, null, GlobalVariables.ExactSearch, foodList);
        } else {
            Functions.find (GlobalVariables.SelectedListItem, searchBar.Text, FoodRelated.FoodNameList [GlobalVariables.SelectedListItem], GlobalVariables.ExactSearch, foodList);
        }
    }

    protected internal void ExactSearchCheckBoxCheckedChanged (object sender, EventArgs e)
    {
        GlobalVariables.ExactSearch = exactSearchCheckBox.Checked;
    }

    protected internal void CalorieRadioButtonCheckedChanged (object sender, EventArgs e)
    {
        Validation.checkCurrentRadioButton (timeRadioButton, calorieRadioButton, caloriesLabel);
    }

    protected internal void TimeRadioButtonCheckedChanged (object sender, EventArgs e)
    {
        Validation.checkDateValidity (GlobalVariables.NowDate, GlobalVariables.dateReset, Storage.checkRegistryValues (GlobalVariables.RegistryAppenedValue, GlobalVariables.registryMainValue));
        Validation.checkCurrentRadioButton (timeRadioButton, calorieRadioButton, caloriesLabel);
    }

    protected internal void NewItemCheckboxCheckedChanged (object sender, EventArgs e)
    {
        Functions.dumpFoodPropertiesList (foodNameEditBox, servingSizeEditBox, caloriesPerServingEditBox, definerEditBox);
        GlobalVariables.AddItem = newItemCheckbox.Checked;
        foodPropertiesButton.Text = newItemCheckbox.Checked ? "Add this new food item" : "Set Food Item Properties";
    }

    protected internal void resetCaloriesButtonClicked (object sender, EventArgs e)
    {
        manualCalorieEditBox.Value = (decimal)FoodRelated.TotalCaloriesPerDay;
    }

    protected internal void zeroOutCaloriesButtonClicked (object sender, EventArgs e)
    {
        manualCalorieEditBox.Value = 0;
    }

    protected internal void manualSubmitButtonClicked (object sender, EventArgs e)
    {
        FoodRelated.Calories = (float)manualCalorieEditBox.Value;
        Storage.writeRegistry (GlobalVariables.RegistryAppenedValue, GlobalVariables.registryMainValue, false);
        Validation.checkCurrentRadioButton (timeRadioButton, calorieRadioButton, caloriesLabel);
    }

    protected internal void RefreshCaloriesTimeButtonClick (object sender, EventArgs e)
    {
        Validation.checkDateValidity (GlobalVariables.NowDate, GlobalVariables.dateReset, Storage.checkRegistryValues (GlobalVariables.RegistryAppenedValue, GlobalVariables.registryMainValue));
        Validation.checkCurrentRadioButton (timeRadioButton, calorieRadioButton, caloriesLabel);
    }

    //MAIN//
}

public static class Validation
{

    //Functions whose primary purpose is verification and validation, but who don't have a more pressing function.

    public static void checkDateValidity (DateTime dateToCompareTo, DateTime dateToCheck, bool firstProgramUse)
    {
        const bool b = true;
        Storage.readRegistry (GlobalVariables.RegistryAppenedValue, GlobalVariables.registryMainValue);
        if (!Equals (DateTime.Compare (dateToCompareTo, dateToCheck), -1) || firstProgramUse == b) {
            if (Equals (Registry.LocalMachine.OpenSubKey (GlobalVariables.RegistryAppenedValue + GlobalVariables.registryMainValue), null)) {
                Registry.LocalMachine.CreateSubKey (GlobalVariables.RegistryAppenedValue + GlobalVariables.registryMainValue);
            }
            Storage.writeRegistry (GlobalVariables.RegistryAppenedValue, GlobalVariables.registryMainValue, b);
        }
    }

    public static void checkCurrentRadioButton (RadioButton timeRadioButton, RadioButton calorieRadioButton, Label caloriesLabel)
    {
        const bool b = true;
        if (Equals (timeRadioButton.Checked, b)) {
            Functions.writeToObject (caloriesLabel, 1);
        } else if (Equals (calorieRadioButton.Checked, b)) {
            Functions.writeToObject (caloriesLabel, 0);
        }
    }

    public static bool Contains (this string source, string toCheck, StringComparison comp)
    {
        return source.IndexOf (toCheck, comp) >= 0;
    }

}

public static class Functions
{
    //      General functions

    public static void writeToObject (Label labelToChange, int objectNumber)
    {
        string[] messages = {
            string.Format ("Calories Left For The Day: {0}", FoodRelated.Calories),
            string.Format ("Calories will reset on {0:MMMM dd} at {1:hh:mm tt}", GlobalVariables.dateReset, GlobalVariables.dateReset)

        };
        var font = new Font ("Microsoft Sans Serif", 12f, FontStyle.Bold);
        Font[] fontStyle = {
            font,
            font

        };
        var middleCenter = ContentAlignment.MiddleCenter;
        ContentAlignment[] objectAlignment = {
            middleCenter,
            middleCenter

        };
        if (Equals (labelToChange, null))
            return;
        labelToChange.Font = fontStyle [objectNumber];
        labelToChange.Text = messages [objectNumber];
        labelToChange.TextAlign = objectAlignment [objectNumber];
    }

    public static void InitializeForms (ListBox foodList, RadioButton calorieRadioButton, RadioButton timeRadioButton, Label caloriesLabel, Label Seperator1,
                                        Label Seperator2, Label howManyServingsLabel, TextBox searchBar, Button deleteSelectedFoodItemButton,
                                        Button clearSearchBarButton, TextBox foodNameEditBox, TextBox definerEditBox, NumericUpDown servingSizeEditBox,
                                        NumericUpDown caloriesPerServingEditBox, NumericUpDown manualCalorieEditBox)
    {

        const BorderStyle fixed3D = BorderStyle.Fixed3D;
        const HorizontalAlignment center = HorizontalAlignment.Center;
        const bool b = true;
        GlobalVariables.mainForm.Text = GlobalVariables.registryMainValue;
        calorieRadioButton.Checked = b;
        caloriesLabel.BorderStyle = fixed3D;
        Seperator1.AutoSize = false;
        Seperator1.BorderStyle = fixed3D;
        Seperator1.Width = 1;
        searchBar.TextAlign = center;
        Seperator2.AutoSize = false;
        Seperator2.BorderStyle = fixed3D;
        Seperator2.Height = 2;
        searchBar.TextAlign = center;
        refresh_foodList (foodList);
        Validation.checkDateValidity (GlobalVariables.NowDate, GlobalVariables.dateReset, Storage.checkRegistryValues (GlobalVariables.RegistryAppenedValue, GlobalVariables.registryMainValue));
        deleteSelectedFoodItemButton.Enabled = false;
        clearSearchBarButton.Enabled = false;
        foodList.SetSelected (0, b);
        GlobalVariables.SelectedListItem = 0;
        howManyServingsLabel.Text = string.Format ("How many {0}s do you plan on eating?", FoodRelated.DefinersList [GlobalVariables.SelectedListItem]);
        foodNameEditBox.Text = FoodRelated.FoodNameList [0];
        foodNameEditBox.TextAlign = center;
        servingSizeEditBox.Text = FoodRelated.ServingSizeList [0].ToString ();
        servingSizeEditBox.TextAlign = center;
        definerEditBox.Text = FoodRelated.DefinersList [0];
        definerEditBox.TextAlign = center;
        caloriesPerServingEditBox.Text = FoodRelated.CaloriesPerServingList [0].ToString ();
        caloriesPerServingEditBox.TextAlign = center;
        Validation.checkCurrentRadioButton (timeRadioButton, calorieRadioButton, caloriesLabel);
        manualCalorieEditBox.Value = decimal.Parse (FoodRelated.Calories.ToString ());
    }

    public static void dumpFoodPropertiesList (TextBox foodNameEditBox, NumericUpDown servingSizeEditBox,
                                               NumericUpDown caloriesPerServingEditBox, TextBox definerEditBox)
    {
        foodNameEditBox.Clear ();
        servingSizeEditBox.Value = 0;
        caloriesPerServingEditBox.Value = 0;
        definerEditBox.Clear ();
    }

    public static void refresh_foodList (ListBox foodList)
    {
        FoodRelated.FoodNameList.Clear ();
        FoodRelated.ServingSizeList.Clear ();
        FoodRelated.CaloriesPerServingList.Clear ();
        FoodRelated.DefinersList.Clear ();
        Storage.readFoodTable ("Text Files\\", "food.table");
        foodList.DataSource = null;
        foodList.Items.Clear ();
        foodList.DataSource = FoodRelated.FoodNameList.Values.ToList ();
        Storage.writeFoodTable ("Text Files\\", "food.table", new string[] { 
            null,
            null,
            null,
            null
        });
    }

    public static void foodPropertiesSwitch (ListBox foodList, TextBox foodNameEditBox, NumericUpDown servingSizeEditBox,
                                             NumericUpDown caloriesPerServingEditBox, TextBox definerEditBox, CheckBox newItemCheckbox)
    {
        if (string.IsNullOrEmpty (foodNameEditBox.Text)) {
            ErrorHandler.errorMessageBox ("Please set a food name value!", foodNameEditBox, 0, true);
            return;
        }
        if (servingSizeEditBox.Value <= 0) {
            ErrorHandler.errorMessageBox ("Please set a serving size value!", servingSizeEditBox, 0, true);
            return;
        }
        if (caloriesPerServingEditBox.Value <= 0) {
            ErrorHandler.errorMessageBox ("Please set a calories per serving value!", caloriesPerServingEditBox, 0, true);
            return;
        }
        if (string.IsNullOrEmpty (definerEditBox.Text)) {
            ErrorHandler.errorMessageBox ("Please set a definer value!", definerEditBox, 0, true);
            return;
        }
        if (Equals (GlobalVariables.AddItem, false)) {
            FoodRelated.FoodNameList [GlobalVariables.SelectedListItem] = foodNameEditBox.Text;
            FoodRelated.ServingSizeList [GlobalVariables.SelectedListItem] = float.Parse (servingSizeEditBox.Text);
            FoodRelated.CaloriesPerServingList [GlobalVariables.SelectedListItem] = float.Parse (caloriesPerServingEditBox.Text);
            FoodRelated.DefinersList [GlobalVariables.SelectedListItem] = definerEditBox.Text;
            Storage.writeFoodTable ("Text Files\\", "food.table", new string[] {
                null,
                null,
                null,
                null
            }
            );
        } else {
            Storage.writeFoodTable ("Text Files\\", "food.table", new [] {
                foodNameEditBox.Text,
                servingSizeEditBox.Text,
                caloriesPerServingEditBox.Text,
                definerEditBox.Text
            }
            );
            newItemCheckbox.Checked = false;
        }
        refresh_foodList (foodList);
    }

    public static float modifyCalories (NumericUpDown userServingInputTextBox, bool add)
    {
        int hour = DateTime.Now.Hour;
        string amPMDefiner = DateTime.Now.ToString ("tt");
        Storage.readRegistry (GlobalVariables.RegistryAppenedValue, GlobalVariables.registryMainValue);
        float tempFloat = FoodRelated.CaloriesPerServingList [GlobalVariables.SelectedListItem] * float.Parse (userServingInputTextBox.Text) / FoodRelated.ServingSizeList [GlobalVariables.SelectedListItem];
        if (hour > 12 && hour < 4 && amPMDefiner.Equals ("am", StringComparison.CurrentCultureIgnoreCase)) {
            float midSnackPenalty = tempFloat / 10;
            if (midSnackPenalty <= 10) {
                midSnackPenalty = 10;
            }
            string appliedSwitch = Equals (add, false) ? "applied" : "subtracted";
            DialogResult dialogResult = MessageBox.Show (string.Format ("A midnight snacking penalty of {0} will be {1} if you continue.", midSnackPenalty, appliedSwitch), "Midnight Snacking Penalty.", MessageBoxButtons.OKCancel, MessageBoxIcon.Information, MessageBoxDefaultButton.Button2);
            switch (dialogResult) {
            case DialogResult.OK:
                if (Equals (add, false)) {
                    return tempFloat + midSnackPenalty;
                }
                return tempFloat - midSnackPenalty;
            default:
                return 0;
            }
        }
        return tempFloat;
    }

    public static void find (int offset, string stringToFind, string stringToAvoid, bool exactSearch, ListBox foodList)
    {
        for (int i = offset; i < foodList.Items.Count; i++) {
            const bool b = true;
            if (Equals (exactSearch, b)) {
                if (Equals (foodList.Items [i].ToString ().Equals (stringToFind, StringComparison.CurrentCultureIgnoreCase), b) &&
                    !foodList.Items [i].ToString ().Equals (stringToAvoid, StringComparison.CurrentCultureIgnoreCase)) {
                    foodList.SelectedIndex = i;
                    break;
                }
            } else {
                if (Equals (foodList.Items [i].ToString ().Contains (stringToFind, StringComparison.CurrentCultureIgnoreCase), b) &&
                    !foodList.Items [i].ToString ().Equals (stringToAvoid, StringComparison.CurrentCultureIgnoreCase)) {
                    foodList.SelectedIndex = i;
                    break;
                }
            }
        }
    }

}

public static class Storage
{

    //      Functions that relate to storage

    public static void readFoodTable (string directory, string file)
    {
        int position = 0;
        String line;
        if (!File.Exists (directory + "food table.txt")) {
            using (StreamReader sr = new StreamReader (directory + file)) {
                int number = 0;
                while (!string.IsNullOrEmpty ((line = sr.ReadLine ()))) {
                    if (line.Contains ("-", StringComparison.CurrentCultureIgnoreCase)) {
                        position++;
                        number = 0;
                    } else {
                        switch (number) {
                        case 0:
                            FoodRelated.FoodNameList.Add (position, line);
                            break;
                        case 1:
                            FoodRelated.ServingSizeList.Add (position, float.Parse (line));
                            break;
                        case 2:
                            FoodRelated.CaloriesPerServingList.Add (position, float.Parse (line));
                            break;
                        case 3:
                            FoodRelated.DefinersList.Add (position, line);
                            break;
                        }
                        number++;
                    }
                }
                sr.Close ();
            }
        } else {
            using (StreamReader sr = new StreamReader (directory + "food table.txt")) {
                int[] number = {
                    0,
                    0,
                    0,
                    0
                };
                while (!Equals ((line = sr.ReadLine ()), null)) {
                    if (line.Contains ("-", StringComparison.CurrentCultureIgnoreCase)) {
                        position++;
                    } else {
                        switch (position) {
                        case 0:
                            FoodRelated.FoodNameList.Add (number [position], line);
                            break;
                        case 1:
                            FoodRelated.ServingSizeList.Add (number [position], float.Parse (line));
                            break;
                        case 2:
                            FoodRelated.CaloriesPerServingList.Add (number [position], float.Parse (line));
                            break;
                        case 3:
                            FoodRelated.DefinersList.Add (number [position], line);
                            break;
                        }
                        number [position]++;
                    }
                }
                sr.Close ();
            }
        }
    }

    public static void writeFoodTable (string directory, string file, string[] addString)
    {
        if (File.Exists (string.Format ("{0}food.table", directory))) {
            File.Delete (string.Format ("{0}food.table", directory));
        }
        string finalstring = null;
        const string seperator = "-------------------------------------------------------------------------\n";
        for (int i = 0; i < FoodRelated.FoodNameList.Count; i++) {
            finalstring = finalstring + FoodRelated.FoodNameList [i] + "\n";
            finalstring = finalstring + FoodRelated.ServingSizeList [i] + "\n";
            finalstring = finalstring + FoodRelated.CaloriesPerServingList [i] + "\n";
            finalstring = finalstring + FoodRelated.DefinersList [i] + "\n";
            finalstring = finalstring + seperator;
        }
        if (!string.IsNullOrEmpty (addString [0])) {
            finalstring = string.Format ("{0}{1}\n", finalstring, addString [0]);
            finalstring = string.Format ("{0}{1}\n", finalstring, addString [1]);
            finalstring = string.Format ("{0}{1}\n", finalstring, addString [2]);
            finalstring = string.Format ("{0}{1}\n", finalstring, addString [3]);
            finalstring = string.Format ("{0}{1}", finalstring, seperator);
        }
        File.WriteAllText (directory + file, finalstring);
    }

    public static void readRegistry (string appendedRegistryValue, string registyValue)
    {
        using (RegistryKey tempKey = Registry.LocalMachine.OpenSubKey (appendedRegistryValue + registyValue, true)) {
            string temp = tempKey.GetValue ("Calories Left for the Day").ToString ();
            FoodRelated.Calories = float.Parse (temp);
            DateTime.TryParseExact (tempKey.GetValue ("Last Used Date").ToString (), new [] { "yyyy MMMMM dd hh:mm:ss tt" }, CultureInfo.InvariantCulture, DateTimeStyles.None, out GlobalVariables.dateReset);
        }
    }

    public static void writeRegistry (string appendedRegistryValue, string registyValue, bool reset)
    {
        const bool b = true;
        if (Equals (reset, false)) {
            using (RegistryKey tempKey = Registry.LocalMachine.OpenSubKey (appendedRegistryValue + registyValue, b)) {
                tempKey.SetValue ("Calories Left for the Day", FoodRelated.Calories.ToString ());
            }
        } else {
            using (RegistryKey tempKey = Registry.LocalMachine.OpenSubKey (GlobalVariables.RegistryAppenedValue + GlobalVariables.registryMainValue, b)) {
                tempKey.SetValue ("Calories Left for the Day", FoodRelated.TotalCaloriesPerDay.ToString (), RegistryValueKind.String);
                tempKey.SetValue ("Last Used Date", GlobalVariables.NowDate.AddDays (1).ToString ("yyyy MMMMM dd hh:mm:ss tt"), RegistryValueKind.String);
            }
        }
    }

    public static bool checkRegistryValues (string appendedRegistryValue, string registyValue)
    {
        if (!Equals (Registry.LocalMachine.OpenSubKey (appendedRegistryValue + registyValue), null))
            return false;
        Registry.LocalMachine.CreateSubKey (appendedRegistryValue + registyValue);
        using (RegistryKey tempKey = Registry.LocalMachine.OpenSubKey (appendedRegistryValue + registyValue, true)) {
            tempKey.SetValue ("Calories Left for the Day", FoodRelated.TotalCaloriesPerDay.ToString (), RegistryValueKind.String);
            tempKey.SetValue ("Last Used Date", GlobalVariables.NowDate.AddDays (1).ToString ("yyyy MMMMM dd hh:mm:ss tt"), RegistryValueKind.String);
        }
        return true;
    }
}
}
\$\endgroup\$
  • 2
    \$\begingroup\$ My preferred way of avoiding global variables is to use dependency injection. \$\endgroup\$ – Nick Udell Dec 16 '14 at 13:17
  • \$\begingroup\$ Welcome to Code Review! Nice first question. \$\endgroup\$ – RubberDuck Dec 16 '14 at 13:19
  • \$\begingroup\$ Thank you both for your input! I will look into dependency injection. \$\endgroup\$ – anonymousman21 Dec 16 '14 at 13:36
  • \$\begingroup\$ Welcome to Code Review! What you can and cannot do after receiving answers. \$\endgroup\$ – Heslacher Dec 16 '14 at 16:51
  • \$\begingroup\$ Thanks for clearing that up. Since I got such informative answers, I will not post a follow up just yet. I'll try to get those pesky global variables out of there and if I still feel the code lacking, will post a follow up with the revised code. \$\endgroup\$ – anonymousman21 Dec 16 '14 at 17:07
10
\$\begingroup\$

Welcome on Code Review!

By convention, your namespace shouldn't contain underscores, you should split them with . if it is neccessary (which isn't in your case I think)

Weight_Watching_Program -> WeightWatchingProgram

Your members don't have the accessibility modifier written, by default it is private but I like to believe it is easier to read when it is always there so other devs don't have to think about if you forgot it or not. (You might say you're the only one on your project, I don't know, though you should always code with the idea that someone else might review your code like.... Right now!)

All your "classes" are declared as struct at the moment, and you shouldn't do it. Structs are for lightweighted (immutable) objects. If you want more information, read this : http://msdn.microsoft.com/en-us/library/0taef578.aspx

Your properties are declared this way :

static Dictionary<int, string> definersList = new Dictionary<int, string> ();

public static Dictionary<int, string> DefinersList {
    get {
        return definersList;
    }
    set {
        definersList = value;
    }
}

In C#, you can use auto-properties to make it a little shorter. Like this :

public static Dictionary<int, string> DefinersList { get; set; }

But then you have a problem, you never set your property. Remember that in "your" way, you create a new instance of Dictionary<int,string> when you declare your variable.

To solve this, you should have a constructor in your class that sets your properties. *Note that this won't work if you keep on using a struct since you can't declare an empty constructor.

public FoodRelated()
{
    DefinersList = new = new Dictionary<int, string> ();
    //Do this for all your properties
}

In my opinion, this method has the advantage of keeping all your declaration in the same place (the constructo) instead of spreading them all across your code!

Your static readonly string should be a const string it it should never change. This StackOverflow answer has some good information about it : https://stackoverflow.com/questions/755685/c-static-readonly-vs-const

Also, it is easier to read your code if you put all the members at the top of your class followed by the properties instead of mixing them up. This SO answer as it covered so I won't repeat it all : https://stackoverflow.com/questions/603758/whats-the-best-way-to-layout-a-c-sharp-class.

In the C# convention, you should put brackets on a new line. My explanation might not be the best so here's an example :

if (true){ //not cool
}

if(true) //Pretty cool
{
}

You wrote way too much code in here : Equals (deleteSelectedFoodItemButton.Enabled, true) a bool is by default... a bool! Consider that Equals returns true if deleteSelectedFoodItemButton.Enabled equals true, you could shorten it to deleteSelectedFoodItemButton.Enabled == true.

But wait, there's more! Since deleteSelectedFoodItemButton.Enabled itself is a boolean, you could shorten it to : deleteSelectedFoodItemButton.Enabled. (Excuse the poor readability of this paragraph!)

if (Equals (deleteSelectedFoodItemButton.Enabled, true) && foodList.Items.Count <= 0)

then becomes :

if (deleteSelectedFoodItemButton.Enabled && foodList.Items.Count <= 0)

You can do the same thing with Equals (deleteSelectedFoodItemButton.Enabled, true) by using the ! operator.

if (Equals (deleteSelectedFoodItemButton.Enabled, false))

becomes :

if (!deleteSelectedFoodItemButton.Enabled) 

In the same idea, if (Equals (labelToChange, null)) could be changed to

if (labelToChange == null)

In your code, you often split the method call from the () with a space, you don't need to do this, it just takes some spaces for nothing. This is what I mean :

Validation.checkCurrentRadioButton /*space here that should be removed*/ (timeRadioButton, calorieRadioButton, caloriesLabel);

I see you use String.IsNullOrEmpty, but have you considered that if I was to enter only white spaces in your code, it would pass this input validation. If it is not the desired behavior, you can use String.IsNullOrWhiteSpace.

Finally, you should not put everything static in a class that isn't static itself. But in this situation, I think that most of your code shouldn't be static. When you put something static, ask yourself if it needs to be used by all instances of your class, in this situation your static code is the whole content of your class, so you shouldn't set this to static. You should declare instances of your class instead.

\$\endgroup\$
  • \$\begingroup\$ Thank you for the help! One thing: when attempting to implement auto-properties (of any get; set;) I get a null reference exception. Can you explain this please? \$\endgroup\$ – anonymousman21 Dec 16 '14 at 14:58
  • \$\begingroup\$ You can go check after the auto-property paragraph to find your answer! \$\endgroup\$ – IEatBagels Dec 16 '14 at 15:06
6
\$\begingroup\$
  • structs should be used if the object it represents is lightweight and immutable, so you should better use classes.

  • methods should be named using PascalCasecasing, see the naming guidelines
    Example: public static void checkDateValidity(DateTime dateToCompareTo, DateTime dateToCheck, bool firstProgramUse)

  • using the using statement is very good. If you are using it with a StreamReader the call to Dispose() which is done by the using is calling Close() internally.

  • using switch ..case is a good thing, but if it can be changed to a simple if..else use the later

        switch (dialogResult) {
        case DialogResult.OK:
            if (Equals (add, false)) {
                return tempFloat + midSnackPenalty;
            }
            return tempFloat - midSnackPenalty;
        default:
            return 0;
        }

can be

    if (dialogResult != DialogResult.OK){
        return 0;
    }

    if (Equals (add, false)) 
    {
        return tempFloat + midSnackPenalty;
    }

    return tempFloat - midSnackPenalty;
  • your indention is somehow off (see above). Using proper indention will increase readability (see my sample above).

  • you should be consistent with the style you use. If you aren't using braces {} for single if statements, which would be a bad habbit IMHO, you should stick to it. But better use them because it makes your code less errorprone.

  • a ListBox can either contain items or can't. So checking the Count for <= 0 is fruitless. Better check Count != 0

\$\endgroup\$
  • \$\begingroup\$ Thanks for the advice! A few things: 1. checking for count on listbox is to make sure the delete button doesn't disable (unless the list is empty). I don't know a better way to check so you're welcome to correct me there. 2. Forgive my novice(ity? Ness?) but what methods in particular are you referring to that need to be PascalCase? 3. Because my format in my IDE won't change spaces, I'll be leaving spaces as-is for the moment. As I work on it more, I'll change my coding style and the rest should simply follow suit. \$\endgroup\$ – anonymousman21 Dec 16 '14 at 15:22
  • \$\begingroup\$ updated my answer \$\endgroup\$ – Heslacher Dec 16 '14 at 15:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.