Я хотел знать, эффективно ли я использовал абстракцию и инкапсуляцию, и если нет, то где я могу улучшить, спасибо. (продолжение моей неработающей предыдущей версии)
ГЛАВНЫЙ
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 ответ
Быстрые замечания:
Всякий раз, когда я создаю
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