Пожалуйста, можете ли вы проверить, достаточно ли хорошо написанный мной код соответствует 4 правилам ООП, если есть что-то, что можно улучшить или что-то просто неправильное, я рад изменить (очень новичок в C #, извините, если это ужасно).
В коде реализован «метод Дхонд’та», который представляет собой систему опроса. https://www.bbc.co.uk/news/uk-politics-27187434
ГЛАВНЫЙ
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)
{
// Establish the file path
string filepath = @"C:UsersmatheOneDriveDocumentsAll AssignmentsVoting Systeminputdata.txt";
// Store values in a list of string
List<string> file = File.ReadAllLines(filepath).ToList();
// Puts each party into a list of Party and display Name + Votes
List<Party> partys = new List<Party>();
foreach (string line in file)
{
string[] items = line.Split(',');
Party p = new Party(items[0], Convert.ToInt32(items[1]));
partys.Add(p);
}
// Ask user for thresh hold and also calculate total votes
Console.WriteLine("What is the threshold for partys (%) (round number) ?");
int thresHold = Convert.ToInt32(Console.ReadLine());
// Ask user how many seats they want to allocate
Console.WriteLine("nHow many seats do you want to allocate in total? (round number)");
int seatsCount = Convert.ToInt32(Console.ReadLine());
// Calcutions for Dhon't method
int totalVotes = SumOfVotes(partys);
DisplayPercentageVotes(partys, thresHold, totalVotes);
CalculateDhondt(partys, seatsCount);
DisplayWinningParties(partys);
Console.ReadKey();
}
// Print out all partys and there properties to user
private static void DisplayWinningParties(List<Party> partys)
{
foreach (Party p in partys)
{
if (p.Seats > 0)
{
Console.WriteLine(p);
}
}
}
// Find total votes
private static int SumOfVotes(List<Party> partys)
{
int totalVotes = 0;
foreach (Party p in partys)
{
totalVotes += p.Votes;
}
Console.WriteLine($"nTOTAL No OF COMBINED VOTES FOR ALL PARTIES 2020 : {totalVotes}n");
return totalVotes;
}
// Displays percent of votes for each party
private static void DisplayPercentageVotes(List<Party> partys, int threshold, int totalvotes)
{
// Displays percent of votes for each party
Console.WriteLine($"PARTIES THAT MEET THE {threshold}% INPUTTED THRESHOLD:");
foreach (Party p in partys)
{
if (p.PercentOfVotes(totalvotes) > threshold)
{
Console.WriteLine($"{p.Name} has {Math.Round(p.PercentOfVotes(totalvotes),2)} % of total votes.");
}
}
}
// Method to do the main caclutions 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.Seats += 1;
biggestVote.DivideParty();
// Keep looping through partys and applying dhond't method until all seats are taken
int totalSeatsCount = 0;
while (totalSeatsCount != seatsCount)
{
Party biggestVotes = partys.Aggregate((v1, v2) => v1.NewVotes > v2.NewVotes ? v1 : v2);
biggestVotes.Seats += 1;
biggestVotes.DivideParty();
foreach (Party p in partys)
{
totalSeatsCount += p.Seats;
}
// If we havent reached desired seats count reset the total seats variable
if (totalSeatsCount != seatsCount)
{
totalSeatsCount = 0;
}
}
Console.WriteLine($"nWE HAVE {seatsCount} SEATS ALLOCATED:");
}
}
}
ВЕЧЕРИНКА
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Voting_System
{
class Party
{
// properties for each party
public string Name { get; private set; }
public int Votes { get; private set; }
public int NewVotes { get; set; }
public int Seats { get; set; }
// Constructor for party class
public Party(string name, int votes)
{
Name = name;
Votes = votes;
NewVotes = votes;
}
// 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} Seats: {Seats}";
}
// Applies Dhond't method of division
public void DivideParty()
{
NewVotes = Votes / (1 + Seats);
}
}
}
ФАЙЛ ВВОДА ДАННЫХ
Brexit Party,452321,BP1,BP2,BP3,BP4,BP5;
Liberal Democrats,203989,LD1,LD2,LD3,LD4,LD5;
Labour,164682,LAB1,LAB2,LAB3,LAB4,LAB5;
Conservative,126138,CON1,CON2,CON3,CON4,CON5;
Green,124630,GR1,GR2,GR3,GR4,GR5;
UKIP,58198,UKP1,UKP2,UKP3,UKP4,UKP5;
Change UK,41117,CUK1,CUK2,CUK3,CUK4,CUK5;
Independent Network,7641,INET1,INET2,INET3,INET4,INET5;
Independent,4511,IND1;
1 ответ
В этом обзоре я остановлюсь только на Абстракция и Инкапсуляция потому что два других не применимы в этом сценарии.
Когда мы говорим об ООП, мы обычно имеем в виду четко определенные объекты (с известными обязанностями), которые взаимодействуют друг с другом для решения более серьезной проблемы.
Абстракция
Мы разбиваем исходную задачу на множество более мелких частей. Их можно решить как самостоятельно, так и в сотрудничестве. Если вы реализуете определенный алгоритм, обычно есть координатор / оркестратор, который осуществляет связь между объектами.
Эта роль координатора (логика) может находиться внутри вашего Main
метод:
static void Main(string[] args)
{
var parameters = DhondtMethodAlgorithmParameters.GatherFromConsole();
var inputData = DhondtMethodAlgorithmInput.LoadFromFile(inputFilePath);
var algorithm = new DhondtMethodAlgorithm(parameters, inputData);
var results = algorithm.PerformCalculation();
DisplayResults(results);
}
- Здесь у нас есть 3 разных этапа:
- Сбор данных и преобразование их в желаемую форму
- Настройка алгоритма и его вызов
- Отображение результата расчета
Мы разделили исходную проблему на более мелкие части, каждый из которых имеет четко определенные рамки и ответственность. Мы должны продолжать это разделение, пока не достигнем точки, от которой мы не сможем разделиться дальше.
Это упражнение поможет нам определить объекты и их поведение.
Инкапсуляция
Чтобы правильно использовать инкапсуляцию, мы должны скрыть детали нашей реализации за абстракцией. Другими словами, абстракция должна гарантировать постоянную согласованность данных с точки зрения потребителя.
Например, мы не создаем DhondtMethodAlgorithmParameters
экземпляр, если данные, предоставленные пользователем, искажены. Мы можем досрочно завершить работу с исключением или повторить попытку собрать параметры от пользователя. Когда бы мы ни прошли GatherFromConsole
factory, то мы можем быть уверены, что возвращенный DhondtMethodAlgorithmParameters
содержит только достоверные данные.
То же самое касается LoadFromFile
. Может быть много разных проблем (например, файл не существует, данные повреждены и т. Д.), Которые код может или не может решить. Но с точки зрения абстракции и инкапсуляции всякий раз, когда функция возвращается с проанализированными и проверенными входными данными (DhondtMethodAlgorithmInput
instance), то мы можем быть уверены, что он находится в согласованном состоянии.
С точки зрения алгоритма инкапсуляция может означать, что его входные данные и параметры неизменны после создания. Он не предоставляет никаких методов или членов, с помощью которых потребитель экземпляра алгоритма может изменять базовые данные.
Итак, вкратце:
- Определить объекты и их обязанности << Абстракции
- Выставляйте только те члены, которые необходимы для совместной работы << Инкапсуляция