Добро пожаловать в Stack Overflow и сообщество Ruby!
Есть ли лучший способ сделать это?
Когда дело касается программирования, всегда есть другие способыделать вещи, иногда считается лучше, иногда хуже, это зависит от конкретного случая.Хорошо изучать лучшие практики и применять их на практике до тех пор, пока они не станут вашим стандартным способом кодирования.Как и многие вещи в жизни, в качестве руководящих указаний используются лучшие практики, а не правила.
В вашем случае все было хорошо, пока вы не захотели импортировать код для повторного его использования в другом проекте, поэтому выбранная вами абстракция больше не работает, это происходит, и это нормально, пришло время провести его рефакторинг!
Если посмотреть на ваш код в данный момент, класс вопросов - это просто прославленная структура данных, вы можете достичь чего-то похожего с помощью хеша { prompt: '', answer: ''}
, означающего, что вашВ классе есть часть данных, но нет логической части, мое первое предложение - переместить логику проверки ответов в метод класса Question.
class Question
attr_reader :prompt, :correct_answer
def initialize(prompt, correct_answer)
@prompt = prompt
@correct_answer = correct_answer
end
def score(answer)
return 1 if answer == @correct_answer
return 0
end
end
Преимущество этого подхода заключается в том, что в конечном итоге вы можете решить сделатьтакие вещи, как «этот вопрос стоит 2 балла», «когда пользователь вводит (several spaces)c(several spaces)
Я хочу трактовать как просто c
», и это будет место для реализации этой логики.
Следующая вещь, которую выМожно подумать о введении нового класса, который представляет собой тест / тест / экзамен.Этот класс отвечает за выполнение логики, реализованной вами в run_test
.При этом вы сможете импортировать и повторно использовать свой код.Записывая этот класс, подумайте о возможных вещах, которые вы можете сделать с помощью теста, можете ли вы «начать его», «закончить его», «ответить на вопрос», «перейти к следующему вопросу» и так далее.
В программировании очень часто избегают соединения ввода-вывода и вашего кода, в данном случае ввода-вывода это puts question.prompt
и answer = gets.chomp()
.
Можно ожидать, что следующий API будет работать, но онна самом деле зависит от ваших предпочтений и от того, чего вы пытаетесь достичь:
def run_test(quiz)
quiz.questions.each do |question|
puts question.prompt
answer = gets.chomp()
quiz.answer(question, answer)
end
puts ("You got #{quiz.score} / #{quiz.maximum_score}")
end
Вы видите, что при таком подходе основной фокус кода заключается в циклическом рассмотрении вопросов и доказательстве ввода-вывода, если бы вы создавали веб-страницу, вы могли быпо-прежнему используйте классы викторины и вопроса, что изменится в том, как вы подсказываете вопрос и как получаете ответ.Что вы скрывали от потребителей вашего класса, так это то, как вы оцениваете тест, каков максимальный балл, каков текущий балл у человека?
Когда я составлял этот код, у меня были другие мысли: - должен ли я иметь start
метод, который сбрасывает счет до 0?- если я прячу вопросы за методом next_question
, таким образом, я могу вернуть nil
, если больше не осталось вопросов, при текущем подходе можно было бы ответить на тест несколько раз, выполнив run_test
несколько раз и получив все добавленныеоценка «У тебя 23/10».
Надеюсь, это даст тебе представление о том, что ты мог бы сделать дальше.