Климат кода - слишком сложная ошибка
Я использую кодовый климат в одном из моих проектов, и у меня появляется ошибка из-за "слишком сложного" кода. Я не уверен, как сделать код, который он вызывает менее сложным? Вот:
Метод:
def apply_json
{
total_ticket_count: payment_details.tickets.count,
subtotal: payment_details.subtotal.to_f,
discount: payment_details.discount.to_f,
fees: payment_details.fees_total.to_f,
total: payment_details.total_in_dollars.to_f,
coupon: {
amount: payment_details.coupon.amount,
type: payment_details.coupon.coupon_type,
name: payment_details.coupon.name,
valid: payment_details.coupon.valid_coupon?,
}
}
end
Это просто JSON, который я спрятал в модели. Все на моей ветке велика, ожидайте этого? Я не уверен, что делать? Любые идеи о том, как я могу сделать это менее сложным?
4 ответа
Мне было бы наплевать, если Code Climate считает что-то слишком сложным, но на самом деле это легко понять. Code Climate должен помочь вам писать лучше, легко читаемый код. Но это не обеспечивает жестких правил.
Если вы действительно хотите что-то изменить, вы можете переместить поколение coupon
подчиненный хеш Coupon
модель, потому что это зависит только от значений, предоставленных coupon
ассоциации:
def apply_json
{
total_ticket_count: payment_details.tickets.count,
subtotal: payment_details.subtotal.to_f,
discount: payment_details.discount.to_f,
fees: payment_details.fees_total.to_f,
total: payment_details.total_in_dollars.to_f,
coupon: payment_details.coupon.as_json
}
end
# in coupon.rb
def as_json
{
amount: amount,
type: coupon_type,
name: name,
valid: valid_coupon?
}
end
Подобный рефакторинг можно сделать с payment_details
но неясно, откуда этот атрибут и является ли он ассоциированной моделью.
Пожалуйста, просто игнорируйте предупреждения о сложности.
Они введены в заблуждение.
Эти предупреждения основаны на фальшивой науке.
Цикломатическая сложность была предложена в 1976 году в академическом журнале и увы принята производителями инструментов, потому что ее легко реализовать.
Но это оригинальное исследование ошибочно.
Оригинальный документ предлагает простой алгоритм для вычисления сложности для кода на Фортране, но не дает никаких доказательств того, что вычисленное число фактически соотносится с читабельностью и понятностью кода. Нада, ниенте, ноль, пшик.
Вот их аннотация
Эта статья описывает теоретико-графическую меру сложности и показывает, как ее можно использовать для управления и контроля сложности программы. Сначала в статье объясняется, как применяются концепции теории графов, и дается интуитивное объяснение концепций графов в терминах программирования. Затем представлены контрольные графы нескольких реальных программ на Фортране, чтобы проиллюстрировать корреляцию между интуитивной сложностью и теоретико-графической сложностью. Затем доказывается несколько свойств теоретико-графической сложности, которые показывают, например, что сложность не зависит от физического размера (сложение или вычитание функциональных операторов оставляет сложность неизменной), а сложность зависит только от структуры решения программы.
Также обсуждается вопрос использования неструктурированного потока управления. Дана характеристика неструктурированных графов управления и разработан метод измерения "структурированности" программы. Связь между структурой и сводимостью иллюстрируется несколькими примерами.
В последнем разделе этой статьи рассматривается методология тестирования, используемая в сочетании с мерой сложности; определена стратегия тестирования, которая диктует, что программа может допустить определенный минимальный уровень тестирования или программа может быть структурно сокращена
Источник http://www.literateprogramming.com/mccabe.pdf
Как вы можете видеть, анекдотические свидетельства даны только "для иллюстрации корреляции между интуитивной сложностью и теоретико-графической сложностью", и единственное доказательство состоит в том, что код может быть переписан так, чтобы иметь более низкое число сложности, как определено этой метрикой. Это довольно бессмысленное доказательство для метрики сложности и очень распространенное для качества исследований того времени. Этот документ не будет опубликован по сегодняшним стандартам.
Авторы статьи не провели исследования пользователей, и их алгоритм не основан ни на каких фактических данных. И с тех пор ни одно исследование не смогло доказать связь между цикломатической сложностью и пониманием кода. Не говоря уже о том, что эта метрика сложности была предложена для Фортрана, а не для современных языков высокого уровня.
Лучший способ обеспечить понимание кода - это проверка кода. Просто попросите другого человека прочитать ваш код и исправить то, что он не понимает.
Так что просто отключите эти предупреждения.
Вы пытаетесь описать преобразование данных из одной сложной структуры в другую с использованием кода, и это создает много "сложности" в глазах такого инструмента обзора, как Code Climate.
Одна вещь, которая может помочь, это описать преобразование в терминах данных:
PAYMENT_DETAILS_PLAN = {
total_ticket_count: [ :tickets, :count ],
subtotal: [ :subtotal, :to_f ],
discount: [ :discount, :to_f ],
fees: [ :fees_total, :to_f ],
total: [ :total_in_dollars, :to_f ],
coupon: {
amount: [ :coupon, :amount ],
type: [ :coupon, :coupon_type ],
name: [ :coupon, :name ],
valid: [ :coupon, :valid_coupon? ]
}
}
Это может не показаться огромным изменением, и на самом деле это не так, но оно дает некоторые ощутимые преимущества. Во-первых, вы можете подумать об этом, вы можете проверить конфигурацию с помощью кода. Второе - после того, как вы установили этот формат, вы сможете написать DSL для манипулирования им, фильтрации или дополнения, среди прочего. Другими словами: это гибко.
Интерпретировать этот "план" не так сложно:
def distill(obj, plan)
plan.map do |name, call|
case (call)
when Array
[ name, call.reduce(obj) { |o, m| o.send(m) } ]
when Hash
[ name, distill(obj, plan) ]
end
end.to_h
end
Когда вы приводите это в действие, вот что вы получаете:
def apply_json
distill(payment_details, PAYMENT_DETAILS_PLAN)
end
Может быть, такой подход помогает в других ситуациях, когда вы делаете в основном то же самое.
Вы можете извлечь купонный субхеш как метод, возвращающий этот субхеш. Это уменьшит сложность кода (как в случае с кодеком), но в этом нет необходимости. Однако некоторые люди считают, что метод должен иметь 5 строк или меньше. И они правы в большинстве случаев использования. Но решать вам полностью.
def apply_json
{
total_ticket_count: payment_details.tickets.count,
subtotal: payment_details.subtotal.to_f,
discount: payment_details.discount.to_f,
fees: payment_details.fees_total.to_f,
total: payment_details.total_in_dollars.to_f,
coupon: subhash
}
end
def subhash
{
amount: payment_details.coupon.amount,
type: payment_details.coupon.coupon_type,
name: payment_details.coupon.name,
valid: payment_details.coupon.valid_coupon?,
}
end