Архив за месяц: Январь 2019

Максимально ограничивайте область Generic-а и не используйте в перегрузках методов

Вчера исправлял баг, проявил он себя весьма интересно. Но продемонстрировать его можно на достаточно простом примере:

static void Main(string[] args)
{
    Print(new[] { 1, 2, 3 });
    Console.ReadKey();
}

static voidPrint<T>(T t)
{
    Console.WriteLine(t);
}

static voidPrint<T>(IEnumerable<T> t)
{
    foreach (var item in t)
    {
        Console.WriteLine(item);
    }
}
При запуске вместо ожидаемых 1, 2, 3 мы увидим:
Т.к. мы не задали ограничений на T, то и IEnumerable тоже приводится к T объявленному в первом методе. Накладывание ограничений на T позволило бы узнать о этой проблеме на этапе компиляции. Изменим код:
class Demo
{
    public int X { get; set; }
}

static void Main(string[] args)
{
    Print(new[] { new Demo { X = 1 }, new Demo { X = 2 }, new Demo { X = 3 } });
    Console.ReadKey();
}

static voidPrint<T>(T t) where T : Demo
{
    Console.WriteLine(t);
}

static voidPrint<T>(IEnumerable<T> t) where T : Demo
{
    foreach (var item in t)
    {
        Console.WriteLine(item);
    }

}
В данном примере я явно указал к чему должен приводиться T (к Demo или его потомкам). И вот вместо ошибки времени выполнения, мы получаем ошибку компиляции:
Error CS0311 The type 'ConsoleApp1.Program.Demo[]' cannot be used as type parameter 'T' in the generic type or method 'Program.Print(T)'. There is no implicit reference conversion from 'ConsoleApp1.Program.Demo[]' to 'ConsoleApp1.Program.Demo'.

Как написано в заголовке, надо быть аккуратнее с Generic, максимально накладывать на них ограничения и не использовать в перегруженных методах, особенно в таком виде. А то вместо строгой типизации получим не строгую.

Что не так с качеством?

Я не очень понимаю, в какой момент произошел слом в массовом сознании, но я его наблюдаю регулярно и систематически.
Но то что слом произошел, причем совсем недавно, и не только в России, это факт. Как вам вот такие два определения качества:
1. ИСО 8402—86: Качество — совокупность свойств и характеристик продукции или услуги, которые придают им способность удовлетворять обусловленные или предполагаемые потребности потребителя.
2. ГОСТ Р ИСО 9000-2015: Качество — степень соответствия совокупности присущих характеристик объекта требованиям.
Видите разницу, под катом мои мысли на эту тему.

Ключевая разница этих определений в том, что в 86 году под качеством понимали удовлетворение потребностей потребителя, в 2015 соответствие требованиям.
И вот уже в голове голосом Райкина звучит:
-У вас к пуговицам претензии есть?
- Нет, к пуговицам претензий нет, пришиты намертво.
Аналитик отвечает только за то, чтобы в TFS (или какая у вас там система управления требованиями) появились пользовательские истории для Scrum или требования для остальных методологий. Ой, простите, Скрам это не методология, это всего лишь фреймворк, который, кстати, тоже не про удовлетворение потребностей потребителя, а про ритуальные действия, которые должны выполняться строго в соответствии с требованиями. Но не суть, аналитики написали некий текст, разработчик в соответствии с этим текстом написал функционал, инженер по тестированию проверил, все работает так, как написано в требовании. Пришиты намертво, не оторвешь. Вот только пользоваться этим нельзя. Например, по тому, что никто не подумал о реальной ситуации где это будет работать. Об обрывах связи, о больших наборах данных, о том, что пользователя выбесит вводить одно и то же значение 100 раз подряд. А это ведь я рассказываю про идеальный сценарий, с выделенной аналитикой, разработкой и тестированием.
Мы все забываем про потребителя. Причем даже не обязательно вешнего. Рассмотрим самый ужасающий пример такой забывчивости: программиста. Кто является потребителем продукта за качество которого отвечает программист? Остановитесь, подумайте. Кто? Пользователь? Отлично, если программист когда пишет код думает о пользователе, о том как будут пользоваться системой, в каком окружении она будет работать, что можно сделать, чтобы если уж не облегчить жизнь пользователю, то хотя бы не усложнить. Но в большинстве случаев нет даже этого. Ну вот в требовании написано реализовать А. Ну и что, что то что написано не удобно, ломает логику системы, да и использоваться не будет пока не сделают Б, которого даже в планах пока нет. Надо сделать А, вот и сделаю как понял, а там хоть трав.. Ну в смысле а там коммит, ревью, пуш, закрыть задачу и пойти налить кофе.
А ведь кроме несчастного пользователя потребителями труда программиста являются: инженеры по тестированию, специалисты по внедрению, специалисты технической поддержки и ПРОГРАММИСТЫ!!! И ладно, тестировщиков не жаль, админы пусть мудохаются с развертыванием как хотят, тех. поддержка? А это вообще кто такие? Но блин, как можно не думать про себя любимого? Как можно писать методы на сотни строк кода? Ты что, завтра увольняешь и больше не будешь пытаться разобраться в этом спагетти? Как можно в сложной лямбде, находящейся внутри другой лямбды, которая находится по соседству с третей лямбдой использовать имя переменной параметра i (при этом тип сущностей в итерируемой коллекции пусть будет Персона)? Ну а писать catch внутри которого ничего нет, это вообще как? Это что, желание подольше искать неуловимую ошибку?
В Кайдзен есть очень правильный постулат: "Следующий процесс – это потребитель. Вся работа представляет собой ряд процессов, и в каждом процессе имеется свой потребитель и свой поставщик. Большинство работающих в организациях людей имеют дело с внутренним потребителем. Никогда не передавайте бракованные запасные части или неверную информацию людям, участвующим в следующем процессе.".  У каждого кто занимается разработкой программного обеспечения должна постоянно в голове быть мысль: не передавать брак или неверную информацию дальше. Ведь следующий по цепочке это и ты в том числе. Сделал плохо сегодня, придется переделывать завтра. Не предусмотрел сегодня, придется переделывать завтра. Как и с любым принципом, не надо перегибать палку. Не надо доводить мысль до абсолюта, вот пока не доведу до хрустального совершенства, на следующий этап не пущу. Но надо делать максимально хорошо, уверяю вас, плохо оно само получится.
P.s. Сорри за такую сумбурную портянку текста, наболело что-то...

Что не так с качеством?

Я не очень понимаю, в какой момент произошел слом в массовом сознании, но я его наблюдаю регулярно и систематически.
Но то что слом произошел, причем совсем недавно, и не только в России, это факт. Как вам вот такие два определения качества:
1. ИСО 8402—86: Качество — совокупность свойств и характеристик продукции или услуги, которые придают им способность удовлетворять обусловленные или предполагаемые потребности потребителя.
2. ГОСТ Р ИСО 9000-2015: Качество — степень соответствия совокупности присущих характеристик объекта требованиям.
Видите разницу, под катом мои мысли на эту тему.

Ключевая разница этих определений в том, что в 86 году под качеством понимали удовлетворение потребностей потребителя, в 2015 соответствие требованиям.
И вот уже в голове голосом Райкина звучит:
-У вас к пуговицам претензии есть?
- Нет, к пуговицам претензий нет, пришиты намертво.
Аналитик отвечает только за то, чтобы в TFS (или какая у вас там система управления требованиями) появились пользовательские истории для Scrum или требования для остальных методологий. Ой, простите, Скрам это не методология, это всего лишь фреймворк, который, кстати, тоже не про удовлетворение потребностей потребителя, а про ритуальные действия, которые должны выполняться строго в соответствии с требованиями. Но не суть, аналитики написали некий текст, разработчик в соответствии с этим текстом написал функционал, инженер по тестированию проверил, все работает так, как написано в требовании. Пришиты намертво, не оторвешь. Вот только пользоваться этим нельзя. Например, по тому, что никто не подумал о реальной ситуации где это будет работать. Об обрывах связи, о больших наборах данных, о том, что пользователя выбесит вводить одно и то же значение 100 раз подряд. А это ведь я рассказываю про идеальный сценарий, с выделенной аналитикой, разработкой и тестированием.
Мы все забываем про потребителя. Причем даже не обязательно вешнего. Рассмотрим самый ужасающий пример такой забывчивости: программиста. Кто является потребителем продукта за качество которого отвечает программист? Остановитесь, подумайте. Кто? Пользователь? Отлично, если программист когда пишет код думает о пользователе, о том как будут пользоваться системой, в каком окружении она будет работать, что можно сделать, чтобы если уж не облегчить жизнь пользователю, то хотя бы не усложнить. Но в большинстве случаев нет даже этого. Ну вот в требовании написано реализовать А. Ну и что, что то что написано не удобно, ломает логику системы, да и использоваться не будет пока не сделают Б, которого даже в планах пока нет. Надо сделать А, вот и сделаю как понял, а там хоть трав.. Ну в смысле а там коммит, ревью, пуш, закрыть задачу и пойти налить кофе.
А ведь кроме несчастного пользователя потребителями труда программиста являются: инженеры по тестированию, специалисты по внедрению, специалисты технической поддержки и ПРОГРАММИСТЫ!!! И ладно, тестировщиков не жаль, админы пусть мудохаются с развертыванием как хотят, тех. поддержка? А это вообще кто такие? Но блин, как можно не думать про себя любимого? Как можно писать методы на сотни строк кода? Ты что, завтра увольняешь и больше не будешь пытаться разобраться в этом спагетти? Как можно в сложной лямбде, находящейся внутри другой лямбды, которая находится по соседству с третей лямбдой использовать имя переменной параметра i (при этом тип сущностей в итерируемой коллекции пусть будет Персона)? Ну а писать catch внутри которого ничего нет, это вообще как? Это что, желание подольше искать неуловимую ошибку?
В Кайдзен есть очень правильный постулат: "Следующий процесс – это потребитель. Вся работа представляет собой ряд процессов, и в каждом процессе имеется свой потребитель и свой поставщик. Большинство работающих в организациях людей имеют дело с внутренним потребителем. Никогда не передавайте бракованные запасные части или неверную информацию людям, участвующим в следующем процессе.".  У каждого кто занимается разработкой программного обеспечения должна постоянно в голове быть мысль: не передавать брак или неверную информацию дальше. Ведь следующий по цепочке это и ты в том числе. Сделал плохо сегодня, придется переделывать завтра. Не предусмотрел сегодня, придется переделывать завтра. Как и с любым принципом, не надо перегибать палку. Не надо доводить мысль до абсолюта, вот пока не доведу до хрустального совершенства, на следующий этап не пущу. Но надо делать максимально хорошо, уверяю вас, плохо оно само получится.
P.s. Сорри за такую сумбурную портянку текста, наболело что-то...

Стандартизируй-делай-контролируй-воздействуй


Несколько лет назад я уже писал про цикл Деминга, он же PDCA. Но т.к. улучшать хаос не получится, перед тем как его запустить, придется воспользоваться другим циклом, циклом SDCA. В котором вместо планируй будет стандартизируй. Этот цикл, как и цикл PDCA входит в систему Кайдзен, про которую мы еще отдельно поговорим. Сегодня же предлагаю обсудить стандартизацию и сам цикл SDCA.

Начну с того, что у нас очень странно понимают стандарты. Несколько лет назад шла массовая волна внедрения Кайдзен на российских предприятиях, а так как включать голову это сложно и не интересно, то вылилось это в решения вроде: на рабочем столе разметить места для калькулятора, степлера, клавиатуры, мышки и штрафовать работников, если у них вещи находятся не на тех местах. Что мало того, что противоречит здравому смыслу, это противоречит самому Кайдзен.
Что же такое стандарт? Это способ сделать работу наиболее оптимальным способом. Т.е. с наименьшими затратами усилий, с максимальным качеством, с минимальной вероятностью ошибиться. Если у вас есть три человека, которые делают одну и ту же работу, то чем дольше они работают, чем шире спектр проблем с которыми они сталкиваются, чем чаще они включают голову, тем больше у них будет ноу-хау как сделать свою работу в наименее трудозатратном режиме. Если все эти наработки собрать, проанализировать (выбрав не только по принципу наименьших трудозатрат, но и наилучшего качества результата), и сформировать на их основе стандарт выполнения это работы, то... как повезет. Но без этого шага все остальные шаги будут бессмысленны. Пока у вас нет стандарта, вы не можете понять то что делает человек правильно или нет. Может он супер и делает все лучше всех, а может вы не можете его сравнить с остальными работниками и не понимаете его эффективность (см. картинку в начале поста).
Но ок, мы разработали стандарт, что дальше? Дальше необходимо его внедрить. Вспоминая, что любые изменения это для их участников всегда тяжело (нет возможности работать на автомате, надо включать голову, пока новый тип действий не войдет в привычку), необходимо разъяснять нужность стандарта, обучать людей работать в соответствии со стандартом, выявлять тех кто работает не по стандарту и выяснять с чем это связано. Т.е. после того как стандарт готов, начинается самая главная часть работы, добиться того, чтобы работа выполнялась в соответствии с ним.
Только после того как работа начинает выполняться в соответствии со стандартном, переходим к объективному контролю, что у нас произошло после внедрения стандарта. Улучшились ли показатели работы, уменьшилась ли вариабильность этих показателей, повысилась ли эффективность работы?
Последним шагом будет продолжение воздействия на наш стандарт. Обнаружилось падение качеств, смотрим кто отклонился от стандарта или в чем корневая причина и как мы можем изменить стандарт, чтобы такого падения избежать в будущем. Кто-то работает лучше чем все остальные, начинаем разбираться какое ноу-хау он внедрил в свою работу и вносим ее в стандарт. Выбираем в каких работах у нас еще наблюдается разброс показателей или запускаем цикл SDCA для них.
Ну и к нашему примеру с калькуляторами и наказаниями... Я не пользуюсь калькулятором, т.к. мне удобнее считать в редакторе электронных таблиц (сохраняются все промежуточные результаты, вбивая формулы, я могу в случае ошибки поправить входные данные и получить новый результат не перевводя все заново, возможность повторного использования и т.д.). Т.е. у меня есть ноу-хау которое повышает эффективность моей работы. Ко мне приходит специально обученный человек и размещает у меня на столе (скорее всего в зоне максимальной доступности, Кайдзен же борется с потерями, и время на то, чтобы достать калькулятор из стола, это потери) калькулятор. И вот лежит этот калькулятор, мешает мне, но я им не пользуюсь от слова совсем, при этом делаю свою работу быстрее и качественнее (меньше ошибок, за счет готовых формул и удобного контроля входных данных). И вот, вместо того, чтобы быть инструментов повышения эффективности, стандарт становиться средством позволяющим менеджеру пользоваться своей властью в вопросах в которых он не разбирается. А Кайдзен по поводу того, на кого надо ориентироваться в вопросах принятия решений как правильно ставит во главу не менеджера, а гембо (то где создается полезность для потребителя). И даже если внедрением практик Кайдзен достигается повышение эффективности достаточное для того чтобы убрать сотрудника из цепочки создания ценности, надо его не увольнять, а задействовать в других процессах, чтобы увеличивать возможности компании по удовлетворению внешнего спроса.

Стандартизируй-делай-контролируй-воздействуй


Несколько лет назад я уже писал про цикл Деминга, он же PDCA. Но т.к. улучшать хаос не получится, перед тем как его запустить, придется воспользоваться другим циклом, циклом SDCA. В котором вместо планируй будет стандартизируй. Этот цикл, как и цикл PDCA входит в систему Кайдзен, про которую мы еще отдельно поговорим. Сегодня же предлагаю обсудить стандартизацию и сам цикл SDCA.

Начну с того, что у нас очень странно понимают стандарты. Несколько лет назад шла массовая волна внедрения Кайдзен на российских предприятиях, а так как включать голову это сложно и не интересно, то вылилось это в решения вроде: на рабочем столе разметить места для калькулятора, степлера, клавиатуры, мышки и штрафовать работников, если у них вещи находятся не на тех местах. Что мало того, что противоречит здравому смыслу, это противоречит самому Кайдзен.
Что же такое стандарт? Это способ сделать работу наиболее оптимальным способом. Т.е. с наименьшими затратами усилий, с максимальным качеством, с минимальной вероятностью ошибиться. Если у вас есть три человека, которые делают одну и ту же работу, то чем дольше они работают, чем шире спектр проблем с которыми они сталкиваются, чем чаще они включают голову, тем больше у них будет ноу-хау как сделать свою работу в наименее трудозатратном режиме. Если все эти наработки собрать, проанализировать (выбрав не только по принципу наименьших трудозатрат, но и наилучшего качества результата), и сформировать на их основе стандарт выполнения это работы, то... как повезет. Но без этого шага все остальные шаги будут бессмысленны. Пока у вас нет стандарта, вы не можете понять то что делает человек правильно или нет. Может он супер и делает все лучше всех, а может вы не можете его сравнить с остальными работниками и не понимаете его эффективность (см. картинку в начале поста).
Но ок, мы разработали стандарт, что дальше? Дальше необходимо его внедрить. Вспоминая, что любые изменения это для их участников всегда тяжело (нет возможности работать на автомате, надо включать голову, пока новый тип действий не войдет в привычку), необходимо разъяснять нужность стандарта, обучать людей работать в соответствии со стандартом, выявлять тех кто работает не по стандарту и выяснять с чем это связано. Т.е. после того как стандарт готов, начинается самая главная часть работы, добиться того, чтобы работа выполнялась в соответствии с ним.
Только после того как работа начинает выполняться в соответствии со стандартном, переходим к объективному контролю, что у нас произошло после внедрения стандарта. Улучшились ли показатели работы, уменьшилась ли вариабильность этих показателей, повысилась ли эффективность работы?
Последним шагом будет продолжение воздействия на наш стандарт. Обнаружилось падение качеств, смотрим кто отклонился от стандарта или в чем корневая причина и как мы можем изменить стандарт, чтобы такого падения избежать в будущем. Кто-то работает лучше чем все остальные, начинаем разбираться какое ноу-хау он внедрил в свою работу и вносим ее в стандарт. Выбираем в каких работах у нас еще наблюдается разброс показателей или запускаем цикл SDCA для них.
Ну и к нашему примеру с калькуляторами и наказаниями... Я не пользуюсь калькулятором, т.к. мне удобнее считать в редакторе электронных таблиц (сохраняются все промежуточные результаты, вбивая формулы, я могу в случае ошибки поправить входные данные и получить новый результат не перевводя все заново, возможность повторного использования и т.д.). Т.е. у меня есть ноу-хау которое повышает эффективность моей работы. Ко мне приходит специально обученный человек и размещает у меня на столе (скорее всего в зоне максимальной доступности, Кайдзен же борется с потерями, и время на то, чтобы достать калькулятор из стола, это потери) калькулятор. И вот лежит этот калькулятор, мешает мне, но я им не пользуюсь от слова совсем, при этом делаю свою работу быстрее и качественнее (меньше ошибок, за счет готовых формул и удобного контроля входных данных). И вот, вместо того, чтобы быть инструментов повышения эффективности, стандарт становиться средством позволяющим менеджеру пользоваться своей властью в вопросах в которых он не разбирается. А Кайдзен по поводу того, на кого надо ориентироваться в вопросах принятия решений как правильно ставит во главу не менеджера, а гембо (то где создается полезность для потребителя). И даже если внедрением практик Кайдзен достигается повышение эффективности достаточное для того чтобы убрать сотрудника из цепочки создания ценности, надо его не увольнять, а задействовать в других процессах, чтобы увеличивать возможности компании по удовлетворению внешнего спроса.

Цитата дня


Лучший аргумент против демократии пятиминутная беседа со средним избирателем.
 -- Уинстон Черчилль

Под катом немного про другую известную цитату Черчилля, да и про демократию тоже немного.


Многие слышали другую фразу Черчеля, причем большинство ее знает выдернутой из контекста. Рекомендую прочитать всю его речь в парламенте, как представителя проигравшей выборы партии (да, фраза про демократию была произнесена не лидером нации, только недавно победившей во второй мировой войне, а лидером проигравшей выборы партии), а здесь, я только чуть расширю, буквально на одно предложение в обе стороны его цитату: «Никто не утверждает, что демократия совершенна или всеведуща. На самом деле, можно сказать, что она худшая форма правления, если не считать всех остальных, что были испытаны с течением времени. Однако существует мнение, и оно широко распространено в нашей стране, что народ должен быть суверенным, причем преемственным образом, и что общественное мнение, выражаемое всеми конституционными средствами, должно формировать, направлять и контролировать действия министров, которые являются служителями, а не хозяевами».
Ну и теперь про демократию и управление проектами, государством, отделом, группой людей. Рассмотрим простой кейс. Есть команда из трех программистов работающих над проектом. Два новичка и один более опытный. Более опытный предлагает использовать DI и даже понимает зачем это надо. Два менее опытных разработчика необходимости DI не понимают, с ним работать сложнее, если что-то упадет, то найти где  проблема бывает тяжело. В общем два мнения, добавим на это ограничение, что у более опытного нет формальной власти (мы же про демократию?) и надо все решать в процессе обсуждения. Не будем даже доходить до того, какое решение будет принято и к каким последствиям оно приведет. Давайте представим, процесс убеждения двумя новичками одного опытного разработчика в том, что не надо использовать DI. И как отнесется к решению принятому большинством, наш более опытный разработчик. Как то так. 

Цитата дня


Лучший аргумент против демократии пятиминутная беседа со средним избирателем.
 -- Уинстон Черчилль

Под катом немного про другую известную цитату Черчилля, да и про демократию тоже немного.


Многие слышали другую фразу Черчеля, причем большинство ее знает выдернутой из контекста. Рекомендую прочитать всю его речь в парламенте, как представителя проигравшей выборы партии (да, фраза про демократию была произнесена не лидером нации, только недавно победившей во второй мировой войне, а лидером проигравшей выборы партии), а здесь, я только чуть расширю, буквально на одно предложение в обе стороны его цитату: «Никто не утверждает, что демократия совершенна или всеведуща. На самом деле, можно сказать, что она худшая форма правления, если не считать всех остальных, что были испытаны с течением времени. Однако существует мнение, и оно широко распространено в нашей стране, что народ должен быть суверенным, причем преемственным образом, и что общественное мнение, выражаемое всеми конституционными средствами, должно формировать, направлять и контролировать действия министров, которые являются служителями, а не хозяевами».
Ну и теперь про демократию и управление проектами, государством, отделом, группой людей. Рассмотрим простой кейс. Есть команда из трех программистов работающих над проектом. Два новичка и один более опытный. Более опытный предлагает использовать DI и даже понимает зачем это надо. Два менее опытных разработчика необходимости DI не понимают, с ним работать сложнее, если что-то упадет, то найти где  проблема бывает тяжело. В общем два мнения, добавим на это ограничение, что у более опытного нет формальной власти (мы же про демократию?) и надо все решать в процессе обсуждения. Не будем даже доходить до того, какое решение будет принято и к каким последствиям оно приведет. Давайте представим, процесс убеждения двумя новичками одного опытного разработчика в том, что не надо использовать DI. И как отнесется к решению принятому большинством, наш более опытный разработчик. Как то так. 

Синтаксический сахар yield return

На stackoverflow задали вопрос про yield return. Ну и т.к. пример для понимания что это за зверь написал, то пусть он и в этом блоге полежит. Под катом два примера, как реализовать класс реализующий IEnumerable или IEnumerable классически и при помощи yield return. Для тех кто не в курсе, foreach и методы Linq работают с классами реализующими эти интерфейсы.

Итак, давайте посмотрим два примера в которых будут возвращаться четные числа от 2 до 10. Первый будем реализовывать класс без yield return:

class MyCollection : IEnumerable, IEnumerator
{
int _current = 0;

public int Current
{
get
{
if (_current <= 10)
{
return _current;
}
throw new IndexOutOfRangeException();
}
}

object IEnumerator.Current => Current;

public bool MoveNext()
{
if (_current < 10)
{
_current
+= 2;
return true;
}
return false;
}

public void Reset()
{
_current
= 0;
}

public void Dispose()
{

}

public IEnumerator GetEnumerator()
{
return new MyCollection();
}

IEnumerator IEnumerable.GetEnumerator()
{
return new MyCollection();
}
}
Как видно (ну я на это как минимум надеюсь), у нас класс кроме интерфейса IEnumerable реализует еще и интерфейс IEnumerator. В чем разница: 
IEnumerable - говорит: "Я могу предоставить способ последовательного перебора коллекции". И именно в этом интерфейсе объявлены методы GetEnumerator.
IEnumerator - говорит: "Я могу отдать текущий элемент, перейти к следующему, вернуться в начало". К этому интерфейсу принадлежат все остальные методы в примере.
В чем идея, в цикле foreach один раз вызывается метод GetEnumerator, а уже в полученном объекте, до тех пор, пока метод MoveNext не вернет false, берется current и записывается в переменную цикла. В общем виде последовательность такая:
var items = <объект поддерживающий IEnumerable>.GetEnumerator();
пока (items.MoveNext())
{
  var item = items.Current;
  // Здесь полезная работа
}
Надеюсь все понятно. Теперь, как можно переписать этот пример, при помощи синтаксического сахара yield return:
class MyCollection : IEnumerable
{
public IEnumerator GetEnumerator()
{
for (int i = 2; i <= 10; i += 2)
{
yield
return i;

}
}

IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
Обратите внимание насколько уменьшился код и на то, что нам не пришлось реализовывать второй интерфейс, все это оказалось спрятано внутри синтаксического сахара yield return. При вызове вот такого кода, что для первого, что для второго примера:
static void Main(string[] args)
{
foreach (var item in new MyCollection())
{
Console.WriteLine(item);
}
Console.ReadKey();
}
Вы увидите на консоли четные числа от 2 до 10. Как писать, выбирать вам.

Синтаксический сахар yield return

На stackoverflow задали вопрос про yield return. Ну и т.к. пример для понимания что это за зверь написал, то пусть он и в этом блоге полежит. Под катом два примера, как реализовать класс реализующий IEnumerable или IEnumerable классически и при помощи yield return. Для тех кто не в курсе, foreach и методы Linq работают с классами реализующими эти интерфейсы.

Итак, давайте посмотрим два примера в которых будут возвращаться четные числа от 2 до 10. Первый будем реализовывать класс без yield return:

class MyCollection : IEnumerable, IEnumerator
{
int _current = 0;

public int Current
{
get
{
if (_current <= 10)
{
return _current;
}
throw new IndexOutOfRangeException();
}
}

object IEnumerator.Current => Current;

public bool MoveNext()
{
if (_current < 10)
{
_current
+= 2;
return true;
}
return false;
}

public void Reset()
{
_current
= 0;
}

public void Dispose()
{

}

public IEnumerator GetEnumerator()
{
return new MyCollection();
}

IEnumerator IEnumerable.GetEnumerator()
{
return new MyCollection();
}
}
Как видно (ну я на это как минимум надеюсь), у нас класс кроме интерфейса IEnumerable реализует еще и интерфейс IEnumerator. В чем разница: 
IEnumerable - говорит: "Я могу предоставить способ последовательного перебора коллекции". И именно в этом интерфейсе объявлены методы GetEnumerator.
IEnumerator - говорит: "Я могу отдать текущий элемент, перейти к следующему, вернуться в начало". К этому интерфейсу принадлежат все остальные методы в примере.
В чем идея, в цикле foreach один раз вызывается метод GetEnumerator, а уже в полученном объекте, до тех пор, пока метод MoveNext не вернет false, берется current и записывается в переменную цикла. В общем виде последовательность такая:
var items = <объект поддерживающий IEnumerable>.GetEnumerator();
пока (items.MoveNext())
{
  var item = items.Current;
  // Здесь полезная работа
}
Надеюсь все понятно. Теперь, как можно переписать этот пример, при помощи синтаксического сахара yield return:
class MyCollection : IEnumerable
{
public IEnumerator GetEnumerator()
{
for (int i = 2; i <= 10; i += 2)
{
yield
return i;

}
}

IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
Обратите внимание насколько уменьшился код и на то, что нам не пришлось реализовывать второй интерфейс, все это оказалось спрятано внутри синтаксического сахара yield return. При вызове вот такого кода, что для первого, что для второго примера:
static void Main(string[] args)
{
foreach (var item in new MyCollection())
{
Console.WriteLine(item);
}
Console.ReadKey();
}
Вы увидите на консоли четные числа от 2 до 10. Как писать, выбирать вам.

Мнение о книге "Новая цель"

Если вы читали "Цель" и вам понравилось, то... Сложно сказать. Как производственный роман - супер. Даже есть любовная линия, и заканчивается все в лучших традициях русских народных сказок. Иными словами, как литературному произведению - зачет. Собственно это было сразу понятно по тому, как изменился стиль книги Цель-2, которую Голдратт писал без Джеффа Кокса.
Теперь к полезности. Основные идеи книги:
1. Включайте голову, т.к. даже самые логичные методы, как бы хорошо они не работали у других, без понимания что вы делаете и зачем, к ожидаемому результату не приведут.
2. Перед тем как внедрять изменения необходимо стабилизировать систему, выявить ограничение (привет ТОС) и в первую очередь направить все усилия на работу с ограничением или с тем, что окажет влияние на всю систему.
3. Шесть сигма и бережливое производство при правильном применении круто, но как оно работает мы вам не расскажем, приходите на курсы и мы вам расскажем что там по чем и даже выдадим зеленый или черный пояс.
4. Дерево текущей реальности и дерево будущей реальности это полезный инструмент которым надо пользоваться (в отличии от первых двух целей, здесь методика не рассматривается, так, упоминается общая идея и что с этим деревом надо работать).
5. Разбалансированные системы это круто и только так можно обеспечить стабильность производства.
6. Закупки тоже надо привязывать к барабану (надо подумать, что это может быть в приложении к программированию).
Читать ли книгу? Да. И как развлекательное чтение, и как затравку для чтения более серьезных вещей по ТОС или того же Деминга. Лучше или хуже эта книга для начала по сравнению с оригинальной Целью? Сложно сказать, с точки зрения практических приемов лучше Цель. Если время позволяет, то читать Цель, Цель-2, Новая цель.