Почему нет свойств расширения?
Меня часто спрашивают «парни, вы добавили методы расширения в C# 3, так почему бы не добавить ещё и свойства расширения?»
Хороший вопрос.
Давайте, сначала я чуть поговорю о C# 3.0. Явно главной новостью в C# 3 был LINQ. В некотором смысле, у нас было всего три новых возможности в C# 3:
- всё необходимое для LINQ – неявно типизированные переменные, анонимные типы, лямбда-выражения, методы расширения, инициализаторы объектов и коллекций, конструкторы запросов, деревья выражений, улучшенный вывод типов
- частичные методы
- автоматически реализуемые свойства
Последние два были крошечными по сравнению с пунктами из первой пачки. С точки зрения проектирования, синтаксис и семантика обеих возможностей прямолинейны. С точки зрения реализации, у нас уже были механизмы для устранения вызовов; частичные методы и условные методы – почти одно и то же за кулисами. Авто-свойства также были весьма прямолинейны в анализе и генерации кода. Нагрузка по тестировнию тоже была для них не особенно большой.
Команда C# была «длинным шестом» в 2008 релизе Visual Studio и .NET Framework. Под этим я имею в виду то, что если бы вы взяли количество времени, нужно для выполнения работы, на которую подписалась каждая команда, с учётом численности персонала, всё такое, и сделали шесты пропорциональной этому длины для каждой команды в Developer Division, то шест C# оказался бы самым длинным. Что означает, что у любой другой команды в DevDiv был запас в расписании, но если бы мы отстали на день от своего расписания, то новая студия и CLR тоже были бы выпущены на день позже. Если бы любая другая команда отстала на день, ну, до тех пор, пока это не делало их шест длиннее нашего, у них всё ещё было бы всё в порядке. Внутри нашей команды, при разделе работы между разными её участниками, «длинным шестом» были задачи привязывания лямбд и вывода типов методов, отданные мне. Так что, в некотором смысле, каждый день моего опоздания одначал запаздывание выхода продукта на столько же дней. (Никакого давления!)
К счастью, у нас тут превосходная команда, мы все очень хорошо помогали друг другу в течение этого релиза, подхватывая задачи друг друга при необходимости, и выполнили качественный релиз за долгое время. Моя мысль – в том, что если что-то не было либо необходимым для LINQ , либо маленьким, ортогональным, и легковыбрасываемым в случае необходимости (как остальные две), это выбрасывали немедленно. Ни в коем случае мы не собирались рисковать задержать выход всего продукта для какой-то штуки, которая была бы сразу и сложной и не необходимой. Конечно же, сразу было очевидно, что естественным спутником методов расширения являются свойства расширения. Менее очевидно, по какой-то причине, что события расширения, операторы расширения, конструкторы расширения (также известные, как «паттерн «фабрика»»), и так далее, тоже являются естественными спутниками. Но мы даже не рассматривали вопрос проектирования свойств расширения в C# 3; мы знали, что без них можно обойтись, и они добавят риск в и итак уже рискованное расписание, без привлекательного выигрыша.
Ну, теперь мы дошли до C# 4.
Как я люблю напоминать, ответ на все вопросы вида «почему в продукте X нет возможности Y?» один. Этопотому, что для того, чтобы в продукте была некоторая возможность, эта возможность должна быть
- в первую очередь продумана
- нужна
- спроектирована
- специфицирована
- реализована
- протестирована
- задокументирована
- доставлена потребителям
Мы должны пройти каждый из этих пунктов, иначе – никаких новшеств.
Когда мы начали работать над C# 4, мы составили список всех запросов, о которых мы только слышали. В нём были сотни возможностей. Как я описывал в прошлом году, мы рассортировали тот список по корзинкам «стоит сделать / неплохо бы / плохая идея». Свойства расширения были в корзинке «стоит сделать». Затем мы посмотрели на доступный нам бюджет – который измерялся не столько в долларах, сколько в доступных проектировщиках, разработчиках, тестерах, писателях, и менеджерах, умноженных на доступное время – и определили, что у нас хватит ресурсов на реализацию примерно половины вещей в корзинке «стоит сделать». Так что мы выбросили половину этого. Свойства расширения пережили это урезание. Затем мы спроектировали эту возможность. У нас были многочасовые споры о предполагаемом синтаксисе деклараций, способах «прямого» вызова методов чтения и записи как статических методов, и так далее. Мы придумали и согласовали приемлемый синтаксис, спроектировали семантику, написали черновик спецификации, и начали писать код и планы тестирования.
К моменту, когда код дошёл до приличного состояния – еще не до конца протестирован, но работает и соответствует спецификации – мы стали устраивать собрания с командой WPF. Разработчики WPF были предполагаемыми основными потребителями свойств расширения. В WPF уже есть механизм, похожий на свойства расширения; было бы неплохо унифицировать этот механизм с нашим. К сожалению, рассмотрев хорошенько их реальные сценарии, мы прили к разочаровывающему выводу о том, что мы спроектировали не то; эта возможность на самом деле не решала их проблемы. Это, надо признать, провал процесса проектирования. Мы должны были поинтересоваться мнением основного потребителя намного раньше. Сделай мы это – и они могли бы либо повлиять на дизайн и получить что-то, пригодное для них, или бы мы выбросили эту возможность из плана без затрат на написание спецификации, кода, и планов тестирования.
Но, когда оказываешься в неприятной ситуации, приходится принимать решение прекратить выбрасывать хорошие деньги на плохое. Вместо того, чтобы нести дополнительные расходы – на тестирование, документацию, поставку потребителям, а потом поддержку этой возможности до конца дней языка – в обмен на возможность, которая не удовлетворяет потребностей наших потребителей, мы выбросили эту возможность. К тому моменту мы не были уверены, что у нас осталось достаточно времени на перепроектирование возможности правильным образом.
Так что, к сожалению, никаких свойств расширения в C# 4. Возможно, в гипотетической будущей версии C#.
Comments
- Anonymous
February 28, 2011
А вопрос, где вообще собирают предложения для следующих версий языка? Просто иногда удивляет то, какой бред реализуется (типа того-же динамика). И то, что отсутствуют действительно полезные вещи, о отсутствии которых говорят многие программисты, работающие действительно с большими проектами. например нормальный const/mutable - что действительно улучшит безопасность кода, HashSet, NotNull и т.д. Ну а вообще, сшарп - очень красивая штука. спасибо вам за неё.