3
\$\begingroup\$

I am a C# beginner, and I wrote a program that parses the weekly menu of a German delivery service. It works fine and I think the code quality is okay. Can anyone with more experience than me review my code?

using HtmlAgilityPack;
namespace FMReader
{
 internal class Program
 {
  static void Main(string[] args)
  {
        HtmlWeb htmlweb = new HtmlWeb();
        var webpage = htmlweb.Load(@"https://bestellung.fm-teistungen.de/de/menu/56/2022-06-20/2022-06-26/");

        List<Menu> menus1OfTheWeek = new List<Menu>();
        List<Menu> menus2OfTheWeek = new List<Menu>();
        List<string> weekdays = new List<string>() { "Monday", "Tuesday", "Wednesday", "Thursday", "Friday" };

        foreach (var menu1 in webpage.DocumentNode.SelectNodes("//td[@mealid='11']"))
        {
            var currentMenuAsString = menu1.InnerText.Trim();
            Menu currentMenu = new Menu() { Description = currentMenuAsString, MenuType = MenuType.Menu1, Price = 1.5 };
            menus1OfTheWeek.Add(currentMenu);
        }
        foreach (var menu2 in webpage.DocumentNode.SelectNodes("//td[@mealid='12']"))
        {
            var currentMenuAsString = menu2.InnerText.Trim();
            Menu currentMenu = new Menu() { Description = currentMenuAsString, MenuType = MenuType.Menu2, Price = 1.5 };
            menus2OfTheWeek.Add(currentMenu);
        }
        
        foreach (var day in weekdays)
        {
            Console.WriteLine($"{day}");
            var index = weekdays.IndexOf(day);
            menus1OfTheWeek[index].PrintProperties();
            menus2OfTheWeek[index].PrintProperties();
            Console.WriteLine();
            Console.WriteLine();
        }
    }
}

}

Related classes are:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

 namespace FMReader
 {
   public class Menu
   {
      public MenuType MenuType { get; set; }
      public double Price { get; set; }
      public string? Description { get; set; }

      public void PrintProperties()
      {
        Console.WriteLine($"{Description} {Environment.NewLine} Price: {Price} EUR {Environment.NewLine} Menu: {MenuType}");
      }
  }

}

and

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace FMReader
{ 
  public enum MenuType
  {
     Menu1,
     Menu2
  }
}
\$\endgroup\$

2 Answers 2

1
\$\begingroup\$
  1. var webpage = htmlweb.Load(@"https://bestellung.fm-teistungen.de/de/menu/56/2022-06-20/2022-06-26/"); <- That will only works for this specific date. Try to figure out, how to make it more generic.
  2. foreach (var menu1 in webpage.DocumentNode.SelectNodes("//td[@mealid='11']")) <- You are using "magic strings". Save the string in a const and give it a meaningful name.
  3. foreach (var menu2 in webpage.DocumentNode.SelectNodes("//td[@mealid='12']")) <- same here
  4. You're code is redudant. It does many things double. For example: 2 foreach loops with exact the same code.
  5. 2 times Console.WriteLine(); <- better: Console.WriteLine("\n");
  6. PrintProperties() <- That's a bad name for a function. PrintMenuDescriptionWithPrice() would be more meaningful.
  7. public string? Description { get; set; } <- Why is that not in the constructor, if it shouldn't be null?
  8. If you print doubles, you should use padding.
  9. Never ever use doubles or floats for currencies.
  10. The price is again a magic number. Use allways const for constant numbers.
  11. The keynames in MenuType are meaningless. How to figure out what is the difference between them? I have problems to understand why you use enum for the menus.
  12. Why is weekdays a list? Did you plan to add some new weekdays? This would be a good enum.
\$\endgroup\$
2
  • \$\begingroup\$ Well, I tried to wrote the program with your tips. Some things like the more generic link are not possible because the website creates a new link for each week. \$\endgroup\$
    – user260153
    Commented Jun 30, 2022 at 8:50
  • \$\begingroup\$ The link for each week is generated. Or did you think that someone would come up with a random link name every week? If it's random, you can only guess. I firmly believe that there is logic behind it. Is this answer helpful to you? Then you can mark this answer as useful and upvote it. \$\endgroup\$
    – robni
    Commented Jul 8, 2022 at 23:47
1
\$\begingroup\$

Adding on to previous answer:

@robni Says #9. Never ever use doubles or floats for currencies. He forgot to tell you that you would use Decimal instead. Why? double and Single are Base-2 floating points that approximate decimal places which may produce tiny errors, but Decimal is Base-10 floating point that uses exact decimal places.

Menu1 and Menu2 are very generic, relatively non-descript names. I can imagine different menus such as Breakfast, Lunch, Bruch, Dinner, Holiday, or possibly SpecialEvent. Granted, the last 2 would have differing menus such as Valentine's Day, Mother's Day, Thanksgiving, etc. To keep it simple, you may want to consider something like { Breakfast, Dinner } or { Lunch, Dinner }.

\$\endgroup\$
1
  • \$\begingroup\$ I agree with these additions. Even in a tiny app or in a exercise, always avoid doubles or floats and always use Decimal. \$\endgroup\$
    – robni
    Commented Jun 27, 2022 at 21:16