[РИТ 2020] Код, с которым приятно иметь дело

[РИТ 2020] Код, с которым приятно иметь дело

Я хотел бы предложить авторам OSS-библиотек и разработчикам приложений взглянуть на написание кода с другой стороны — со стороны тех, кому придётся работать с ним в будущем. Несмотря на то, что чисто технически мы пишем код для машин, его основными пользователями являются люди. Что же такое «код, удобный в использовании»?

За годы работы над коммерческими и OSS-проектами я сформировал для себя список принципов, которыми должен соответствовать такой код, например: тестируемость, гибкость, расширяемость, узнаваемость и т.д. В докладе я рассмотрю этот «чек-лист» подробнее, а также приведу примеры из мира Руби и не только.

52cc8a838bf44a589d2572833b2dd1b9?s=128

Vlad Dem

May 26, 2020
Tweet

Transcript

  1. Код, с которым приятно иметь дело Владимир Дементьев (Злые марсиане)

  2. palkan_tula palkan Кот, с которым приятно иметь дело Что это?

    Д Если код хорош — то всегда легко, а когда наоборот — трудно
  3. palkan_tula palkan Чек-лист для авторов и пользователей Код, с которым

    приятно иметь дело Yet Another Framework
  4. palkan_tula palkan А судьи кто? Или обо мне

  5. palkan_tula palkan github.com/palkan 5

  6. palkan_tula palkan evilmartians.com 6

  7. palkan_tula palkan evilmartians.com 7

  8. palkan_tula palkan evilmartians.com 8 Ruby Next Transpiler for Ruby

  9. palkan_tula palkan evl.ms/blog 9

  10. palkan_tula palkan github.com/palkan 10

  11. palkan_tula palkan Ruby Hero ...По-русски

  12. palkan_tula palkan –Matz “Ruby is designed to make programmers happy.”

    12
  13. palkan_tula palkan “The more expressive language the much easier is

    to write terrible code” –Noah Gibbs 13
  14. palkan_tula palkan Код, с которым приятно иметь дело

  15. palkan_tula palkan «Иметь дело» 15 Читать Писать и изменять Отлаживать

    Делиться
  16. palkan_tula palkan Читать Писать и изменять Отлаживать Делиться «Иметь дело»

    16 Приятно
  17. palkan_tula palkan Пишите код для других, а не для себя

    17
  18. None
  19. palkan_tula palkan Пишем код для людей

  20. palkan_tula palkan Простой код

  21. palkan_tula palkan Простой код 21 Минимум кода для простого функционала

    Меньше думать при написании Легко понимать написанное
  22. palkan_tula palkan –Alan Kay “Simple things should be simple, complex

    things should be possible.” 22
  23. palkan_tula palkan Boilerplate Враг №1

  24. palkan_tula palkan 24 var req = new XMLHttpRequest(); req.responseType =

    'json'; req.onload = function() { handle(xhr.response) }; req.open('GET', '/api/me.json', true); req.send(null);
  25. palkan_tula palkan 25 fetch('/api/me.json') .then(response => response.json() .then(handle);

  26. palkan_tula palkan 26 uri = URI("http: //example.com/index.json") params = {limit:

    10, page: 3} uri.query = URI.encode_ www_form(params) req = Net ::HTTP ::Get.new uri req.basic_auth 'user', 'pass' res = Net ::HTTP.start(uri.host, uri.port) do |http| http.request(req) end if res.is_a?(Net ::HTTPSuccess) JSON.parse(res.body) end
  27. palkan_tula palkan 27 HTTParty.get( "http: //example.com/index.json", {limit: 10, page: 3},

    basic_auth: {username: "user", password: "pass"} )
  28. palkan_tula palkan 28 Лаконичный API поверх низкоуровневого

  29. palkan_tula palkan Boilerplate 29 «Легковесный» API Разумные значения по умолчанию

  30. palkan_tula palkan Больше разумных значений по умолчанию 㱺 Меньше действий

    пользователя 㱺 Меньше шансов на ошибку 30
  31. palkan_tula palkan Значения по умолчанию 31 Аргументы методов/функций Параметры конфигурации

  32. palkan_tula palkan Разумная конфигурация 32 Значения, которые подходят большинству пользователей

  33. palkan_tula palkan Hanami 1.0 → 2.0 slidr.io/jodosha/parisrb-2020-keynote 33

  34. palkan_tula palkan Разумная конфигурация 34 Значения, которые подходят большинству пользователей

    Автоматическое «распознавание» популярных переменных окружения (DATABASE_URL, REDIS_URL)
  35. palkan_tula palkan Разумная конфигурация 35

  36. palkan_tula palkan 36 SomeSDK.configure do |config| config.access_key = "REPLACE_WITH_ACCESS_KEY_ID" config.secret_key

    = "REPLACE_WITH_SECRET_ACCESS_KEY" end Разумная конфигурация В документации каждой второй библиотеки для интеграции с API
  37. palkan_tula palkan 37 SOME_SDK_ACCESS_KEY_ID=123 SOME_SDK_SECRET_ACCESS_KEY=secret # or some_sdk.yml access_key_id: 123

    secret_access_key: secret Zero-code конфигурация
  38. palkan_tula palkan Zero-code конфигурация 38 Ruby: anyway_config Go: viper

  39. palkan_tula palkan Anyway Config evilmartians.com/chronicles/anyway-config-keep-your-ruby-configuration-sane 39

  40. palkan_tula palkan 40 Аргументы методов/функций Параметры конфигурации Соглашения об именовании

    (Convention over configuration) Значения по умолчанию
  41. palkan_tula palkan Разумные соглашения 41 class Post < ActiveRecord ::Base

    belongs_to :user end Post.joins(:user).all # => SELECT * FROM posts INNER JOIN users ...
  42. palkan_tula palkan 42 class Post < ActiveRecord ::Base self.table_name =

    "posts" belongs_to :user, foreign_key: :user_id, class_name: "User", primary_key: :id end Разумные соглашения
  43. palkan_tula palkan Простой код 43 Минимум кода для простого функционала

    Меньше думать при написании Легко понимать написанное
  44. palkan_tula palkan Принцип наименьшего удивления

  45. palkan_tula palkan Wat, Ruby?! 45 1.nonzero? # => 1 0.nonzero?

    # => nil 0.zero? # => true 1.zero? # => false
  46. palkan_tula palkan Wat, JS?! medium.com/@winwardo/the-principle-of-least-astonishment-and-javascripts-sort-e98a734a30c9 46

  47. palkan_tula palkan Erlang :( 47 1> lists:split(2, [2, 0, 2,

    0]). {[2,0],[2,0]} 2> lists:sublist(2, [2, 0, 2, 0]). ** exception error: no function clause matching 3> lists:sublist([2, 0, 2, 0], 2). [2, 0]
  48. palkan_tula palkan Минимум wtf 48 Консистентность API и стиля кода

  49. palkan_tula palkan Стандартный стиль 49 StandardJS StandardRB PEP8 go fmt

  50. palkan_tula palkan Минимум wtf 50 Консистентность API и стиля кода

    Узнаваемость/похожесть/подражание Отсутствующие/осмысленные monkey patches Однозначные именования
  51. palkan_tula palkan Удивительные названия 51

  52. palkan_tula palkan Синтаксический уксус Как не дать выстрелить себе в

    ногу
  53. palkan_tula palkan Синтаксический уксус 53 Заставляет разработчика задуматься о том,

    что он делает Намекает на потенциальную опасность операции
  54. palkan_tula palkan 54 class SomeTest < Minitest ::Test i_suck_and_my_tests_are_order_dependent! end

  55. palkan_tula palkan 55 unsafe fn dangerous() {} unsafe { dangerous();

    }
  56. palkan_tula palkan Отладь меня, если сможешь Код, помогающий исправлять ошибки

  57. palkan_tula palkan Отладка обычного человека 57

  58. palkan_tula palkan Коды ошибок для машин, сообщения — для людей

    58
  59. palkan_tula palkan Сообщения об ошибках 59 Содержательные: содержат максимум контекста

    для быстрой локализации проблемы Призывающие к действию: содержат инструкции для устранения проблемы
  60. palkan_tula palkan Содержательные ошибки 60 # плохо create_event(type: "BBQ") =>

    Unknown type. # хорошо create_event(type: "BBQ") => Unknown type: BBQ.
  61. palkan_tula palkan Ошибки с подсказками 61 # плохо create_event(type: "BBQ")

    => Unknown type. # хорошо create_event(type: "BBQ") => Unknown type: BBQ. # отлично create_event(type: "BBQ") => Unknown type: BBQ. Choose: quarantine or self- isolation"
  62. palkan_tula palkan https://twitter.com/o0ignition0o/status/1223003607966060544 62 Ошибки с подсказками

  63. palkan_tula palkan 63 https://github.com/jules2689/extended_bundler-errors Ошибки с подсказками

  64. palkan_tula palkan Human errors 64

  65. palkan_tula palkan Логирование 65 Должно помогать, а не мешать Должно

    быть настраиваемым (уровни, формат, устройство вывода)
  66. palkan_tula palkan Идеальный логгер 66 MyLibrary.logger = Logger.new

  67. palkan_tula palkan Логирование 67 Должно помогать, а не мешать Должно

    быть настраиваемым (уровни, формат, устройство вывода) Должно иметь разумные настройки по умолчанию
  68. palkan_tula palkan [36mCOLOR=true[0m 68

  69. palkan_tula palkan Тестируемость 2 unit tests. 0 integration tests. Вы

    же пишете тесты, не так ли?
  70. palkan_tula palkan Удобно ли тестировать код, который использует ваш код,

    или код, который использует код, которой использует ваш код, или код, который использует код, который использует код, которой использует ваш код... 70
  71. palkan_tula palkan Тестируемость 71 Тестовый режим/бекенд/адаптер

  72. palkan_tula palkan 72 # Тестовые адаптеры config.active_job.queue_adapter = :test config.action_mailer.delivery_method

    = :test # Мок-режим Fog.mock! # No-op режим Sidekiq ::Testing.fake! Тестируемость
  73. palkan_tula palkan Тестируемость 73 Тестовый режим/бекенд/адаптер Инструменты для тестирования

  74. palkan_tula palkan Тестируемость 74 Тестовый режим/бекенд/адаптер Инструменты для тестирования Забота

    о скорости выполнения тестов
  75. palkan_tula palkan 75 CarrierWave.configure do |config| config.enable_processing = false end

    Devise.setup do |config| config.stretches = Rails.env.test? ? 1 : 11 end Тестируемость
  76. palkan_tula palkan От частного к общему Принципы гибкой архитектуры

  77. palkan_tula palkan Гибкая архитектура 77 Взаимозаменяемость (adapter pattern, DI) Расширяемость

    (plugins, middlewares) В следующей серии
  78. palkan_tula palkan Заметки Про вашего мальчика код

  79. palkan_tula palkan –Joe Armstrong “A program is only as good

    as its documentation.” 79
  80. palkan_tula palkan Документация (в широком смысле) — это всё то,

    что в будущем за вас ответит на вопросы разработчиков 80
  81. palkan_tula palkan Документация 81 Непосредственно документы (специально написанные) Комментарии в

    коде Сообщения коммитов / описания PR История изменений (change log) Примеры / демо / тесты
  82. palkan_tula palkan Лучше никакой документации, чем устаревшая 82

  83. palkan_tula palkan Чек-лист 83 Минимум шаблонного кода Разумные значения по

    умолчанию Интуитивно понятный API Содержательные сообщения об ошибках
  84. palkan_tula palkan Чек-лист 84 Гибкое и настраиваемое логирование Тестируемость Расширяемость

    и взаимозаменяемость Полезная документация
  85. palkan_tula palkan 85 gemcheck.evilmartians.io

  86. palkan_tula palkan Writing code for people slideshare.net/iAdramelk/writing-code-for-people-228709457 86

  87. Спасибо Владимир Дементьев, Злые марсиане Write code for @evilmartians evilmartians.com

    @palkan @palkan_tula