Рубрики
Без рубрики

Обучение программированию в реальном времени – 21 июня 2019 г.

Краткое изложение того, что я узнал в сегодняшнем прямом эфире по кодированию на twitch.tv/jitterted . С тегами todayilearned, java, модульное тестирование, livecoding.

20-й эпизод работы над Quiz down, приложением на базе Java + Spring, которое использует синтаксис, подобный Markdown, для создания тестов по кодированию.

Истории, Реализованные

После нетривиального рефакторинга (см. Никаких голых структур данных ниже), Теперь у меня есть возможность переходить от вопроса к вопросу. Генерация HTML теперь генерирует checked если этот выбор был выбран ранее. Следующий шаг – загрузить ответы пользователя из базы данных и отправить их контроллеру пользовательского интерфейса.

HTML: Используйте отключенный атрибут для кнопки или ссылки

Когда я искал подходящий класс CSS для отображения кнопки как отключенной, я обнаружил, что вместо использования, скажем, класса is-disabled CSS, HTML поддерживает disabled в качестве атрибута для обеих button и ссылка ( ). Например, чтобы показать ссылку как отключенную вместо:

вы бы использовали атрибут disabled следующим образом:

Никаких Голых Структур Данных

Одна из моих эвристик Java-дизайна – это Никаких голых структур данных , что означает обертывание необработанных структур данных ( Список , Карта и т.д.) в типе, чтобы вы могли передавать его по кругу и взаимодействовать с ним таким образом, который имеет смысл с точки зрения домена.

Это похоже на Нет строкового кода эвристика: не используйте String везде, вместо этого используйте типы классов и интерфейсов. Подробности см. здесь и здесь .

При добавлении функции, позволяющей пользователям переходить от вопросов к вопросам, мне нужно было, чтобы выбор, сделанный пользователем, был доступен. Ранее я сохранял эти варианты в виде Set , так как это было просто и не использовалось во многих местах. Однако, как только я нуждался в нем в большем количестве мест (перенося его обратно во внешний интерфейс из базы данных), передача “голого” Set сделала код немного сложнее для чтения и работы. Например, с помощью Set выяснение правильности ответа зависит от типа вопроса ( FIB – это заполнение пробела, а MC – множественный выбор):

  public boolean isCorrectFor(@NonNull Set response) {
    return switch (questionType) {
      case FIB -> correctChoices.containsAll(response);
      case MC -> correctChoices.equals(response);
    };
  }

Это довольно типичный код, но если вы не знакомы со спецификой Набор , возможно, вам придется немного прочитать JavaDoc, чтобы убедиться, что вы правильно его поняли. Заменив его типом Ответа , который инкапсулирует набор , приведенный выше код становится:

  public boolean isCorrectFor(Response response) {
    return switch (questionType) {
      case FIB -> response.matchesAny(correctResponse);
      case MC -> response.allMatch(correctResponse);
    };
  }

Теперь это может быть не таким уж удивительным улучшением (я все еще играю с именованием), но это приводит к следующему шагу (который я еще не сделал) по переносу поведения, специфичного для типа вопроса, в подкласс ответа, например, a Реакция Фибрилляции предсердий и Ответ , который будет выглядеть следующим образом:

  public boolean isCorrectFor(Response response) {
    return response.correctlyMatches(correctResponse);
  }

Полностью делегирование того, как сравниваются ответы, классу, который лучше всего знает, как проводить это сравнение.

В моем обучении и обучении разработчиков Java использование строгих типов и открытых структур данных является причиной большой боли, когда что-то меняется, поэтому всегда старайтесь инкапсулировать строки в объекты значений и заключать ваши структуры данных в свой собственный класс.

Раскрытие актива() в ответе: нарушает инкапсуляцию?

Инкапсуляция Set внутри Response означает, что когда мне нужно отобразить варианты ответа или сохранить их в базе данных (т.Е. Передать ответ через границу домена ) Мне нужно получить эти варианты в виде набора, поэтому в классе Response есть метод

public Set asSet() {
  return Set.copyOf(response); // return a copy of our internal field
}

Это возвращает выбор в виде Set . Я использую это в классе Graded Answer View , чтобы преобразовать его в разделенную запятыми Строку :

  private static String responseAsString(Answer answer) {
    return answer.response().asSet()
                 .stream()
                 .sorted()
                 .collect(Collectors.joining(", "));
  }

Вы могли бы подумать: о нет, это нарушает инкапсуляцию, предоставляя доступ к set , но на самом деле я этого не делаю, потому что я возвращаю копию своего внутреннего хранилища вариантов ответов. Я никогда не раскрываю само поле, поэтому единственный способ изменить внутренние данные Response – это использовать только его методы. Изменение копии не будет иметь никакого эффекта.

Пустые varargs

Я не думаю, что осознавал это раньше, но вызов метода, определенного с помощью varargs (например, create From(String... строки) ) означает, что вы можете вызвать этот метод с без аргументов: create From() , и внутри этого метода аргумент strings

Это означает, что мне не нужно было в специальном случае превращать varargs в пустой набор, потому что вызов Set.of() без аргументов превратится в пустой набор (технически ImmutableCollections.emptySet() начиная с Java 9), что я бы хочу.

Совместные тесты

Большинство моих тестов являются модульными тестами, поскольку они тестируют код в классе, работая с этим классом как можно ближе. Например, Choice class может быть непосредственно протестирован без каких-либо других объектов. Однако Question Transformer не может быть протестирован сам по себе, поскольку его задача в основном заключается в сотрудничестве с более конкретными трансформаторами для выполнения своей работы, т.Е. Его задача – интегрировать или сотрудничать с другими объектами. Это означает, что мне не нужно всесторонне тестировать все поведение всех задействованных классов, просто один или два теста, которые гарантировали бы, что Вопросительный трансформатор правильно//сотрудничает с (в данном случае, распространяя ответ на) другие объекты.

Вы можете увидеть клип из моего стрима, где я делаю это: https://www.twitch.tv/videos/443315061 .

Будьте уверены и настройтесь на мой следующий прямой эфир по кодированию: https://twitch.tv/jitterted .

Хочешь поддержать меня? Станьте меценатом в https://patreon.com/jitterted

Оригинал: “https://dev.to/jitterted/live-coding-learnings-june-21-2019-1ihd”