Delphi анонимные методы - за и против. Хорошая практика при использовании замыканий (методов анонима) в Delphi - PullRequest
7 голосов
/ 19 октября 2011

В моей команде есть коллега, который активно использует замыкания в наших проектах, разработанных в Delphi.Лично мне это не нравится, потому что делает код труднее для чтения, и я считаю, что замыкания должны использоваться ТОЛЬКО тогда, когда они вам нужны.

С другой стороны, я прочитал Может кто-то объяснить анонимныйметоды для меня? и другие ссылки, связанные с этим, и я принимаю во внимание, что, возможно, я ошибаюсь, поэтому я прошу вас привести несколько примеров, когда лучше использовать замыкания вместо старогоПодход -fashion (без использования замыканий).

1 Ответ

11 голосов
/ 19 октября 2011

Я считаю, что этот вопрос требует очень субъективного суждения.Я разработчик Delphi старой школы и склонен с вами согласиться.Замыкания не только увеличивают определенные риски (как указывает Дэвид Х в комментариях), они также снижают читабельность для всех классически обученных разработчиков Delphi.Так почему они вообще были добавлены в язык?Например, в Delphi XE функция форматирования синтаксиса и замыкания не работали вместе, и это увеличило мое недоверие к замыканиям;Сколько вещей добавлено в компилятор Delphi, что IDE не была полностью обновлена ​​для поддержки?Вы знаете, что вы недовольный старый таймер, когда публично признаете, что были бы счастливы, если бы язык Delphi был заморожен на уровне Delphi 7 и никогда больше не улучшался.Но Delphi - это живой, мощный, развивающийся синтаксис.И это хорошо.Повторите это для себя, когда вы обнаружите, что старая рукоятка начинает действовать.Попробуйте.

Я могу вспомнить как минимум десять мест, где методы Anonymous действительно имеют смысл, и, следовательно, причины, по которым вы должны их использовать, несмотря на мой предыдущий комментарий, что я им не доверяю.Я укажу только те два, которые я решил использовать лично, и ограничения, которые я налагаю на себя, когда использую их:

  1. Сортировка методов в классах контейнеров в Generics.Collectionsпримите анонимный метод, чтобы вы могли легко обеспечить логику сортировки без необходимости писать обычную (неанонимную) функцию, которая совпадает с той же сигнатурой, что и метод сортировки.Новый синтаксис дженериков идет рука об руку с этим стилем, и хотя он поначалу кажется вам чуждым, он растет для вас и становится, если не совсем удачным, по крайней мере более удобным, чем альтернативы.

  2. Методы TThread, такие как Synchronize, перегружены, и помимо поддержки одного TThreadMethod в качестве параметра Thread.Synchronize(aClassMethodWithoutParameters), мне всегда было больно получать параметры в этот метод синхронизации.теперь вы можете использовать замыкание (анонимный метод) и передавать параметры в.

Пределы, которые я рекомендую при написании анонимных методов:

A.У меня есть личное эмпирическое правило, состоящее только из ОДНОГО замыкания для каждой функции, и всякий раз, когда их больше одного, рефакторинг этого бита кода для его собственного метода.Это удерживает цикломатическую сложность ваших «методов» от сумасшествия.

B.Кроме того, внутри каждого замыкания я предпочитаю иметь только один вызов метода и его параметры, и если в итоге я пишу гигантские блоки кода, я переписываю их как методы.Замыкания для захвата переменных, а не карт-бланш для написания бесконечно скрученного спагетти-кода.

Пример сортировки:

 var     
   aContainer:TList<TPair<String, Integer>>;  
 begin   
  aContainer.Sort(    
    TMyComparer.Construct(
      function (const L, R: TPair<String, Integer>): integer
      begin
        result := SysUtils.CompareStr(L.Key,R.Key);
      end ) {Construct end}   );  {aContainer.Sort end}  
 end;

Обновление: один комментарий указывает на «языковое уродство», я полагаючто увеличение относится к разнице между необходимостью писать:

  x.Sort(     
    TMyComparer.Construct(
      function (const L, R: TPair<String, Integer>): integer
      begin
        result := SysUtils.CompareStr(L.Key,R.Key);
      end )   ); 

Вместо следующего гипотетического синтаксиса с типом утки (или я бы сказал, выведенные типы), который я только что изобрел здесь для сравнения:

  x.Sort( lambda( [L,R], [ SysUtils.CompareStr(L.Key,R.Key) ] ) )

Некоторые другие языки, такие как Smalltalk и Python, могут писать лямбды более компактно, потому что они динамически типизированы.Например, потребность в IComparer в качестве типа, передаваемого методу Sort () в контейнере, является примером сложности, вызванной интерфейсом, которому должны следовать строго типизированные языки с обобщениями для реализации таких черт, как упорядочение.Требуется для сортировки.Я не думаю, что был хороший способ сделать это.Лично я ненавижу видеть процедуру, начинайте и заканчивайте ключевые слова в круглых скобках вызова функций, но я не вижу, что еще можно было бы разумно сделать.

...