Pull to refresh

Comments 57

анти фабричный метод:

public void FactoryMethod(...)
{

}
Однозвенная архитектура, MVC, слабая связанность, делегаты и feature driver development — смешать, но не взбалтывать.

Достаточно забавная архитектура для построения однозвенных (desktop) приложений большого и очень большого объема. Готовится следующим образом:

1. Приложение делится на инкапсулированные объекты, которые вообще ничего не знают друг о друге. Для деления хорошо подходит парадигма MVC — логика программы в кучке Model объектов, графический интерфейс в большой кучке View объектов, небольшая кучка Controller для промежуточной логики.

2. Каждому объекту назначаются входящие сигналы (методы) и исходящие сигналы (делегаты).

3. Выделяется специальный файл «точки сборки». В этом файле находится код создания всех объектов. После того как объекты созданы, на кажду фичу программы (например, «по клику на крестик закрыть окно») пишется метод, который связывает исходящие сигналы и входящие сигналы учавствующих в этой фиче объектов. Запуск программы состоит из последовательного вызова функций для создания всех фичей.

Паттерн позволяет легко поддерживать программу — для того, чтобы найти как в ней реализована соответствующая фича достаточно открыть файл с «точкой сборки» и найти соответствующую фиче функцию. Также паттерн сам по себе активно сопротивляется антипаттернам «банка с червями» и «god object» — при увеличении какого-либо объекта в размерах он достаточно просто разделяется на несколько более мелких объектов.

Паттерн пока экспериментальный, но за последние несколько лет разработки достаточно хорошо зарекомендовал себя в проектах от 1 миллиона строк кода.
Паттерн Singleton.
На тебя вешают кучу работы (твоей и не твоей), а ты, блин, один и нихрена не можешь разделиться на пять человек и сделать её вовремя.
UFO just landed and posted this here
Антипаттерн Процедурщина.

Встречается у 90% новичков, перешедших с процедурных языков (С, Pascal) на ООЯ (Чаще всего сейчас это Java и C#).
Заключается в том, что их project — это один класс, с кучей абсолютно несвязанных друг с другом методов, экспоненциально растущим числом полей этого класса, и наконец самими методами — over 200 строк плохо читабельного, негибкого кода.

Лечить правильными паттернами и осознанием ООП.)
Это называется паттерн «God Object», заключается в введении особого объекта, который знает абсолютно всё обо всём в проекте и всё делает.
Паттерн «конкурс паттернов»
Предложить участникам вспомнить «самые полезные (или наоборот вредные), самые оригинальные, самые правдивые, самые нелепые, самые неожиданные» велосипеды, а в конце конкурса, когда станет ясно ничего нового не придумано, объявить победителем тех, кто рассказал про дерижабли и подводные лодки.
Меджу тем, это был пример паттерна «безграмотный комментарий».
«победителями», «дирижабли» и тире после «ясно», конечно же.
Буду участвовать в двух номинациях :)
а это был пример паттерна «откомментирую свой комментарий»
Антипаттерн «Программирование с помощью перестановок».
Заключается в том, что берётся неработающий кусок кода и маленькими изменениями программист пытается заставить его работать, изменения повторяются до тех пор, пока не получится нужный результат. Например код if(a[i++] < b[i]) ... будет меняться на if(a[i] < b[i]) ... или if(a[i++] <= b[i]) ... или if(a[i+1] <= b[i]) ... или if(a[i] <= b[i-1]) ... до тех пор, пока не получится :)
Используется обычно для того, чтобы правильно попасть на граничные условия, или же в совершенно непонятном коде.
Высылаю свой паттерн ExceptionHandler, который я часто использую. Паттерн используется когда необходимо быстро написать какое-нибудь приложение, которое работает, например с сетью.

Проблема

Нередко бывают случаи когда обрывается связь с сетью, иногда сервер перестает отвечать. Как правило, такие ошибки не повторяются. В итоге возникает ситуация, когда приложение, которое нужно написать быстро, валится из-за случайной сетевой ошибки.

Решение

Самый простой способ реагирования на такую ошибку — попробовать еще раз. Вдруг получится? Можно, конечно, написать try...catch, потом попробовать еще раз. Но со временем я понял что мне нужны два параметра: 1) сколько раз пробовать 2) сколько времени ждать после ошибки.

В итоге решение проблемы сводится к такому простому коду:

  1.                 // пробовать 5 раз, после exception ждать 1 секунду
  2.                 ExceptionHandler exHandler = new ExceptionHandler(51000);
  3.                 exHandler.Execute(delegate()
  4.                 {
  5.                     bResult = anyOperationWithNetwork();
  6.                 });
  7.  


Если было более 5 попыток, то выбрасывается исключение, которое привело к этой ошибке.

Сам класс:

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4.  
  5. namespace Patterns
  6. {
  7.     public delegate void ExceptionHandlerDelegate();
  8.  
  9.     class ExceptionHandler
  10.     {
  11.         private int maxExceptionCount;
  12.         private int sleepTime;
  13.         public ExceptionHandler(int maxExceptionCount, int sleepTime)
  14.         {
  15.             this.maxExceptionCount = maxExceptionCount;
  16.             this.sleepTime = sleepTime;
  17.         }
  18.  
  19.         public void Execute(ExceptionHandlerDelegate del)
  20.         {
  21.             int currentExceptionCount = 0;
  22.             bool success = false;
  23.  
  24.             do
  25.             {
  26.                 try
  27.                 {
  28.                     del();
  29.                     success = true;
  30.                 }
  31.                 catch (Exception ex)
  32.                 {
  33.                     currentExceptionCount++;
  34.  
  35.                     if (currentExceptionCount > maxExceptionCount)
  36.                         throw ex;
  37.                     else
  38.                         if (sleepTime > 0)
  39.                             System.Threading.Thread.Sleep(sleepTime);
  40.                 }
  41.             } while (!success);
  42.         }
  43.     }
  44. }
  45.  


Хочу получить приглашение, сам сертифицированный .NET разработчик (MCAD.NET) с 2005 года, архитектор ПО и большой поклонник Patterns & Practices.
Мда… Хуже может быть только простой цикл
while (i++ < 5)
{
try
{
// Do something
bool result =…

if (result)
{
break;
}
}
catch
{
}
Thread.Sleep(2000);
}
или комментирование без аргументов. Их я, правильно ли понимаю, не будет? :)
Будут конечно. Любая ситуация, выходом из которой становиться такой, простите, велоспед, нуждается в тщательном анализе. Возможно вы неверно использовали API другиха разработчиков/компаний/продуктов. В любом случае код, в котором такое встречается, выглядит, как минимум непрофессионально. Примеров такого — масса. К сожалению даже такие гиганты как Майкрософт постоянно что-нибудь этакое да штампанут. Нарпример CodeLook для Visual Studio. Там в главном окне обновление происходит не по событию выделения элемента в списке а по таймеру. Причем повезло если в его такт попал — иначе жди следующего Timer_Tick 10 секунд ;)
Да и КСТАТИ! :) У вас что это выполняется в основном потоке? Т.е. вы на одну секунду замораживаете UI вот этим вызовом new ExceptionHandler(5, 1000);?
Хотел сказать замораживаете UI на период от 1 до 5 секунд :)
Ну и напоследок еще два момента
1) Не совсем понял UseCase вот этого кода: bResult = anyOperationWithNetwork();… Зачем нужно bResult? Где оно потом используется?
2) Зачем вы объявили свой делегат ExceptionHandlerDelegate когда есть готовый public delegate void Action(), а также public delegate void Action(T obj) и масса других с разным количеством параметров?
Прошу прощения за опечатку, уточню уж, раз оказия вышла :)
public delegate void Action(T obj)
public delegate void Action<T1, T2>(T1 arg1, T2 arg2)
public delegate void Action<T1, T2, T3>(T1 arg1, T2 arg2, T3 arg3)
public delegate void Action<T1, T2, T3, T4>(T1 arg1, T2 arg2, T3 arg3, T4 arg4)

Любая ситуация, выходом из которой становиться такой, простите, велоспед, нуждается в тщательном анализе

Я ясно дал понять в самом начале «используется когда необходимо быстро написать какое-нибудь приложение». Что лучше — потратить три часа на тщательный анализ или за 5 минут написать то, что будет работать? Сразу вспоминается афоризм "Программист — это человек, который может решить неизвестную вам проблему, способом который вы не поймете". Вы как раз и предлагаете усложнение. Вместо того, чтобы написать какую-то программу быстро и просто, вы начинаете усложнять, тщательно анализировать, таким образом тратите на простую задачу совершенно ненужное количество усилий и времени.
В любом случае код, в котором такое встречается, выглядит, как минимум непрофессионально

вам шашечки или ехать? Опять же, речь идет о «быстро». Если программа в 100 строк, то усложнение это как раз и будет антипаттерн. Вместо того, чтобы написать простую программу, человек начинает городить огород. К тому же, ваше определение «непрофессиональности» дальше слов не заходит.
У вас что это выполняется в основном потоке? Т.е. вы на одну секунду замораживаете UI вот этим вызовом

Вы предъявляете претензии к функции Sleep. Проблема использования кода в графическом UI лежит за пределами этой статьи. Впрочем, не в моей практике создавать крокодила, который будет летать по воздуху, плавать под водой и который будет обладать кучей других ненужных функций. Если программисту надо, он сам может модифицировать код как хочет.
Не совсем понял UseCase вот этого кода: bResult = anyOperationWithNetwork();… Зачем нужно bResult?

просто код из рабочего проекта, где функция возвращала какой-то результат.
Зачем вы объявили свой делегат… и масса других с разным количеством параметров

Опять же, предъявляете претензию к .NET. Интересно, зачем вообще Microsoft сделали возможность объявлять свои делегаты, ведь есть уже масса других с разным количеством параметров!

осталось подкрепить слова делом и привести пример в заданном контекте, и мы посмотрим на вашего франкенштейна.
>Вместо того, чтобы написать какую-то программу быстро и просто, вы начинаете тщательно анализировать

«Что тут думать — прыгать надо!»
>> catch (Exception ex)
А если это было исключение, не связанное с сетью? Может это OutOfMemory? Или StackOverflow? Или ThreadAbortException? А может просто программа криво написана? А что если каждый вызов делегата приводит к сайд-эффектам?

>>throw ex;
Прощай callstack
Или еще веселый вариант: при обращении по сети удаленный хост недоступен и мы получаем исключение TimeOutException через время t (допустим 30 секунд). Соответственно при применении вышеописанного решения пользователь будет ждать в 5 раз больше — 2.5 минуты.
Обычно я не заморачиваюсь на таких веселых вариантах. Я не говорю, что код универсальный, я ясно дал понять где его можно использовать.

То, что вы предлагаете обрабатывать все типы исключений, OutOfMemory, StackOverflow, ThreadAbortException в программе чуть сложнее «Hello, world» называется никак иначе как «из пушки по воробьям».

Заказчик не обрадуется, если ему нужно написать просто и быстро (как я уже сказал в своем первом сообщении) программу на один раз, а вы будете его лечить своими OutOfMemory, которые случаются на его системе с оперативной памятью в 4Гб раз в столетие.

Опять же, много слов, мало дела. Предложите решение проблемы лучше. Решение не словесное, а подкрепленное кодом. Тогда с вами можно будет подискутировать. А так это похоже на бревно в своем глазу.
я ясно дал понять где его можно использовать.

Если надо быстро напедалить говнокода?

То, что вы предлагаете обрабатывать все типы исключений, OutOfMemory, StackOverflow, ThreadAbortException в программе чуть сложнее «Hello, world» называется никак иначе как «из пушки по воробьям».

А где я предлагал обрабатывать OutOfMemory и прочие? Обрабатывать надо только те исключения, которые мы ожидаем. В случае с сетью вообще ничего не надо обрабатывать в backend коде, а UI пусть (если он есть) красивый меседжбокс нарисует. Если очень хочется можно автоконнект в UI сделать. А поддержкой надежности пусть занимается TCP/IP. Если же у нас есть кривой сервер, который сам по себе то работает, то не работает, то для него можно сделать костыль (и ловить там не любой Exception, а конкретный, именно тот, который прилетает, когда сервер обычно недоступен). Но возводить этот кривой костыль в ранг паттерна — это слишком.
Ну так что-то кроме слов будет?
см. «проблема» в комменте 1-ого уровня.
см. «проблема» в комменте 1-ого уровня.


Проблема там описана излишне обобщенно. Ну вот, например, там написано: «Нередко бывают случаи когда обрывается связь с сетью». Что значит фраза «обрывается связь с сетью»? IP пакет не дошел? Дак это TCP/IP разруливает. Или в течении длительного времени были потеряны все IP пакеты и TCP/IP пришел к выводу, что связи нет? Ну тогда нет смысла долбиться повторно вызывая операцию, делая вид, что мы умнее тех, кто реализовывал TCP/IP. Если реализация TCP/IP считает, что связи нет, то значит её действительно нет.

«иногда сервер перестает отвечать» — ок, это уже ближе к делу. В данном случае мы имеем дело с кривым сервером. Если мы не имеем доступа к самому серверу, то кривость сервера можно попытаться разрулить другой кривостью на стороне клиента. Допустим, при обращении к серверу, когда он лежит вылетает исключение ServerDownException. В этом случае в цикле с повторным выполнением операции надо писать не catch(Exception...), а catch(ServerDownException ...)
«иногда сервер перестает отвечать» — ок, это уже ближе к делу. В данном случае мы имеем дело с кривым сервером
ну вот даже на такой простой вещи можно сказать что вы теоретик. Если сервер перестал отвечать, то это не означает, что мы имеем дело с кривым сервером. На GPRS соединении очень часто что-то работает не так. Поэтому ваш ServerDownException во-первых, работает только в каком-то конкретном случае. Во-вторых, имеет плохое название. В-третьих, непонятно как он будет реализован, опять же — одни слова. В-четвертых, он не покрывает всех случаев, по которым сервер может не отвечать.

В итоге пока вы будете с этим разбираться, я уже 10 раз напишу то, что хотел.

Ну тогда нет смысла долбиться повторно вызывая операцию, делая вид, что мы умнее тех, кто реализовывал TCP/IP
Шедевр. Можете еще не нажимать F5 в браузере, когда что-то не открывается, не надо делать вид, что вы умнее тех, кто реализовал TCP/IP или писал браузер.

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

ну вот даже на такой простой вещи можно сказать что у вас слабая аргументация, так как переходите на личности

Если сервер перестал отвечать, то это не означает, что мы имеем дело с кривым сервером. На GPRS соединении очень часто что-то работает не так.


Что именно работает не так?

Поэтому ваш ServerDownException во-первых, работает только в каком-то конкретном случае.


В этом и смысл. Мы обрабатываем только те ошибки, которые мы знаем, как надо обрабатывать. Непредусмотренные ошибки, которые мы не планировали обрабатывать (например, OutOfMemoryException, или AuthorizationException и пр.) не надо обрабатывать. Потому что мы ничего осмысленного в случае их возникновения сделать не сможем. Долбиться многократно в стену, надеясь, что у нас сами собой появятся права на доступ к сети, или пользователь в это время воткнет еще одну планку памяти смысла нет. Если не знаешь, что надо делать — не делай ничего. Пусть исключение дальше летит.

Во-вторых, имеет плохое название. В-третьих, непонятно как он будет реализован

Это неважно. Название просто от балды. Смыл в том, что обрабатывать надо только те ситуации, которые мы знаем, как обрабатывать.

В-четвертых, он не покрывает всех случаев, по которым сервер может не отвечать.

Вот и отлично. Что поможет нам в результате разруливать разные ошибочные ситуации в будущем при саппорте, когда ошибки не будут маскироваться и зашумляться кодом, который не был спроектирован на обработку этих ошибок, но, тем не менее, зачем-то их обработал.
Вот простейший пример возможных проблем: вызываем Вашим способом метод WCF сервера. Первый вызов метода возвращает подробную ошибку с хорошим описанием, что произошло, после чего прокси благополучно переходит в faulted state и мы забываем исходное исключение. Последующие вызовы генерируют исключение, что прокси находится в faulted state, с текстом которого к нам приходит клиент. Как будем разруливать ситуацию, учитывая, что в тексте результирующего исключения не содержится вообще никакой полезной информации, и исключение с полезной информацией мы благополучно проигнорировали?
Шедевр. Можете еще не нажимать F5 в браузере, когда что-то не открывается, не надо делать вид, что вы умнее тех, кто реализовал TCP/IP или писал браузер.
Если бы Вы разрабатывали браузер, то тоже, наверное сделали бы, чтобы браузер пять раз пытался загрузить страницу перед тем, как показать пользователю ошибку, да? :))) Как думаете, почему браузеры так не поступают? Видимо, просто их разработчики паттерна не знают :)
Когда человек в результате констуктивной критики бросается минусовать посты критикующих — это говорит о его неуравновешенности. Зачем вам это было нужно? Это же просто смешно.
Это провокация? Просто кто-то это уже сделал за меня. Смешно смотреть на попытки выискать какую-то подпольную правду, может просто кто-то несогласен? В любом случае советую не обращать на это внимания. Лучше комментируйте в следующий раз аргументировано, это намного важнее, чем выявление минусовщика комментов.
Это не вы? Тогда прошу прощения за необоснованное обвинение. Проехали, ок?
Антипаттерн «Переусложнение». Встречается у начинающих программистов у которых руки горят все попробовать — Reflection, WCF, WPF. Причем при этом начисто забывают об основных принципах проектировании, не говоря уже о паттернах. Пример: у нас работает новичок. Ему поручили вывести в заголовке формы имя текущего редактируемого объекта. Это вылилось в:
1) Абстрактный параметризованный класс модели представления, который принимал тип редкатируемого объекта:
public class EditEntityWithNameViewModel: ViewModelBase {… }
2) В этом классе был добавлен метод protected string GetEntityName(T model, string propertyName), который с помощью механизмов отражения лез в model и получал значение свойства с именем propertyName.
3) Затем классы Entity1ViewModel и Entity2ViewModel были унаследованы от закрытых дженерик-классов EditEntityWithNameViewModel и EditEntityWithNameViewModel соответственно и в них перегружены свойства Description примерно таким образом:
public override string Description // Entity1ViewModel
{
get { return GetEntityName(this.Model, «GroupName»)}
}

public override string Description // Entity2ViewModel
{
get { return GetEntityName(this.Model, «ObjectName»)}
}

На вопрос зачем эти свистопляски с отражением и промежуточным бесполезным дженерик-классом с одним методом GetEntityName он затруднился ответить :) Сказал что-то вроде «так ведь рефлекшн это круто его советуют использовать». Правда кто советут, он опять-таки затруднился ответить.
На самом деле решение было очень простым и укладывалось в две строчки кода, которые надо было добавить в конструкторы обоих классов:

public Entity1ViewModel(Entity1 model)
{
this.Description = model.GroupName;
}

public Entity2ViewModel(Entity2 model)
{
this.Description = model.ObjectName;
}
Небольшая опечаточка. Класс EditEntityWithNameViewModel: ViewModelBase {… } конечно же.
Мда… вряд ли это тянет на определение «антипаттерн». Просто частный случай ИМХО, который даже нет смысла рассматривать.
20 тысяч? Мне всегда было интересно: неужели обычные девелоперы платят такие деньги за посещение этих мероприятий?? Или все места раздаются такими вот конкурсами? Ведь руководство же не пойдет смотреть на библиотечку по программированию. Только если софтверные компании, а там, на мой взгляд, дешевле погуглить.
В рашке да, такое бывает редко. В US, наоборот, встречается очень часто. Формат был просто перенесен с US на нашу реальность.
«В рашке да, такое бывает редко. В US, наоборот, встречается очень часто» — Это тоже паттерн
Гуглят обычно российские программисты, так как привыкли полагаться на себя. Американским же разработчикам, насколько я заметил, проще получить информацию в доступной форме — в виде презентации, в личном общении с разработчиками какого-либо фреймворка на конференции. И, да — они готовы за это платить большие деньги. Потому что в их случае профит от полученных знаний очевиднее.
На такие мероприятия обычно приходят девелоперы и архитекторы (чаще всего руководители отделов), чье участие оплачивает компания. В прошлом году где-то 12 человек от Касперского пришло, много было девелоперов из Яндекса. Ценность сего саммита в том, что вы можете познакомиться и пообщаться с командой Patterns & Practices, поделиться конкретной проблемой и получить советы по ее решению. Причем не только на саммите, но и после него вам окажут поддержку
Стретегия синхронизации.

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

public interface IGuard
{
	IDisposable Aquire();
}

Могут быть, например, следующие реализации данного интерфейса:

MutexGuard — захватить объект может только один поток
ReaderGuard — при захвате данного гарда предоставляется доступ на чтение
WriterGuard — при захвате данного гарда предоставляется доступ на запись
NotSynchronizingGuarg — гард, который ничего не делает

При этом клиентский код будет выглядеть всегда одинаково. Ему безразлично, какая именно стратегия синхронизации используется:

void Foo(IBar bar)
{
	using(bar.SomeGuard.Aquire())
	{
		...
	}
}

Контроль уникальных идентификаторов в больших проектах.

Предположим есть клас А и клас Б, которые генерируют определенные сообщения. Каждое сообщение содержит константу. Эта константа позволяет различать отдельные сообщения.

Решение в лоб. Можно создать БОЛЬШОЙ список констант, который будет содержать все константы сообщений.
Вытекающая проблема — с добавлением новых сообщений в списке можно потеряться и, например, продублировать значение констант для разных сообщений.

Вариант решения. Создавать в коде только контейнеры для идентификаторов сообщений, заполнять их с помощью Reflection на старте программы.

Как выглядит:

Контейнер идентификатора сообщения и атрибут, помечающий класс как содержащий в себе набор идентификаторов сообщений:

[AttributeUsage(AttributeTargets.Class, Inherited = true, AllowMultiple = false)]
 public class EventIDAttribute : Attribute
 {
 };

 public class EventID
 {
  public EventID(int id, string name)
  {
   ID = id;
   Name = name;
  } 

  public int ID
  {
   {private set; get }
  }

  public string Name
  {
   {private set; get }
  }
 };


Класс, отвечающий за инициализацию контейнеров сообщения на старте программы:

public class EventInitialiser
  {
    private static int _id;

    public static void Init()
    {
      foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
      {
        foreach (Type type in assembly.GetTypes())
        {
          if (IsEventClass(type))
          {
            FieldInfo[] fields = type.GetFields();
            foreach (FieldInfo fieldInfo in fields)
            {
              if (fieldInfo.FieldType == typeof(EventID))
              {
                int newID = System.Threading.Interlocked.Increment(ref _id);
                EventID newEventID = new EventID(newID,
                  string.Format("{0}.{1}", fieldInfo.ReflectedType.FullName, fieldInfo.Name));
                
                fieldInfo.SetValue(null, newEventID);
                EventIDCache.AddEventToCache(newEventID);
              }
            }
          }
        }
      }
    }

    private static bool IsEventClass(Type type)
    {
      object[] attributes = type.GetCustomAttributes(typeof(EventIDAttribute), true);
      return (null != attributes && attributes.Length > 0);
    }
  };


И наконец, группы идентификаторов сообщений. Они могут находиться в разных пространствах имен, библиотеках. Но их значения с таким подходом — всегда будут уникальны.

  [EventID]
  public class SomeUIEventIDs
  {
    public static EventID SomeButtonWasClicked;
    public static EventID SomeTextWasTyped;
  };

  [EventID]
  public class SomeCoreEventIDs
  {
    public static EventID SomeErrorOccured;
  };


Реализация транспортного слоя уже вещь более житейская, ее упустим. Вот пример проверки идентификатора пришедшего сообщения в некотором обработчике:

  public void ProcessMessage(EventID eventId, object sender, EventArgs args)
    {

      if (SomeUIEventIDs.SomeButtonWasClicked.ID == eventId.ID)
      {/*Operation 1*/      }

      else if (SomeUIEventIDs.SomeTextWasTyped.ID == eventId.ID)
      {/*Operation 2*/      }

      else if (SomeCoreEventIDs.SomeErrorOccured.ID == eventId.ID)
      {/*Operation 3*/      }     
    }

Возможно, я не совсем правильно понял проблему, но почему бы идентификатор события не сделать Guid и инициализировать как Guid.NewGuid()
Можно и гид, и уникальную строку генерировать. Смысл в том, чтобы генерировать при запуске, а не хардкодить константы до компиляции.
Возможно, я не совсем правильно понял проблему, но почему бы идентификатор события не сделать Guid и инициализировать как Guid.NewGuid()
прошу прощения, промазал :)
Опасный антипаттерн: слой, который отвечает за обработку ошибок, записи их в лог => сам никак не блокирует свои ошибки, и при попытке записать текст ошибки в лог — передает ошибку наверх, где никто её не обрабатывает и всё падает при этом :-D
Сегодня столкнулся с еще одним паттерном у некоторых людей из нашей команды — они боятся большого количества кода, разделенного по функциональности и размещенного в различных слоях программы.
В итоге — вместо разделения кода на несколько классов… структур… слоев… делают всё в одном месте — в одном большом файле с одним единственным классом.
Все познается в сравнении и иногда, чтобы понять ценность паттерна нужно оценить вред соответствующего ему анти-паттерна. Вот некоторые примеры комбинаций паттерн/анти-паттерн.

Паттерн «Сделать наспех и сбежать — преступление» («Commit-and-run is a crime», Niclas Nilsson) — внесение изменений в код с учетом всех возможных последствий.
Анти-паттерн «Ползущий улучшизм» («Creeping featurism») — добавление новых улучшений в ущерб качеству системы.

Паттерн «Одна строчка рабочего кода стоит 500 строк спецификации» («One line of working code is worth 500 of specification», Allison Randal) — ни один дизайн не бывает идеальным с самого начала, любой дизайн подвержен изменениям по мере реализации.
Анти-паттерн «Аналитический паралич» («Analysis paralysis») — выделение непропорционально больших усилий в фазе анализа проекта.

Паттерн «У каждого есть свои слепые пятна» (Dave Quick) — «слепые пятна» — слабости и проблемы, которые трудно принять. Люди, готовые сообщить неприятную правду — драгоценный ресурс.
Анти-паттерн «Я тебе это говорил» («I told you so») — когда игнорируется предупреждение эксперта, являющееся оправданным.

Паттерн «Предоставьте разработчикам независимость» (Phillip Nelson) — независимость позволит разработчикам продемонстрировать свои навыки и проявить творческие способности.
Анти-паттерн «Драконовские меры» («Management by perkele») — военный стиль управления без толерантности к диссидентству.

Паттерн «Остерегайтесь хороших идей» (Greg Nyberg) — хорошие идеи раздувают масштаб проекта, повышают сложность и требуют лишних усилий на включение в приложение того, что не нужно для достижения бизнес-цели.
Анти-паттерн «Рыцарь на белом коне» («Knight in shining armor») — проявляется, когда личность появляется на сцене и пытается починить всё, без сообщений о том, какие изменения он/она сделал(а)/сделает и почему.
Антипаттерн «Паттерн ориентированная архитектура». Он возникает в системах, разработанными архитекторами, которые недавно прочитали и переварили книгу по архитектурным паттернам (или сходили на конференцию) и пришли к заключению, что применение паттернов – ключ к удачной архитектуре. Вместо того, что бы использовать один наиболее подходящий паттерн, реализуются все паттерны, которые могут быть применены, создавая огромную систему, способную свести с ума.
ппц! Других слов не подобрать! Вопрос топикстартеру — на каком основании принимали решение? Чтобы было меньше слов и больше плюсов? Прошу ответить.
На основе концепции, логики, подхода к понятию паттерн. Код в данном случае — не главное. Спасибо за участие! Насколько я знаю, ребята из КарьерЛаба готовы предложить Вам скидку на участие
Конечно, больше слов, меньше дела :) Какой код может быть в паттернах, что еще за вдор? Люди, которые написали какой-то код, не получили ничего, а копипастеры (не будем показывать пальцем) пойдут на саммит, который им нахрен не нужен.

Конечно, я и сам не получил бесплатное приглашение, но я возмущаюсь не поэтому. Конкурс был проведен плохо. Да и вряд ли кто-то поедет из отдаленных уголков России, в итоге приглашения пропадут зря. В итоге получается lose-lose situation.
Sign up to leave a comment.