В настоящее время я пытаюсь изучить принципы проектирования SOLID вместе с разработкой, основанной на поведении, но мне довольно трудно понять принцип единой ответственности. Я пытался найти хороший учебник по С#, в котором используется разработка через тестирование, но не смог найти ничего стоящего в этом ключе. Как бы то ни было, потратив несколько дней на чтение, я решил, что лучший способ учиться — на собственном опыте, поэтому я начал создавать небольшое приложение, максимально используя эти принципы.
Это простой калькулятор очков в боулинге. Я решил, что лучше всего работать с самой простой частью, поэтому я начал с уровня мяча (или броска). Прямо сейчас я создал тесты, а также интерфейс и класс для работы с баллами мяча (броска), который гарантирует, что они не являются недействительными, т.е. <10
или >0
. После реализации этого я понял, что класс ball - это просто целое число, допускающее значение NULL, поэтому, возможно, оно мне даже не нужно... но пока оно есть.
Следуя за мячом, я решил, что следующей логичной вещью, которую нужно добавить, будет интерфейс фрейма и класс. Здесь я застрял. Вот где я нахожусь:
namespace BowlingCalc.Frames
{
public interface IFrame : BowlingCalc.Generic.ICheckValid
{
void AddThrow(int? score);
int? GetThrow(int throw_number);
}
}
namespace BowlingCalc.Frames
{
public class Frame : IFrame
{
private List<Balls.IBall> balls;
private Balls.IBall ball;
private int frame_number;
public Frame(Balls.IBall ball, int frame_number)
{
this.ball = ball;
this.frame_number = frame_number;
balls = new List<Balls.IBall>();
check_valid();
}
public void AddThrow(int? score)
{
var current_ball = ball;
current_ball.Score = score;
balls.Add(current_ball);
}
public int? GetThrow(int throw_number)
{
return balls[throw_number].Score;
}
public void check_valid()
{
if (frame_number < 0 || frame_number > 10)
{
throw (new Exception("InvalidFrameNumberException"));
}
}
}
}
Фрейм использует мой ранее реализованный класс мяча посредством внедрения зависимостей, чтобы добавить баллы мяча в кадр. Он также реализует способ возврата счета для любого заданного мяча в кадре.
Что я хочу сделать и где я застрял, так это добавить способ убедиться, что оценка кадра действительна. (На данный момент только простой случай кадров 1-9, где суммарный счет обоих шаров должен быть 10 или меньше. Я перейду к гораздо более сложному случаю кадра 10 позже.)
Проблема в том, что я понятия не имею, как реализовать это ТВЕРДЫМ способом. Я думал добавить логику в класс, но это, похоже, противоречит принципу единой ответственности. Затем я подумал добавить его как отдельный интерфейс/класс, а затем вызывать этот класс в каждом кадре, когда его оценка обновляется. Я также подумал о создании отдельного интерфейса, IValidator
или что-то в этом роде, и реализации его в классе Frame. К сожалению, я понятия не имею, какой из них является лучшим/НАДЕЖНЫМ способом ведения дел.
Итак, что было бы хорошим, НАДЕЖНЫМ способом реализовать метод, который проверяет оценку кадра?
Примечание. Любая критика моего кода приветствуется. Я очень рад научиться создавать лучший код и рад получить любую помощь.