Функции должны быть компактными
От: dosik Россия www.dosik.ru
Дата: 25.04.16 15:41
Оценка: +1 -2
В своей книге Р. Мартин утверждает, что функции необходимо предъявлять всего два требования:
1. они должны быть компактными
2. они должны быть еще более компактными
Т.е. функция должна выполнять лишь одну операцию. Функции, выполняющие несколько операций необходимо дробить на несколько.
Тогда вопрос: А как же накладные расходы на вызов функции? Ведь вместо того, чтобы продолжить вычисления, теперь нам надо заполнить стек и передать управление по адресу, а по возвращению очистить стек. Т.е. улучшая читабельность кода мы уменьшаем производительность системы. Да и как то меня учили, что в функцию необходимо выносить лишь тот код, который может быть вызван из нескольких участков программы. И какой тогда смысл выносить в отдельную функцию код, который будет вызываться только в одном месте?
Re: Функции должны быть компактными
От: alpha21264 СССР  
Дата: 25.04.16 16:06
Оценка: +1
Здравствуйте, dosik, Вы писали:

D>Т.е. функция должна выполнять лишь одну операцию. Функции, выполняющие несколько операций необходимо дробить на несколько.

D>Тогда вопрос: А как же накладные расходы на вызов функции?

Это дело компилятора. Сейчас компилятор много чего без тебя инлайнит.
Да и вообще — кому сейчас нужно ловить настолько мелких блох?
Чай не времена 286-х!

Течёт вода Кубань-реки куда велят большевики.
Re[2]: Функции должны быть компактными
От: dosik Россия www.dosik.ru
Дата: 25.04.16 16:12
Оценка: +2
Здравствуйте, alpha21264, Вы писали:

A>Да и вообще — кому сейчас нужно ловить настолько мелких блох?

A>Чай не времена 286-х!

Ну как сказать ))) Сегодня ты пишешь клиентские десктопные приложения, а завтра на тебе, и ты уже ARM программист, и там рассказывай про блох )))
Re: Функции должны быть компактными
От: vmpire Россия  
Дата: 25.04.16 16:21
Оценка: +1
Здравствуйте, dosik, Вы писали:

D>Т.е. функция должна выполнять лишь одну операцию. Функции, выполняющие несколько операций необходимо дробить на несколько.

Спорное утверждение. Нужно решать в каждом конкретном случае, что лучше.

D>Тогда вопрос: А как же накладные расходы на вызов функции? Ведь вместо того, чтобы продолжить вычисления, теперь нам надо заполнить стек и передать управление по адресу, а по возвращению очистить стек.

Как уже написали, в современных ЯВУ это забота компилятора. Он лучше человека разберётся, что куда инлайнить.

D>Т.е. улучшая читабельность кода мы уменьшаем производительность системы.

Вот это и есть цель: улучшить читаемость

D>Да и как то меня учили, что в функцию необходимо выносить лишь тот код, который может быть вызван из нескольких участков программы. И какой тогда смысл выносить в отдельную функцию код, который будет вызываться только в одном месте?

Неправильно, видимо, учили. Есть такое понятие: "самодокументируемый код".
Чем писать несколько строк кода и к ним комментарий, скажем, "// Check permissions", лучше вынести этот код в отдельный метод с названием CheckPermissions(). Комментарий станет ненужным, не сможет потерять свою актуальность, и, в случае, если функция понадобится в другом месте, коментарий там также не потребуется.
Re: Функции должны быть компактными
От: tdiff  
Дата: 25.04.16 17:34
Оценка: +2
Здравствуйте, dosik, Вы писали:

D>В своей книге Р. Мартин утверждает, что функции необходимо предъявлять всего два требования:

D>1. они должны быть компактными
D>2. они должны быть еще более компактными
D>Т.е. функция должна выполнять лишь одну операцию. Функции, выполняющие несколько операций необходимо дробить на несколько.
D>Тогда вопрос: А как же накладные расходы на вызов функции?

1. Я так подозреваю, что значительная часть целевой аудитории подобных книг пишет программы, в которых производительность не является критичным фактором (не важно, секунду или две будет считаться бизнес-логика, всё равно всё в конечном итоге упирается в БД).
2. Надо стараться не переборщить с "компактизированием", т.к. не всегда разбиение фунции на меньшие улучшает читаемость. Если не ошибаюсь, как раз у Мартина в самом начале, в качестве примера, из понятной программы на 20 строк делается монстр из 5 классов.
Re: Функции должны быть компактными
От: __kot2  
Дата: 25.04.16 18:35
Оценка: +1 :))) :)
Здравствуйте, dosik, Вы писали:
D>Тогда вопрос: А как же накладные расходы на вызов функции? Ведь вместо того, чтобы продолжить вычисления, теперь нам надо заполнить стек и передать управление по адресу, а по возвращению очистить стек. Т.е. улучшая читабельность кода мы уменьшаем производительность системы.
вообще, даже когда ты пишешь на ассемблере, у тебя всегда есть выбор между ф-ией и макросом. современные копиляторы умеют сами оценивать накладные расходы на вызов и решать, что лучше — инлайнить код или реально вызывать его.

D>Да и как то меня учили, что в функцию необходимо выносить лишь тот код, который может быть вызван из нескольких участков программы. И какой тогда смысл выносить в отдельную функцию код, который будет вызываться только в одном месте?

это рекомендации где-то годов 70ых-80. после людям пришло понимание, что программы большие и сложные и соверешнно бесполезные, если в них нельзя разобраться. сначала они начали писать комменты, а потом поняли, что можно давать имена ф-ия так, чтобы по ним было все понятно и без комментов.
любой человек, который до сих пор пишет ф-ии в столбик строк по 30, вставляя туда комменты просто неквалифицирован и его нельзя допускать до написания реального кода
Re: Функции должны быть компактными
От: Pzz Россия https://github.com/alexpevzner
Дата: 25.04.16 18:51
Оценка: 1 (1) +3
Здравствуйте, dosik, Вы писали:

D>Тогда вопрос: А как же накладные расходы на вызов функции? Ведь вместо того, чтобы продолжить вычисления, теперь нам надо заполнить стек и передать управление по адресу, а по возвращению очистить стек. Т.е. улучшая читабельность кода мы уменьшаем производительность системы. Да и как то меня учили, что в функцию необходимо выносить лишь тот код, который может быть вызван из нескольких участков программы. И какой тогда смысл выносить в отдельную функцию код, который будет вызываться только в одном месте?


Ну, есть такая точка зрения, что если выбирать между эффективностью кода и понятностью кода, понятность важнее. Заметим к слову, что даже в программе, в которой эффективкость важна, обычно это касается 10% кода, а остальной код вызывается редко, или упирается во ввод-вывод, а не процессор, и т.п. Кроме того, компилятор часто догадывается поинлайнить функции. И еще, вызов может быть даже дешевле инлайна, поскольку разделение кода на небольшие функции может облегчить жизнь той части компилятора, которая распределяет регистры.

Другой вопрос, что разбиение кода на мелкие функции далеко не всегда облегчает его понимание. Поэтому к этому совету надо относиться критически.
Re: Функции должны быть компактными
От: dosik Россия www.dosik.ru
Дата: 25.04.16 19:19
Оценка:
Отвечу сам себе, поскольку основная масса ответов идентична — не бери на себя работу компилятора, пиши удобочитаемый код, а компилятор сам все заинлайнит.
А что тогда с высоконагруженными приложениями, где кроме как на себя, даже на компилятор положиться нельзя?
Re[2]: Функции должны быть компактными
От: __kot2  
Дата: 25.04.16 19:31
Оценка:
Здравствуйте, dosik, Вы писали:
D>Отвечу сам себе, поскольку основная масса ответов идентична — не бери на себя работу компилятора, пиши удобочитаемый код, а компилятор сам все заинлайнит.
D>А что тогда с высоконагруженными приложениями, где кроме как на себя, даже на компилятор положиться нельзя?
они оптимизированы только в воображении менеджмента и еще может быть hr. в основном работают очень неэффективно
Re[2]: Функции должны быть компактными
От: T4r4sB Россия  
Дата: 25.04.16 19:39
Оценка:
Здравствуйте, __kot2, Вы писали:

__>любой человек, который до сих пор пишет ф-ии в столбик строк по 30, вставляя туда комменты просто неквалифицирован и его нельзя допускать до написания реального кода


30 это много?
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Re[2]: Функции должны быть компактными
От: ononim  
Дата: 25.04.16 20:00
Оценка:
A>Да и вообще — кому сейчас нужно ловить настолько мелких блох?
A>Чай не времена 286-х!
Да вот в соседней ветке
Автор: system.console
Дата: 24.04.16
блохами возмущаются
Как много веселых ребят, и все делают велосипед...
Отредактировано 25.04.2016 20:01 ononim . Предыдущая версия .
Re: Функции должны быть компактными
От: vsb Казахстан  
Дата: 25.04.16 20:19
Оценка: +1
В первую очередь код должен быть как можно более читаемым. Если ради этого нужно жертвовать производительностью — надо делать это не задумываясь. И только когда производительность программы станет неудовлетворительной, нужно произвести минимальные ухудшения, чтобы улучшить производительность до приемлемой. Поэтому такими вещами, как накладные расходы на вызовы функций, заморачиваться не нужно.

Есть проекты, в которых производительность важна до той степени, что их части приходится писать на языке ассемблера. Но это очень редкие случаи и погоды они не делают. В 99% случаев именно так.
Re: Функции должны быть компактными
От: Философ Ад http://vk.com/id10256428
Дата: 25.04.16 20:28
Оценка: 53 (2) +3
Здравствуйте, dosik, Вы писали:

D>Тогда вопрос: А как же накладные расходы на вызов функции? Ведь вместо того, чтобы продолжить вычисления, теперь нам надо заполнить стек и передать управление по адресу, а по возвращению очистить стек. Т.е. улучшая читабельность кода мы уменьшаем производительность системы.


О такой мелочёвке нужно можно заботиться только после того как ты отпрофилировал программу. До профайлинга нужно написать удобочитаемый и легко изменяемый код.
Когда после профилировки ты выяснишь, что у тебя какой-нибудь Math.Max() не заинлайнен компилятором, и существует милиард его вызовов, и что от милиарда вызовов никуда не уйти (а именно в этом бОльшая часть оптимизаций и заключается), тогда и заинлайнишь — не раньше.
В ином случае ты рискуешь во время написания отловить блох, а в итоге получить O(n!) там, где должен быть O(n log(n)).
Всё сказанное выше — личное мнение, если не указано обратное.
Отредактировано 26.04.2016 5:21 Философ . Предыдущая версия . Еще …
Отредактировано 25.04.2016 20:29 Философ . Предыдущая версия .
Re[3]: Функции должны быть компактными
От: __kot2  
Дата: 25.04.16 20:38
Оценка:
Здравствуйте, T4r4sB, Вы писали:
TB>Здравствуйте, __kot2, Вы писали:
__>>любой человек, который до сих пор пишет ф-ии в столбик строк по 30, вставляя туда комменты просто неквалифицирован и его нельзя допускать до написания реального кода
TB>30 это много?
слова много и мало они тут неправильные
у меня был знакомый, он тоже писал, писал, потом когда думал, что уже много, создавал новый файл и начинал писать туда. так люди какают, а не пишут программы
функция должна делать одно дело. 30 строк — очень редко когда это что-то прямо одно такое. бывает, но редко. чаще всего там все-таки несколько действий, каждое из которых имеет смысла выделить в отдельную ф-ию.
если все равно непонятно что означает "одно действие", то для начала создайте блоки минимальной видимости переменных, типа

void see_you()
{
  int size = get_size();
  if size > ... 
  do_something(size)

  //а здесь ниже уже нигде size не ипользуется и идет код типа
  call_something()
  do_some_stuff()
  for ( x)
  {
    if ( x > 10)
    {
      print_something();
      x += 2;
    }

    superman = new superman()
    betment = new betment()
    fight(superman, betment)
  }
}

то разумно, чтобы случайно не наткнуться на конфликт имен взять верхий блок в скобки и записать в стиле

void see_you()
{
  {
    int size = get_size();
    if size > ... 
    do_something(size)
  }

  call_something()
  do_some_stuff()

  for ( x : xs)
  {
    if ( x > 10)
    {
      print_something();
      x += 2;
    }

    {
      superman = new superman()
      betment = new betment()
      fight(superman, betment)
    }
  }
}


после этого берете и все что внутри скобочек выделяете в отдельные ф-ии (за исключением, может, пары разумных исключений) и получаете код вроде

void see_you()
{
  adjust_size()
  call_something()
  do_some_stuff()

  for ( x : xs)
  {
    if ( time_to_so_it(x))
      do_it();

    betment_superman_fight();
  }
}

или даже правильнее будет

void see_you()
{
  adjust_arena_size()
  call_spectators()
  setup_lights()

  betment_fight_for_every_something(xs);
}


причем я не говорю о рефакторинге, никто не мешает так писать сразу. и, разумеется, именя ф-ий не должны называться do_stuff() а должны описывать что конкретно за стафф мы ду.
Re[4]: Функции должны быть компактными
От: T4r4sB Россия  
Дата: 25.04.16 20:46
Оценка: +4
Здравствуйте, __kot2, Вы писали:

__>функция должна делать одно дело. 30 строк — очень редко когда это что-то прямо одно такое. бывает, но редко. чаще всего там все-таки несколько действий, каждое из которых имеет смысла выделить в отдельную ф-ию.


Да скорее задолбаешься контекст функции передавать в подфункции.
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Re[3]: Функции должны быть компактными
От: alpha21264 СССР  
Дата: 25.04.16 21:11
Оценка: +5
Здравствуйте, ononim, Вы писали:

A>>Да и вообще — кому сейчас нужно ловить настолько мелких блох?

A>>Чай не времена 286-х!
O>Да вот в соседней ветке
Автор: system.console
Дата: 24.04.16
блохами возмущаются


Я не думаю, что можно набрать 5-10 секунд такими блохами.
Десять миллиардов команд чтобы переключить канал?
Я не думаю, что это от того, что функции короткие.

Течёт вода Кубань-реки куда велят большевики.
Re[3]: Функции должны быть компактными
От: alpha21264 СССР  
Дата: 25.04.16 21:16
Оценка: 2 (1)
Здравствуйте, dosik, Вы писали:

D>Здравствуйте, alpha21264, Вы писали:


A>>Да и вообще — кому сейчас нужно ловить настолько мелких блох?

A>>Чай не времена 286-х!

D>Ну как сказать ))) Сегодня ты пишешь клиентские десктопные приложения, а завтра на тебе, и ты уже ARM программист, и там рассказывай про блох )))


Не чини, пока не сломалось. Вот когда будешь писать для АРМ-а вот тогда... Всё равно дело будет не в блохах.

Течёт вода Кубань-реки куда велят большевики.
Re[5]: Функции должны быть компактными
От: __kot2  
Дата: 25.04.16 21:18
Оценка: -2
Здравствуйте, T4r4sB, Вы писали:
TB>Здравствуйте, __kot2, Вы писали:
__>>функция должна делать одно дело. 30 строк — очень редко когда это что-то прямо одно такое. бывает, но редко. чаще всего там все-таки несколько действий, каждое из которых имеет смысла выделить в отдельную ф-ию.
TB>Да скорее задолбаешься контекст функции передавать в подфункции.
контекст должен быть сгруппирован в структуры
Re[2]: Функции должны быть компактными
От: nigh  
Дата: 25.04.16 21:36
Оценка:
Здравствуйте, dosik, Вы писали:

D>А что тогда с высоконагруженными приложениями, где кроме как на себя, даже на компилятор положиться нельзя?

А что такое "высоконагруженые приложения", пример можно? Или вы чисто теоретически интересуетесь?
Re[2]: Функции должны быть компактными
От: IT Россия linq2db.com
Дата: 25.04.16 22:04
Оценка: +4 :))) :))
Здравствуйте, __kot2, Вы писали:

__>любой человек, который до сих пор пишет ф-ии в столбик строк по 30, вставляя туда комменты просто неквалифицирован и его нельзя допускать до написания реального кода


Считаю такое мнение признаком недопереквалифицированности.
Если нам не помогут, то мы тоже никого не пощадим.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.