Создание системы Dhond’t на C # путем чтения из файла данных

Я хотел знать, эффективно ли я использовал абстракцию и инкапсуляцию, и если нет, то где я могу улучшить, спасибо. (продолжение моей неработающей предыдущей версии)

ГЛАВНЫЙ

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

namespace Voting_System
{
    class Program
    {  
        static void Main(string[] args)
        {
            // Puts each party into a list of Party and display Name + Votes
            Console.WriteLine("Type the name of the file your data is in with the .txt extension : ");
            string data = Console.ReadLine();

            // Make list of party classes to hold all parties from data.txt file
            List<Party> partys = FindData(data);

            // Ask user for thresh hold and also calculate total votes
            Console.WriteLine("What is the threshold for partys (%) (round number) ?");
            int threshHold = Convert.ToInt32(Console.ReadLine());

            // Calcutions for Dhon't method
            var votesAndSeats = GetSumVotesAndSeats(data);
            DisplayPercentageVotes(partys, threshHold, votesAndSeats.Item1);
            CalculateDhondt(partys, votesAndSeats.Item2);
            DisplayWinningParties(partys);

            Console.ReadKey();
        }

        // takes input of the name of the data file and outputs the required data
        private static List<Party> FindData(string exactpath)
        {
            // Store values in a list of string
            List<string> file = File.ReadAllLines(exactpath).ToList();
            List<Party> partys = new List<Party>();
            foreach (string line in file.Skip(3))
            {
                string[] items = line.Split(',');
                Party p = new Party(items[0], Convert.ToInt32(items[1]), items.Skip(2).ToArray());
                partys.Add(p);
            }
            return partys;
        }

        // Print out all partys that have seats and there properties to console
        private static void DisplayWinningParties(List<Party> partys)
        {
            foreach (Party p in partys)
            {   
                if (p.SeatsAmount > 0)
                {
                    Console.WriteLine(p);
                }
            }
        }

        // Find total votes for all parties and number of seats to be allocated
        private static (int,int) GetSumVotesAndSeats(string exactpath)
        {
            List<string> file = File.ReadAllLines(exactpath).ToList();
            int totalElectionVotes = Convert.ToInt32(file[2]);
            int numOfSeatAllocation = Convert.ToInt32(file[1]);

            return (totalElectionVotes, numOfSeatAllocation);
        }

        // Displays percent of votes for each party that meets the threshold
        private static void DisplayPercentageVotes(List<Party> partys, int threshold, int totalvotes)
        { 
            Console.WriteLine($"Parties that meet the {threshold}% threshold :");
            foreach (Party p in partys.ToList())
            {
                if (p.PercentOfVotes(totalvotes) > threshold)
                {
                    Console.WriteLine($"{p.Name} has {Math.Round(p.PercentOfVotes(totalvotes), 2)}" +
                                      $" % of total votes.");
                }
                else
                {
                    partys.Remove(p);
                }
            }
        }

        // Method to do the main calculations of the Dhon't method
        private static void CalculateDhondt(List<Party> partys, int seatsCount)
        {
            // Find intial party with highest votes
            Party biggestVote = partys.Aggregate((v1, v2) => v1.Votes > v2.Votes ? v1 : v2);
            biggestVote.SeatsAmount += 1;
            biggestVote.DivideParty();

            // Keep looping through partys and applying dhond't method until all seats are taken
            int totalSeatsCount = 0;
            while (totalSeatsCount != seatsCount)
            {
                // If we havent reached desired seats count reset the total seats variable
                totalSeatsCount = 0;

                Party biggestVotes = partys.Aggregate((v1, v2) => v1.NewVotes > v2.NewVotes ? v1 : v2);
                Console.WriteLine(biggestVotes);
                biggestVotes.SeatsAmount += 1;
                biggestVotes.DivideParty();

                foreach (Party p in partys)
                {
                    totalSeatsCount += p.SeatsAmount;
                }
            }
            Console.WriteLine($"n{seatsCount} seats allocated :");
        }
    }
}

ВЕЧЕРИНКА

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

namespace Voting_System
{
    class Party
    {
        // Fields
        private string _name = "unknown";
        private int _votes;
        private string[] _seatsCodeValues;
        private int _newVotes;
        private int _seatsAmount;

        // Properties 
        public string Name
        {
            get { return _name; }
            private set { _name = value; }
        }

        public int Votes
        {
            get { return _votes; }
            private set { _votes = value; }
        }

        public string[] SeatsCodeValues
        {
            get { return _seatsCodeValues; }
            private set { _seatsCodeValues = value; }
        }

        public int NewVotes
        {
            get { return _newVotes; }
            private set { _newVotes = value; }
        }

        public int SeatsAmount
        {
            get { return _seatsAmount; }
            set { _seatsAmount = value; }
        }

        // Constructor for party class 
        public Party(string name, int votes, string[] seatsCodeValues)
        {
            Name = name;
            Votes = votes;
            NewVotes = votes;
            SeatsCodeValues = seatsCodeValues;
        }


        // Returns percentage of votes for your party
        public double PercentOfVotes(double totalVotes) => (Votes / totalVotes) * 100;

        // When ever you print the object of this class return this
        public override string ToString()
        {
            return $"Name: {Name}, Votes: {Votes}, {SeatsAmount} " +
                   $"Seats Values : {string.Join(",", SeatsCodeValues.Take(SeatsAmount))}";
        }

        // Applies Dhond't method of division 
        public void DivideParty()
        {
            NewVotes = Votes / (1 + SeatsAmount);
        }
    }
}
```

1 ответ
1

Быстрые замечания:

  • Всякий раз, когда я создаю Console app, первое, что я делаю, это добавляю Runner класс с public void Execute() метод, а затем вызовите его из Main() из Program учебный класс. И тогда вся логика в том, что Runner учебный класс.

  • Ваш Program Класс состоит из 100+ строк и содержит различные методы. Каждый из них делает что-то довольно специфическое, но я бы фактически переместил некоторые из них в свой собственный класс (например, те, которые читают данные файла).

  • Следуйте рекомендациям Microsoft по именованию WRT. Например exactpath сложное слово, поэтому должно быть exactPath. Вы также не должны использовать символы, отличные от буквенно-цифровых, например подчеркивание в Voting_System.

  • Используйте описательные имена. exactPath мне кажется странным: есть ли inexactPath? data в string data = Console.ReadLine(); неправильно на многих уровнях: это слишком общее название и не описывает, что это такое. FindData слишком общее название метода.

  • Console.WriteLine("Type the name of the file your data is in with the .txt extension : "); кажется, требует, чтобы пользователь набрал файл имя, но ясно, что вы ожидаете дорожка. Это большая разница.

  • Комментарии должны быть редкими и рассказывать мне, почему, а не что. Например // Store values in a list of string не сообщает мне ничего, что ваш код еще не сказал мне. То же самое для // Constructor for party class и большинство других комментариев.

  • Используйте правильный английский. partys неправильно, это parties.

  • Не сокращайте без нужды. Пока «р» в foreach (Party p in partys) не так уж и плохо, и контекст дает мне достаточно информации, все же было бы лучше просто использовать слово party.

  • DisplayPercentageVotes делает больше, чем указано в названии: он также изменяет содержимое partys. Таким образом должно быть два метода.

  • Почему Party есть эти геттеры / сеттеры «старого стиля»?

  • Многие из ваших foreach циклы можно заменить вызовами LINQ.

  • Вы не проверяете ввод пользователя. Вы не проверяете, существует ли указанный пользователем путь к файлу, вы не проверяете, правильно ли структурировано содержимое файла, …

  • Я ценю помощь, но многие вещи, такие как mlinq и обработка ошибок, не ожидались нами, так как это наш первый проект в нашем модуле C #.

    — Mj _

  • Что вы имеете в виду, говоря о создании класса только для считываемых данных файла? и когда вы говорите о методах получения и установки в старом стиле, следует ли мне сделать что-то вроде public string Name {get; частный набор; } вместо? встретит ли это столпы инкапсуляции и абстракции?

    — Mj _

  • Альтернативный способ инкапсуляции: dotnettutorials.net/lesson/encapsulation-csharp , но, честно говоря, я давно не видел такого кода в «реальной жизни». Если ваш учитель требует, чтобы вы написали его таким образом (с частными полями и т. Д.), Вам нужно будет это сделать, но это не тот стиль кодирования, который вы часто видите в наши дни (за исключением WPF и Unity и т. Д.).

    — BCdotWEB

  • Хорошо, спасибо, также можете ли вы объяснить, почему мне нужно было создать класс для сегментов кода обработки файлов?

    — Mj _

  • Я бы так поступил по простой причине: мне не нравятся длинные файлы классов, в которых мне нужно переходить от метода к методу. Иногда это неизбежно, но по возможности я стараюсь перенести конкретную логику в отдельный файл класса. Я бы, например, перешел к чтению файла и преобразованию его содержимого в список настраиваемых объектов.

    — BCdotWEB

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *