$30 off During Our Annual Pro Sale. View Details »

Нейрофизиология сложности кода

Нейрофизиология сложности кода

Григорий Петров (Devrel в Evrone) @ Moscow Python №78

"В этом докладе я хочу продемонстрировать вам детали: как именно выглядит сложность в нейронах наших мозгов. Нас ждет огромное дерево когнитома, облака когов с оптическим зумом, зрительная кора, бесчеловечные эксперименты с воображением. И код. Много кода. Простого кода, сложного кода и непонятного кода, который с одной стороны простой, с другой сложный, а с третьей стороны вообще пересечение параллельных линий в форме котика".

Видео: https://moscowpython.ru/meetup/78/code-complexity-neurophysiology/

MoscowPython: http://moscowpython.ru
Курсы Learn Python: http://learn.python.ru
Moscow Python Podcast: http://podcast.python.ru

Moscow Python Meetup
PRO

July 14, 2022
Tweet

More Decks by Moscow Python Meetup

Other Decks in Programming

Transcript

  1. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    1
    Нейрофизиология
    сложности кода
    Григорий Петров

    View Slide

  2. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    Давайте использовать социальные сети:
    [email protected]
    t.me/grigoryvp
    fb.com/grigoryvp
    vk.com/grigoryvp
    github.com/grigoryvp
    twitter.com/grigoryvp
    instagram.com/grigoryvp
    Соцсети Имя
    2

    View Slide

  3. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    Что сейчас будет?
    3
    {
    speaker_name: "Григорий Петров",
    skill_list: ["Python", "Ruby", "JS", "Go", "Rust", "Cpp"],
    job_begin: 1998,
    job_title: "DevRel",
    talk_minutes: 30,
    questions_at: TALK_END,
    }

    View Slide

  4. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    Как мы осознаем окружающий мир
    4

    View Slide

  5. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    Как мы осознаем окружающий мир
    5

    View Slide

  6. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    Как мы осознаем окружающий мир
    6
    ● комната
    ● телевизор
    ● окно
    ● стеллаж
    ● цветок

    View Slide

  7. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    Как мы осознаем окружающий мир
    7

    View Slide

  8. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    Как мы осознаем окружающий мир
    8
    ● стеллаж
    ● цветок
    ● ковер
    ● пиала
    ● книги

    View Slide

  9. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    Как мы осознаем окружающий мир
    9

    View Slide

  10. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    Как мы осознаем окружающий мир
    10
    ● белый фарфор
    ● форма пиалы
    ● отражение
    ● горизонтальная доска
    ● вертикальная доска

    View Slide

  11. View Slide

  12. View Slide

  13. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    Код мы осознаем также
    13

    View Slide

  14. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    Код мы осознаем также
    def reset_loaders():
    for backend in engines.all():
    if not backend.is_template():
    continue
    for loader in backend.loaders:
    loader.reset()
    14

    View Slide

  15. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    Код мы осознаем также
    def reset_loaders():
    for backend in engines.all():
    if not backend.is_template():
    continue
    for loader in backend.loaders:
    loader.reset()
    15
    для всех бэкендов
    * только для темплейтов
    для всех лоадеров бэкенда
    ресет!

    View Slide

  16. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    Откуда берется облако смыслов?
    16

    View Slide

  17. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    Откуда берется облако смыслов?
    ➜ "Когнитом" Анохина.
    17

    View Slide

  18. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    Откуда берется облако смыслов?
    ✓ "Когнитом" Анохина.
    ➜ Дерево смыслов, растущее с рождения.
    18

    View Slide

  19. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    Откуда берется облако смыслов?
    ✓ "Когнитом" Анохина.
    ✓ Дерево смыслов, растущее с рождения.
    ➜ Новые элементы соединяются с существующими.
    19

    View Slide

  20. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    Откуда берется облако смыслов?
    ✓ "Когнитом" Анохина.
    ✓ Дерево смыслов, растущее с рождения.
    ✓ Новые элементы соединяются с существующими
    ➜ и закрепляются повторениями *.
    20
    * Обучение от простого к сложному и практика

    View Slide

  21. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    Откуда берется облако смыслов?
    ✓ "Когнитом" Анохина.
    ✓ Дерево смыслов, растущее с рождения.
    ✓ Новые элементы соединяются с существующими
    ➜ и закрепляются повторениями *.
    21
    * Обучение от простого к сложному и практика

    View Slide

  22. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    Облако смыслов для кода
    22

    View Slide

  23. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    Облако смыслов для кода берется из:
    23
    Синтаксис языка

    View Slide

  24. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    Облако смыслов для кода берется из:
    def foo(left, right):
    mid = (left + right) / 2
    return mid
    24
    Синтаксис языка

    View Slide

  25. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    Облако смыслов для кода берется из:
    def foo(left, right):
    mid = (left + right) / 2
    return mid
    25
    Синтаксис языка
    callable с параметрами
    туша callable с возвратом

    View Slide

  26. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    Облако смыслов для кода берется из:
    26
    Фреймворк

    View Slide

  27. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    Облако смыслов для кода берется из:
    class Publisher(models.Model):
    name = models.CharField()
    website = models.URLField()
    class Meta:
    ordering = ["-name"]
    def __str__(self):
    return self.name
    27
    Фреймворк

    View Slide

  28. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    Облако смыслов для кода берется из:
    class Publisher(models.Model):
    name = models.CharField()
    website = models.URLField()
    class Meta:
    ordering = ["-name"]
    def __str__(self):
    return self.name
    28
    Фреймворк
    Модель для базы
    Пара полей
    Отображение для админки

    View Slide

  29. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    Облако смыслов для кода берется из:
    29
    Библиотеки

    View Slide

  30. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    Облако смыслов для кода берется из:
    data[0:2, 0]
    30
    Библиотеки

    View Slide

  31. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    Облако смыслов для кода берется из:
    data[0:2, 0]
    31
    Библиотеки

    View Slide

  32. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    Облако смыслов для кода берется из:
    32
    Идиомы стека

    View Slide

  33. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    Облако смыслов для кода берется из:
    user = next(admin_users, None)
    33
    Идиомы стека

    View Slide

  34. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    Облако смыслов для кода берется из:
    user = next(admin_users, None)
    34
    Идиомы стека
    Первый админ
    * Если есть

    View Slide

  35. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    Облако смыслов для кода берется из:
    35
    Идиомы программирования

    View Slide

  36. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    Облако смыслов для кода берется из:
    def check_token(self, user, token):
    if not (user and token):
    return False
    ...
    36
    Идиомы программирования

    View Slide

  37. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    Облако смыслов для кода берется из:
    def check_token(self, user, token):
    if not (user and token):
    return False
    ...
    37
    Идиомы программирования
    Будем проверять токен
    Все хорошо?
    Продолжаем разговор

    View Slide

  38. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    Облако смыслов для кода берется из:
    38
    Имена идентификаторов

    View Slide

  39. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    Облако смыслов для кода берется из:
    i
    j
    k
    39
    Имена идентификаторов

    View Slide

  40. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    Облако смыслов для кода берется из:
    i
    j
    k
    40
    Имена идентификаторов
    Что?
    Где?
    Когда?

    View Slide

  41. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    Облако смыслов для кода берется из:
    i
    j
    k
    41
    Имена идентификаторов
    default_username
    permission_name_max_length
    resolved_login_url
    Что?
    Где?
    Когда?

    View Slide

  42. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    Облако смыслов для кода берется из:
    i
    j
    k
    42
    Имена идентификаторов
    default_username
    permission_name_max_length
    resolved_login_url
    Что?
    Где?
    Когда?
    Имя пользователя, если не задано
    Максимальная длина какого-то текста
    URL для логина, с которым что-то случилось

    View Slide

  43. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    Облако смыслов для кода берется из:
    43
    Имена идентификаторов
    Идиомы программирования
    Идиомы стека
    Библиотеки
    Фреймворк
    Синтаксис языка

    View Slide

  44. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    У разных людей разный когнитом
    44

    View Slide

  45. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    У разных людей разный когнитом
    Код
    45
    if val is None:
    try:
    del self['_session_expiry']
    except KeyError:
    pass
    return
    if isinstance(val, timedelta):
    val = timezone.now() + val
    self['_session_expiry'] = val

    View Slide

  46. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    У разных людей разный когнитом
    Код
    46
    Что осознает junior
    if val is None:
    try:
    del self['_session_expiry']
    except KeyError:
    pass
    return
    if isinstance(val, timedelta):
    val = timezone.now() + val
    self['_session_expiry'] = val
    Ничего не передали?
    Пробуем стереть по ключу
    * А так можно?
    Ошибки игнорируем
    Передали разницу времени?
    Делаем что-то с чем-то
    Сохраняем по ключу

    View Slide

  47. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    У разных людей разный когнитом
    Код
    47
    Что осознает junior Что осознает senior
    if val is None:
    try:
    del self['_session_expiry']
    except KeyError:
    pass
    return
    if isinstance(val, timedelta):
    val = timezone.now() + val
    self['_session_expiry'] = val
    Ставим/удаляем поле
    * Соблюдаем таймзону
    * Собственный сеттер
    Ничего не передали?
    Пробуем стереть по ключу
    * А так можно?
    Ошибки игнорируем
    Передали разницу времени?
    Делаем что-то с чем-то
    Сохраняем по ключу

    View Slide

  48. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    Кошелек Миллера
    48

    View Slide

  49. View Slide

  50. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    Кошелек Миллера
    ➜ Мы не знаем почему так.
    50

    View Slide

  51. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    Кошелек Миллера
    ✓ Мы не знаем почему так.
    ➜ Активируемые части когнитома могут быть большими.
    51

    View Slide

  52. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    Кошелек Миллера
    ✓ Мы не знаем почему так.
    ✓ Активируемые части когнитома могут быть большими.
    ➜ Например "комната с дверью за спиной и окном".
    52

    View Slide

  53. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    Кошелек Миллера
    ✓ Мы не знаем почему так.
    ✓ Активируемые части когнитома могут быть большими.
    ✓ Например "комната с дверью за спиной и окном".
    ➜ Ориентироваться в непривычном помещении нам тяжело.
    53

    View Slide

  54. View Slide

  55. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    Очевидно:
    ➜ Чем больше знакомых приемов, тем проще разработчик читает код.
    55

    View Slide

  56. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    Очевидно:
    ✓ Чем больше знакомых приемов, тем проще разработчик читает код.
    ➜ Разработчик с большим опытом проще читает код.
    56

    View Slide

  57. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    Очевидно:
    ✓ Чем больше знакомых приемов, тем проще разработчик читает код.
    ✓ Разработчик с большим опытом проще читает код.
    ➜ Код, написанный знакомыми приемами, проще читается.
    57

    View Slide

  58. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    Очевидно:
    ✓ Чем больше знакомых приемов, тем проще разработчик читает код.
    ✓ Разработчик с большим опытом проще читает код.
    ✓ Код, написанный знакомыми приемами, проще читается.
    ➜ "Пять" это не число строк, методов или классов.
    58

    View Slide

  59. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    Очевидно:
    ✓ Чем больше знакомых приемов, тем проще разработчик читает код.
    ✓ Разработчик с большим опытом проще читает код.
    ✓ Код, написанный знакомыми приемами, проще читается.
    ✓ "Пять" это не число строк, методов или классов.
    ➜ Это количество несвязанных частей когнитома для осознания кода.
    59

    View Slide

  60. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    Очевидно:
    ✓ Чем больше знакомых приемов, тем проще разработчик читает код.
    ✓ Разработчик с большим опытом проще читает код.
    ✓ Код, написанный знакомыми приемами, проще читается.
    ✓ "Пять" это не число строк, методов или классов.
    ✓ Это количество несвязанных частей когнитома для осознания кода.
    ➜ Разное число для разных разработчиков.
    60

    View Slide

  61. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    Очевидно:
    ✓ Чем больше знакомых приемов, тем проще разработчик читает код.
    ✓ Разработчик с большим опытом проще читает код.
    ✓ Код, написанный знакомыми приемами, проще читается.
    ✓ "Пять" это не число строк, методов или классов.
    ✓ Это количество несвязанных частей когнитома для осознания кода.
    ✓ Разное число для разных разработчиков.
    ➜ Разное число для разных путей в коде.
    61

    View Slide

  62. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    Очевидно:
    ✓ Чем больше знакомых приемов, тем проще разработчик читает код.
    ✓ Разработчик с большим опытом проще читает код.
    ✓ Код, написанный знакомыми приемами, проще читается.
    ✓ "Пять" это не число строк, методов или классов.
    ✓ Это количество несвязанных частей когнитома для осознания кода.
    ✓ Разное число для разных разработчиков.
    ✓ Разное число для разных путей в коде.
    ➜ Мы привыкаем к коду, который пишем прямо сейчас.
    62

    View Slide

  63. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    Очевидно:
    ✓ Чем больше знакомых приемов, тем проще разработчик читает код.
    ✓ Разработчик с большим опытом проще читает код.
    ✓ Код, написанный знакомыми приемами, проще читается.
    ✓ "Пять" это не число строк, методов или классов.
    ✓ Это количество несвязанных частей когнитома для осознания кода.
    ✓ Разное число для разных разработчиков.
    ✓ Разное число для разных путей в коде.
    ✓ Мы привыкаем к коду, который пишем прямо сейчас.
    ➜ Когнитивная сложность разная с "прогретым кешом" и "вхолодную".
    63

    View Slide

  64. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    Очевидно:
    ✓ Чем больше знакомых приемов, тем проще разработчик читает код.
    ✓ Разработчик с большим опытом проще читает код.
    ✓ Код, написанный знакомыми приемами, проще читается.
    ✓ "Пять" это не число строк, методов или классов.
    ✓ Это количество несвязанных частей когнитома для осознания кода.
    ✓ Разное число для разных разработчиков.
    ✓ Разное число для разных путей в коде.
    ✓ Мы привыкаем к коду, который пишем прямо сейчас.
    ✓ Когнитивная сложность разная с "прогретым кешом" и "вхолодную".
    ➜ Когнитивная сложность целого больше сложности его частей.
    64

    View Slide

  65. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    Сложность целого больше сложности частей
    65

    View Slide

  66. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    Сложность целого больше сложности частей
    66
    def _post_process(self, paths, adjustable_paths, hashed_files):
    # Sort the files by directory level
    def path_level(name):
    return len(name.split(os.sep))
    for name in sorted(paths, key=path_level, reverse=True):
    substitutions = True
    # use the original, local file, not the copied-but-unprocessed
    # file, which might be somewhere far away, like S3
    storage, path = paths[name]
    with storage.open(path) as original_file:
    cleaned_name = self.clean_name(name)
    hash_key = self.hash_key(cleaned_name)
    # generate the hash with the original content, even for
    # adjustable files.
    if hash_key not in hashed_files:
    hashed_name = self.hashed_name(name, original_file)
    else:
    hashed_name = hashed_files[hash_key]
    # then get the original's file content..
    if hasattr(original_file, 'seek'):
    original_file.seek(0)
    hashed_file_exists = self.exists(hashed_name)
    processed = False
    # ..to apply each replacement pattern to the content
    if name in adjustable_paths:
    old_hashed_name = hashed_name
    content = original_file.read().decode('utf-8')
    for extension, patterns in self._patterns.items():
    if matches_patterns(path, (extension,)):
    for pattern, template in patterns:
    converter = self.url_converter(name, hashed_files, template)
    try:
    content = pattern.sub(converter, content)
    except ValueError as exc:
    yield name, None, exc, False
    if hashed_file_exists:
    self.delete(hashed_name)
    # then save the processed result
    content_file = ContentFile(content.encode())
    if self.keep_intermediate_files:
    # Save intermediate file for reference
    self._save(hashed_name, content_file)
    hashed_name = self.hashed_name(name, content_file)
    if self.exists(hashed_name):
    self.delete(hashed_name)
    saved_name = self._save(hashed_name, content_file)
    hashed_name = self.clean_name(saved_name)
    # If the file hash stayed the same, this file didn't change
    if old_hashed_name == hashed_name:
    substitutions = False
    processed = True
    if not processed:
    # or handle the case in which neither processing nor
    # a change to the original file happened
    if not hashed_file_exists:
    processed = True
    saved_name = self._save(hashed_name, original_file)
    hashed_name = self.clean_name(saved_name)
    # and then set the cache accordingly
    hashed_files[hash_key] = hashed_name
    yield name, hashed_name, processed, substitutions

    View Slide

  67. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    Что делать
    67

    View Slide

  68. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    Что делать
    ➜ Следим за количеством "штук".
    68

    View Slide

  69. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    Что делать
    ✓ Следим за количеством "штук".
    ➜ Следим за "идеоматичностью".
    69

    View Slide

  70. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    Что делать
    ✓ Следим за количеством "штук".
    ✓ Следим за "идеоматичностью".
    ➜ Проверка: Большинство разработчиков так это делают?
    70

    View Slide

  71. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    Что делать
    ✓ Следим за количеством "штук".
    ✓ Следим за "идеоматичностью".
    ✓ Проверка: Большинство разработчиков так это делают?
    ➜ Проверка: Это будет читать junior, middle или senior?
    71

    View Slide

  72. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    Что делать
    ✓ Следим за количеством "штук".
    ✓ Следим за "идеоматичностью".
    ✓ Проверка: Большинство разработчиков так это делают?
    ✓ Проверка: Это будет читать junior, middle или senior?
    ➜ Проверка: Это будет читать специалист или генералист?
    72

    View Slide

  73. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    Что делать
    ✓ Следим за количеством "штук".
    ✓ Следим за "идеоматичностью".
    ✓ Проверка: Большинство разработчиков так это делают?
    ✓ Проверка: Это будет читать junior, middle или senior?
    ✓ Проверка: Это будет читать специалист или генералист?
    ➜ Следим за именами "штук".
    73

    View Slide

  74. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    Что делать
    ✓ Следим за количеством "штук".
    ✓ Следим за "идеоматичностью".
    ✓ Проверка: Большинство разработчиков так это делают?
    ✓ Проверка: Это будет читать junior, middle или senior?
    ✓ Проверка: Это будет читать специалист или генералист?
    ✓ Следим за именами "штук".
    ➜ Проверка: Идентификатор отвечает на вопрос "что это"?
    74

    View Slide

  75. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    Что делать
    ✓ Следим за количеством "штук".
    ✓ Следим за "идеоматичностью".
    ✓ Проверка: Большинство разработчиков так это делают?
    ✓ Проверка: Это будет читать junior, middle или senior?
    ✓ Проверка: Это будет читать специалист или генералист?
    ✓ Следим за именами "штук".
    ✓ Проверка: Идентификатор отвечает на вопрос "что это"?
    ➜ Проверка: Код отвечает на вопрос "зачем это"?
    75

    View Slide

  76. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    Что делать
    ✓ Следим за количеством "штук".
    ✓ Следим за "идеоматичностью".
    ✓ Проверка: Большинство разработчиков так это делают?
    ✓ Проверка: Это будет читать junior, middle или senior?
    ✓ Проверка: Это будет читать специалист или генералист?
    ✓ Следим за именами "штук".
    ✓ Проверка: Идентификатор отвечает на вопрос "что это"?
    ✓ Проверка: Код отвечает на вопрос "зачем это"?
    ➜ Проверка: Код рассказывает историю?
    76

    View Slide

  77. Выводы

    View Slide

  78. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    Выводы
    ➜ Наш мозг работает не так, как рассказывают бабушки у подъезда.
    78

    View Slide

  79. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    Выводы
    ✓ Наш мозг работает не так, как рассказывают бабушки у подъезда.
    ➜ Есть контринтуитивные штуки: диеты, тренажерный зал, сложность кода.
    79

    View Slide

  80. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    Выводы
    ✓ Наш мозг работает не так, как рассказывают бабушки у подъезда.
    ✓ Есть контринтуитивные штуки: диеты, тренажерный зал, сложность кода.
    ➜ Есть люди худые, мускулистые, умные от природы.
    80

    View Slide

  81. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    Выводы
    ✓ Наш мозг работает не так, как рассказывают бабушки у подъезда.
    ✓ Есть контринтуитивные штуки: диеты, тренажерный зал, сложность кода.
    ✓ Есть люди худые, мускулистые, умные от природы.
    ➜ Нам нужно хорошо разобраться в вопросе, если хотим сделать круто.
    81

    View Slide

  82. @grigoryvp Григорий Петров
    http://bit.ly/ccomnf
    82

    View Slide