Почему в то время как(правда) петли в конструкторе на самом деле плохо?

Хотя вообще вопрос мой объем-это скорее C#, как мне известно, что такие языки, как C++ имеют различную семантику в отношении выполнения конструктора, управление памятью, неопределенное поведение, и т. д.

Кто-то задал мне интересный вопрос, который был для меня не легко ответить.

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

Есть некоторые понятия, которые разбиваются на это:

  • как принцип наименьшего удивления, пользователь не ожидает, что конструктор ведешь себя так.
  • Модульные тесты сложнее, как вы не можете создать этот класс или вколоть его, как он никогда не выходит из цикла.
  • В конце цикла (конец игры) затем концептуально момент, где заканчивается конструктора, что тоже странно.
  • Технически такой класс не имеет членов, за исключением конструктора, который делает это тяжелее, чтобы понять (особенно для языков, где нет реализации)

А еще есть технические вопросы:

  • Конструктор на самом деле никогда не заканчивается, так что же происходит с GC здесь? Этот объект уже в Gen 0?
  • Вытекающие из такого класса невозможно или как минимум очень сложно из-за того, что базовый конструктор никогда не возвращает

Есть что-то более явно плохие или коварные с таким подходом?

Комментарии к вопросу (20)
Решение

Каково назначение конструктора? Он возвращает вновь созданный объект. Что означает бесконечный цикл делать? Он никогда не возвращается. Как конструктор возвращает вновь созданный объект, если он не'т вернуться на всех? Он может'т.

Эрго, бесконечный цикл, нарушает фундаментальные договора конструктора: чтобы что-то построить.

Комментарии (14)

Есть ли что-то более явно плохие или коварные с таким подходом?

Да, конечно. Это ненужно, неожиданно, бесполезно, unelegant. Это нарушает современные концепции дизайна классе (сплоченность, сцепление). Он разрывает контракт метод (конструктор имеет определенное задание, а не просто какой-то случайный метод). Это, конечно, не хорошо ремонтопригодны, будущие программисты тратят много времени, пытаясь понять, что происходит, и пытаясь угадать причины, почему это сделано именно так.

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

Многие/большинство современных усовершенствований в методы разработки программного обеспечения, выполняются специально для того, чтобы сделать сам процесс написания/тестирования/отладки/сопровождения по легче. Все это обойти, такое, где код находится случайно, потому что он "работает"&;.

К сожалению, вы регулярно будете встречать программистов, которые в полном неведении обо всем этом. Он работает, что'с его.

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

$sum_a = `bash -c "echo $((2+2)) 2>/dev/null"`;   # calculate
chomp $sum_a;                         # remove trailing \n
$sum_a = $sum_a + 0;                  # force it to be a number in case some non-digit characters managed to sneak in

$sum_b = 2+2;

Что не так с первым подходом? Он возвращает 4 через достаточно короткий промежуток времени; это правильно. Возражения (вместе со всеми обычными причинами разработчик может дать их опровергнуть) являются:

  • Труднее читать (но эй, хороший программист может читать его так же легко, и мы всегда делали это таким образом: если вы хотите, я могу переделать его в метод!)
  • Медленнее (но это не в сроках опасном месте, так что мы можем игнорировать это, и кроме того, это'ы лучше оптимизировать только при необходимости!)
  • Использует гораздо больше богатства (новый процесс, больше оперативной памяти и т. д. - но Дито нашем сервере более чем достаточно быстро)
  • Вводит зависимостей Баш (но это никогда не будет работать на Windows, Mac или Android в любом случае)
  • И все остальные причины, упомянутые выше.
Комментарии (6)

Вы даете достаточно поводов в ваш вопрос, чтобы править такой подход, но собственно вопрос вот есть "есть что-то более явно плохие или коварные с таким подходом?&и"

Хотя мое первое здесь, что это бессмысленно. Если ваш конструктор не заканчивается, никакие другие части программы могут получить ссылку на объект constructed так что'ы логика поставив его в конструктор вместо обычного метода. Потом мне пришло в голову, что единственным отличием будет то, что в вашей петли, вы могли бы привести ссылки на частично построенный " это " вырваться из петли. Хотя это вовсе'т строго ограничиваются этой ситуации, это's гарантированная, что если вы разрешите это, чтобы защитить эти ссылки всегда указывают на объект, который не является полностью построенным.

Я не'т знать, является ли семантика в такой ситуации четко определены в C#, но я бы утверждать, что это не'т имеет значения, потому что это's не то, что большинство разработчиков хотели бы попытаться вникать.

Комментарии (7)

+1 по крайней мере, удивление, но это нелегко сформулировать для новых разработчиков. На прагматическом уровне, это трудно для отладки исключений в конструкторах, если объект не удается инициализировать его не будет существовать для вас, чтобы проверить состояние или войти извне, что конструктор.

Если вы чувствуете необходимость, чтобы сделать такой шаблон кода, пожалуйста, используйте статические методы класса вместо.

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

Если вы не планируете использовать объект, который вы не на "Строительство" тогда в чем смысл создания экземпляра объекта в первую очередь? Имея в то время как(правда) петли в конструкторе эффективно означает, что вы никогда не собираетесь использовать его по полной...

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

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

Комментарии (2)

почему в то время как(правда) петли в конструкторе на самом деле плохо?

Что's не так уж плохо.

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

Зачем ты хочешь это сделать? Серьезно. Этот класс имеет одну функцию: конструктор. Если все, что вы хотите одну функцию, что's, почему мы имеем функции, а не конструкторы.

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

Есть лучше и проще варианты для достижения той же цели.

Если есть 2 варианта и один лучше, это не'т имеет значения, насколько лучше, вы выбрали лучшую. Кстати, что's, почему мы в <с>Дон'т</с> почти никогда не использовать goto.

Комментарии (0)

Там's ничего изначально плохого. Однако, что будет важно-это вопрос о том, почему вы решили использовать эту конструкцию. Зачем вы это делаете?

Во-первых, я'м не собираюсь говорить об использовании в то время как(правда) в конструктор. Нет абсолютно ничего плохого в использовании этого синтаксиса в конструктор. Тем не менее, концепция "и начать игровой цикл в конструкторе" это тот, который может вызвать некоторые проблемы.

Это's очень распространены в таких ситуациях, чтобы иметь конструктор просто построить объект, и функция, которая вызывает бесконечный цикл. Это дает пользователю вашего кода более гибкого. В качестве примера проблем, которые могут показать, что вы ограничить использование вашего объекта. Если кто-то хочет иметь объект члена, который "Игра объект" на своем классе, они должны быть готовы выполнить весь цикл игры в конструктор, потому что они должны создать объект. Это может привести к пыткам кодирования, чтобы работать вокруг этого. В общем случае, нельзя заранее выделить ваш объект игры, а затем запустить его позже. Для некоторых программ, что's не проблема, но есть несколько классов программ, где вы хотите, чтобы иметь возможность выделить все, а затем вызвать игровой цикл.

Одно из основных правил программирования-использовать простейший инструмент для работы. Это's не жесткое правило, но это's очень полезным. Если вызов функции было бы достаточно, зачем создавать объект класса? Если я вижу более мощный использовать сложный инструмент, я предполагаю, что застройщик была причина для этого, и я начну исследовать, какого рода странных уловок, которые вы могли бы делать.

Бывают случаи, когда это может быть разумным. Там могут быть случаи, когда это по-настоящему интуитивно понятным для вас, чтобы иметь игровой цикл в конструкторе. В тех случаях вам бежать с ним! Например, ваш игровой цикл может быть встроен в гораздо более масштабной программы, которая создает классы воплотить некоторые данные. Если у вас есть, чтобы запустить цикл игры, чтобы генерировать эти данные, это может быть очень разумным, чтобы запустить цикл игры в конструктор. Просто рассматривать это как особый случай: было бы правильным сделать это, потому что главная программа делает его интуитивно понятным для следующего разработчика, чтобы понять, что ты сделал и почему.

Комментарии (2)

У меня сложилось впечатление, что некоторые понятия перемешались и в результате не так хорошо сформулирован вопрос.

Конструктор класса может запустить новый поток, который будет на "никогда" в конце (хотя я предпочитаю использовать а(_KeepRunning) за `то время как(правда) потому что я могу установить булевский элемент в false где-то).

Можно извлечь, что способ создания и запуска потока в функцию своего собственного, для того, чтобы отделить объект строительства и фактическое начало ее работы - мне это нравится, потому что я получаю больший контроль над доступом к ресурсам.

Вы также можете посмотреть на "активный объект, узор" в. В конце концов, я думаю, вопрос был направлен на то, когда начать нить собой "Я активный объект&;, и мои предпочтения-это соединение строительных и начать Для лучшего контроля.

Комментарии (0)

Ваш объект напоминает мне начиная [задачи](https://msdn.microsoft.com/en-us/library/hh195051(в=против 110).аспн). Объект "задача" есть конструктор, но он есть также куча статических методов фабрики как: задач.Запустить, Задач.Старт " и " задач.Фабрика.StartNew.

Это очень похоже на то, что вы пытаетесь сделать, и это'ы скорее всего это 'конвенции'. Главной проблемой людей, кажется, что такое использование конструктора их удивляет. @Компания JörgWMittag говорит, что нарушает основополагающий договор, который я предполагаю, означает, что JöRG является очень удивлены. Я согласен и нечего добавить к этому.

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

Вы можете предоставить конструкторам, которые позволяют управлять (как @Брандин предполагает, что-то вроде ВАР г = Новая игра {...}; г.MainLoop();, которые размещают пользователи, Дон'т хотите начать игру сразу же, и, может быть, хочешь передать его в первую очередь. А вы можете написать что-то вроде ВАР runningGame = игра.StartNew(); чтобы сделать его запуска сразу легко.

Комментарии (1)

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

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

Комментарии (1)