Код-ревью Middle Dart: типы и null-safety обновлено

Код-ревью: работа с null и коллекциями

Вопрос

Функция считает сумму заказа и собирает названия товаров. Найдите проблемы.

double total(Order? order) {
  var sum = 0.0;
  for (var i = 0; i < order!.items.length; i++) {
    sum += order.items[i].price! * order.items[i].qty;
  }
  return sum;
}

List<String> titles(List<Item> items) {
  final result = items.map((i) {
    analytics.log('title ${i.id}');
    return i.title;
  });
  return result.toList() + result.toList();
}

bool sameCart(List<Item> a, List<Item> b) => a == b;

Коротко

Главные темы: ! переносит ошибку в рантайм, map ленивый и пересчитывается на каждом обходе, коллекции сравниваются по ссылке. Деньги в double стандартная претензия на любом ревью.

Что должен найти ревьюер

  1. Ошибкастрока 3
    order! упадёт, если заказа нет. Тип параметра разрешает null, значит нужен явный ответ: вернуть 0 или сделать параметр ненулевым.
  2. Ошибкастрока 4
    price! прячет возможный null в цене: исключение в рантайме. Нужно решить, что делать с товаром без цены, или сделать поле ненулевым в модели.
  3. Ошибкастрока 4
    Деньги в double дают ошибки округления. Хранить в копейках (int) или десятичным типом.
  4. Ошибкастрока 11
    Побочный эффект внутри ленивого map: логирование выполнится при каждом обходе, здесь дважды на каждый товар.
  5. Ошибкастрока 17
    == у списков сравнивает ссылки: два одинаковых по содержимому списка не равны. Нужен listEquals или ListEquality из пакета collection.

Разбор

Главные темы: ! переносит ошибку в рантайм, map ленивый и пересчитывается на каждом обходе, коллекции сравниваются по ссылке. Деньги в double стандартная претензия на любом ревью. Исправленная версия: int total(Order order) => order.items.fold(0, (s, i) => s + i.priceKopecks * i.qty);, логирование отдельным циклом, сравнение через listEquals.

Ответьте сами, а не прочитайте

В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.