Почему в ПЯ C# в интерфейсе запрещены...

aleks058

Почему в Правильном Языке C# запрещены

  • static-методы/свойства/эвенты
  • декларация protected-методов
  • декларация конструкторов

Каждая из этих фишек была бы полезна во многих случаях.

Helga87

Потому что интерфейс, это способ описания возможностей экземпляра класса для того, чтобы другие объекты могли работать с переданным объектом. Поэтому, для instance-а уже не существуют статические члены класса, не интересны конструкторы, да и protected члены тоже, т.к. другие объекты не смогут до них достучаться.
Тебе, видимо, хочется способа описания класса. Т.е. возможность сказать "класс имеет конструктор по умолчанию", "класс имеет конструктор с параметрами указанных типов ", "у класса есть такие-то методы и свойства (мб статические или непубличные)" и пр.
Использование такой возможности нужно там, где необходимо знать о возможностях класса. Самым ярким примером места, где это требуется, это generics. Сейчас это частично решается с помощью механизма constrains, т.е.:
class Lala<T> where T : ICollection, new
{
..
}

К сожалению, constrains сейчас крайне бедны. Если этот механизм расширить предлагаемыми тобой возможностями, мы сможем наконец-то работать с generics, которые, например, знают о поддерживаемых типом операторах, нормально создавать объекты (сейчас разрешено знать только о конструкторе по умолчанию и вообще может даже наступить коммунизм!

aleks058

Интересно, это ограничение языка или платформы?
Мне все это надо, чтобы была более строгая структура программы, что позволит избежать ошибок при разработке.
Тогда действительно надо ввести подобие constraint для интерфейса, где все это можно указывать. Но что-то разработчики шарпа не подумали о таких возможностях

Helga87

Я вообще предлагаю не смешивать понятия интерфейса (ограничителя для объекта) и несуществующего пока в языке ограничителя для класса (вернее, под это чуть-чуть попадают constraint-ы, но это - сделано не так, как хочется, и слишком мало умеет)

bleyman

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

aleks058

Насколько я помню, написать абстрактную реализацию интерфейсной функции никтоне мешает.
Ты что имеешь в виду?
Все возможности, которые я перечислил, были бы полезны тем, кто наследуется от класса и вообще пользуется классом.
Один из примеров - наличие спец. конструктора у класса-имплементатора ISerializable, который нужен при десериализации. Микрософту его наличие приходится проверять через рефлексию, а можно было бы эту задачу возложить на компилятор.

bleyman

Я имею в виду, что интерфейсы в ЯП С# имеют вполне определённую цель - чтобы можно было написать метод IList GetList или void Iterate(IList target). То есть они предназначены только и исключительно для пользователей объекта.
Ты перечислил три вещи:
static-методы/свойства/эвенты
декларация protected-методов
декларация конструкторов
Ни одна из которых не может быть использована сторонним классом. Все эти вещи могли бы использоваться только и исключительно наследниками класса.

bleyman

>> Один из примеров - наличие спец. конструктора у класса-имплементатора ISerializable, который нужен при десериализации.
Мммм... И как ты себе это представляешь? Вызов конструктора то есть. Он же не просто "проверяется", он вызывается. Как можно вызвать интерфейсный метод у несозданного объекта?

bleyman

Вообще с десериализацией - очень левый пример, если уж на то пошло. Потому что на самом деле создание/десериализация объекта происходит в два этапа: 1) выделение памяти и получение указателя на объект, 2) вызов конструктора. Насколько я помню, мсил эти два этапа разделить не позволяет, но десериализатор является частью фреймворка и написан не на мсиле, поэтому он может "использовать рефлекшен" между двумя этапами. Никакая прога на шарпе этого сделать не сможет.

aleks058

Вообще с десериализацией - очень левый пример, если уж на то пошло. Потому что на самом деле создание/десериализация объекта происходит в два этапа: 1) выделение памяти и получение указателя на объект, 2) вызов конструктора. Насколько я помню, мсил эти два этапа разделить не позволяет, но десериализатор является частью фреймворка и написан не на мсиле, поэтому он может "использовать рефлекшен" между двумя этапами. Никакая прога на шарпе этого сделать не сможет.
ИМХО, гон.
Десериализация - это просто вызов конструктора по умолчанию (если ты не реализовал ISerializable, а полагаешься на стандартные средства а затем вызов сеттеров на каждый видимый проперти через рефлекшн и присваивание значений открытых переменных (тоже через рефлекшн).
Если такой механизм тебя не устроил и ты решил сериализоваться ручками, наслешуешь ISerializable, который обязывает тебя реализовать метод

void GetObjectData (
SerializationInfo info,
StreamingContext context
)

и конструктор с параметрами

(SerializationInfo information, StreamingContext context

наличие которого необходимо для сериализации.
Теперь при сериализации сериализатор будет спрашивать у твоего объекта GetObjectData, ты в этом методе будешь наполнять SerializationInfo, который тебе в параметре передали. Затем сериализатор запишет эти данные в XML/binary/твой формат (если тебе захочется сериализатор свой написать) ну и дальше делай с ними чего хочешь - хоть по сети, хоть в файл.
При десериализации вызовется конструктор с параметрами (SerializationInfo information, StreamingContext context) и ты по SerializationInfo восстановишь свой объект.
Недураки из MS спроектировали архитектуру .Net так, что можно вклиниваться практически в любые процессы, происходящие в ней {еще один яркий пример - remoting, в котором довольно нетривиальный механизм инстанциирования объектов (когда просто пишешь new, а у тебя remoting-объект получается вместо локального). И механизм этот при желании тоже можно изменить, но не думаю, что кто-то за это возьмется без хорошего финансироания и обоснования.}
А насчет конструктора. Ну так вот.
Когда ты создаешь сериализатор, ты указываешь класс, над которым он работает.
Отсутствие конструктора с заданными параметрами отлавливается только в рантайме, когда ты пытаешься десериализовать поток данных. Так же как и отсутствие конструктора без параметров, когда ты не реализовывал ISerializable.
Короче, правильно сказал насчет Constaints для классов. Фича, которой нет. Но маза в том, что ее можно добавить, сохранив совместимость с существующим кодом.

aleks058

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

bleyman

Ок, да, про десериализацию я немножко нагнал.
Хотя вот тут:
>>затем вызов сеттеров на каждый видимый проперти через рефлекшн и присваивание значений открытых переменных (тоже через рефлекшн).
ты уверен? Приватные переменные тоже прекрасно десериализуются. По-моему, стандартный десериализатор просто присваивает значения всех value type переменных, и где-то у себя внутри запоминает адреса ссылок, которые нужно будет присвоить когда десериализнётся весь граф (не относится к [nonserialized], естественно). Именно поэтому крайне настойчиво рекомендуется при наличии десериализовательного конструктора ничего в нём не делать. А атрибут [Serializable] нужен по любому, кстати =)
>>Короче, правильно сказал насчет Constaints для классов. Фича, которой нет. Но маза в том, что ее можно добавить, сохранив совместимость с существующим кодом.
Сказал-то он, конечно, правильно, я не спорю. Но ты предлагаешь делать это через жопу - при помощи интерфейсов. Интерфейсы не для этого нужны! Фактически, если в интерфейс добавить конструктор, то использоваться он будет всё равно только через рефлекшен. То есть как бы получится, что ты просто присобачил к классу метаданные. А для присобачивания к классу метаданных следует использовать атрибуты. Точка.
Я не знаю, почему они не встроили в компилятор проверялку атрибута Serializable (в который, в свою очередь, не передаётся bool useDefaultSerialization). Это самый логичный и простой выход.
С другой стороны, рантаймные проверки не так уж и нервируют. После того, как я хекседитором исправлял в бинарно-десериализнутом образе версию используемой дллки - меня уже вообще мало что нервирует (и не спрашивай, как я понял, что это нужно сделать!)

aleks058

Ок, да, про десериализацию я немножко нагнал.
Хотя вот тут:
>>затем вызов сеттеров на каждый видимый проперти через рефлекшн и присваивание значений открытых переменных (тоже через рефлекшн).
ты уверен? Приватные переменные тоже прекрасно десериализуются. По-моему, стандартный десериализатор просто присваивает значения всех value type переменных, и где-то у себя внутри запоминает адреса ссылок, которые нужно будет присвоить когда десериализнётся весь граф (не относится к [nonserialized], естественно). Именно поэтому крайне настойчиво рекомендуется при наличии десериализовательного конструктора ничего в нём не делать. А атрибут [Serializable] нужен по любому, кстати =)
Поэкспериментировал я тут. XmlSerializer работает так, как я говорил, а SoapFormatter и BinaryFormatter - как ты. Забавно.
>>Короче, правильно сказал насчет Constaints для классов. Фича, которой нет. Но маза в том, что ее можно добавить, сохранив совместимость с существующим кодом.
Сказал-то он, конечно, правильно, я не спорю. Но ты предлагаешь делать это через жопу - при помощи интерфейсов. Интерфейсы не для этого нужны! Фактически, если в интерфейс добавить конструктор, то использоваться он будет всё равно только через рефлекшен. То есть как бы получится, что ты просто присобачил к классу метаданные. А для присобачивания к классу метаданных следует использовать атрибуты. Точка.
Не, не. Я не буду пользоваться этим через рефлекшн. Я хочу, чтобы компилятор на этапе компиляции говорил, что "этот объект сюда передавать нельзя, потому что у типа, которого он, нет такого конструктора" или "этот класс не реализовал такой-то static-метод или (protected instance)-метод, хотя должен был".
С другой стороны, рантаймные проверки не так уж и нервируют. После того, как я хекседитором исправлял в бинарно-десериализнутом образе версию используемой дллки - меня уже вообще мало что нервирует (и не спрашивай, как я понял, что это нужно сделать!)
Фанатик

Dasar

Проверки на уровне компиляции - это все хорошо, но в нынешнем виде - это удобно только на маленьких программах.
Взять те же throw в C++/Java-е - идея может быть и правильная, но на реальном большом приложение все эти throw использовать бессмысленно, т.к. при этом сразу дохнет вся идея инкапсуляции.

aleks058

Я хочу подумать над структурой классов и описать правила, которым она должна удовлетворять (интерфейсы, абстрактные классы; "Constraints", которых в шарпе нету).
При реализации классов, если я что-то забуду, я обнаружу ошибку не в рантайме (могу ведь и не обнаружить а при компиляции, потому что иначе тестировать приходится намного больше, чем могло бы быть.
Проверки на этапе компиляции ИМХО, всегда лучше ошибок в рантайме, потому что в рантайме ошибку надо сначала обнаружить тестами, которые еще написать надо, а при компиляции ошибка обнаруживается "сама".
Да. Думаю, что моя проблема решается анализом скомпиленного кода приблудой вроде FxCop, но ее настраивать надо на это.
Или действительно, как сказал , можно попробовать воспользоваться атрибутами. Хотя не знаю, что из этого выйдет.

enochka1145

// Взять те же throw в C++/Java-е - идея может быть и правильная, но на реальном большом приложение все эти throw использовать бессмысленно, т.к. при этом сразу дохнет вся идея инкапсуляции.
Можно здесь немного поподробнее?

Julie16

Это просто бред.

Dasar

> Можно здесь немного поподробнее?
допустим у нас есть некий модуль A, который работает с модулем B.
Причем допустим вся работа заключается в получение какой-то коллекции.
Мы почесали репу: и зафиксировали какие-то разумные throw, например, выход за коллекцию и т.д.
Завтра мы решили добавить в модуль B - дисковое кэширование (мол коллекция большая, используется редко, поэтому ее полезно выкидывать на диск).
Но при этом у нас в модуле B - сразу появилась возможность генерации IO-ошибки.
Значит надо садиться и менять в модуле A - все ограничения на throw.
В итоге получается, что модуль A - обязан знать как реализован модуль B, для того, чтобы правильно прописать список throw. Это и является нарушением инкапсуляции.

Dasar

> Проверки на этапе компиляции ИМХО, всегда лучше ошибок в рантайме, потому что в рантайме ошибку надо сначала обнаружить тестами, которые еще написать надо, а при компиляции ошибка обнаруживается "сама".
Если система компиляции спроектирована так, что позволяет игнорировать ошибки (восстанавливаться после ошибок тогда да - проверка на уровне компиляции - 100% польза.
Иначе - часто возникает ситуации, когда приходится вставлять неправильный(с точки зрения задачи) код - для того, чтобы удовлетворились формальные проверки компилятора.
Банальный пример (в реальном коде, вместо true может стоять какая-то сложная функция, но которая в нашем контексте - все равно выдает всегда true):

if (true)
{
...
}
else
{
bla-bla
}

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

bobby

Зато если начать внезапно из B кидать какие-то exception'ы, нигде это не специфицируя, то они будут пролетать наружу, оседая в неизвестных кусках кода, причем мы (разработчики) об этом узнаем огого когда. Вот, например, для меня совсем неочевидно, что польза от отсутствия необходимости писать throws-декларации больше, чем такой потенциальный вред.
Ещё достаточно часто строят цепочки из exception'ов (вложенных друг в друга чтобы не менять throws(...)-декларации. Таким образом, код, который ловит ошибки, будет продолжать их ловить и после внесенных изменений в используемый им модуль, не вдаваясь в подробности ошибки (причину возникновения и т.п.). Впрочем, тоже не берусь утверждать, насколько это хорошо или плохо.
Все вышесказанное относится к Java, в C++ из-за особенностей семантики я плохо понимаю, какую выгоду можно извлечь от спецификаций throw(... поэтому все же предпочитаю их не писать.

bobby

мы знаем, что bla-bla никогда не выполниться, поэтому, в целом, пофигу что там написано, но компилятор обязательно заставит нас, чтобы даже этот bla-bla проходил все проверки.
Я его полностью поддерживаю! Ведь в какой-то редакции кода наше true обязательно превратится в false, а контекст поменяется, как же без этого.
Хотя, согласен, бывают такие ситуации, когда такое поведение вызывает раздражение.

enochka1145

// В итоге получается, что модуль A - обязан знать как реализован модуль B, для того, чтобы правильно прописать список throw. Это и является нарушением инкапсуляции.
Э-э... А я-то думал, возможные exception-ы - это если не интерфейс, то по крайней мере контракт между A и B. Разве надо знать, как реализован B? Всё-таки набор исключений - это ещё не внутреннее устройство.
Наверно, я всё ещё не до конца уловил твою идею, твою работу с exception-ами. Для меня, например, это просто ошибки времени выполнения, которые аккуратненько записываются в лог, после чего их причина устраняется руками. Причём это ещё не значит, что программа падает. Просто какой-то кусочек функциональности ещё не работает. ОК, ты как клиент: сохранил работу, отправил лог, через некоторое время обновил проект из CVS, запустил, продолжил работу как ни в чём не бывало.

Dasar

> Я его полностью поддерживаю! Ведь в какой-то редакции кода наше true обязательно превратится в false, а контекст поменяется, как же без этого.
И какой смысл - от того, что он не восстановился после этой ошибки?
в результате, он только вынудит меня - закомментировать bla-bla, т.е. код от этого правильнее совсем не станет, он станет правильнее - лишь формально.

Dasar

> Наверно, я всё ещё не до конца уловил твою идею, твою работу с exception-ами. Для меня, например, это просто ошибки времени выполнения, которые аккуратненько записываются в лог, после чего их причина устраняется руками. Причём это ещё не значит, что программа падает. Просто какой-то кусочек функциональности ещё не работает
имхо, exception - это норма. или другими словами - exception, это исключительная (редкая) ситуация.
она редкая, но при этом если она возникла - то это норма для программы.
во многих ситуациях - бессмысленно заменять исключения на что-то другое.
понятно, что, например, исключение о том - что файл не смог записаться, потому что кончилось место - можно было бы избежать, каким-то способом проверив - а есть если место на диске.
Но такое изменение излишне:
1. Такое изменение редко улучшает поведение программы с точки зрения пользователя.
2. Такое изменение часто становиться местом потенциальных ошибок, т.к. мы действие разнесли на два: угадывание а что на самом деле действию может понадобиться и непосредственно само действие.
Отдаленным примером таких потенциальных проблем является кнопка submit в этом форуме в ситуации, когда рвется связь с форумом - кнопка submit disable-ится хотя само действие отправки не выполнено.
Вернемся к throw:
усложним ситуация допустим есть модули A, B и C.
Модуль A, через модуль B работает с модулем C.
A - это, например, UI
B - логика
C - хранилище
Для B - не важно, какая проблема случилась с C - диск readonly, кончилась память, ленту зажевало и т.д.
для B важен только сам факт ошибки.
Модуль A - уже обычно больше знает об ошибках, он знает - что если диск readonly, то надо попросить пользователя снять readonly, если кончилась память - то попросить купить еще, если зажевало ленту - то попросить ее заменить, если ошибка непредвиденная - то просто вывести ее пользователю, и попросить разобраться.
Получается, что хотя о проблемах C - должен знать лишь модуль A (при чем он должен знать лишь о части проблем) в текущей виде - мы вынуждены все знание об ошибках тащить и в модуль B.
Причем если модуль C мы меняем, например - дисковое хранение меняем на хранение в базе, то обо всех этих изменениях обязан знать и модуль B.

enochka1145

OK, наверно мне ещё не доводилось писать столь сложные приложения. Я бы просто написал в B что-нибудь вроде catch (Exception e) { throw e; } где e - сообщение, выброшенное в C, и теперь направляющееся в A.

Dasar

и throw-ограничении модуля B - ты бы написал, что он выкидывает произвольное исключение?

Marinavo_0507

> в результате, он только вынудит меня - закомментировать bla-bla,
> т.е. код от этого правильнее совсем не станет,
> он станет правильнее - лишь формально.
неправда
во втором случае в коде будет явное указание, что данная ветка ещё не дописана
то есть, мысль разработчика будет выражена точнее, то есть, код правильнее
в идеале, возможно, не помешала бы специальная конструкция языка, или соглашение о стиле

Dasar

> во втором случае в коде будет явное указание, что данная ветка ещё не дописана
ни фига - не будет, т.к. может так и надо, что в else у нас ничего не делается.
кусок кода, который, не компилируется - imo - намного более явный указатель на то, что в этом коде что-то не дописано.

Marinavo_0507

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

Dasar

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

bastii

Вернемся к throw:
усложним ситуация допустим есть модули A, B и C.
Модуль A, через модуль B работает с модулем C.
A - это, например, UI
B - логика
C - хранилище
...
Сталкивался в Джава с такой ситуацией. Сначала в модуле С данные хранились в памяти и грузились из БД по запросу из А, а уже затем происходило взаимодействие В и С. Потом захотелось сделать ленивую загрузку. Прошлось прятать SQLException в RuntimeException, что усложнило обработку исключений в А.

Marinavo_0507

сейчас мы вот сюда пару строк добавим, а вот этот кусок кода закомментируем
при этом закоментированный кусок как раз по чистой случайности совпадает с целой веткой условного оператора, а условие всегда true, причём компилятор это знает? не надо выдумывать
достаточно написать

#ifdef FEATURE_xxx /* включить, когда фича xxx будет дописана */
...
#endif

Dasar

> при этом закоментированный кусок как раз по чистой случайности совпадает с целой веткой условного оператора,
не важно
> а условие всегда true, причём компилятор это знает?
тоже не важно
условие может быть не всегда true, да и некомпилируемый кусок - может быть отдельным оператором, блоком, методом и т.д.

Marinavo_0507

Вот есть в коде ошибка. Как компилятору узнать, какой блок не компилировать, если программист этого не указал?

Dasar

> Как компилятору узнать, какой блок не компилировать, если программист этого не указал?
догадаться
спросить

Marinavo_0507

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

Dasar

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

Marinavo_0507

> Помощь - это: я все сделал, все работает
Откуда он узнает, что всё работает?
Ошибка означает, что компилятор не понял, как сделать так, чтоб работало.
> он - шантажирует
Ты очеловечиваешь компилятор.

Dasar

> Ошибка означает, что компилятор не понял, как сделать так, чтоб работало.
все он понял, это же не паскалевский компилятор - который только до первой ошибки идет.
> Ты очеловечиваешь компилятор.
и? в чем проблема?

Helga87

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

Dasar

это проблема подхода, или проблема реализации?

Helga87

Вероятно подхода, т.к. при любой реализации, если у нас не все хорошо в программе, мы имеем какое-то количество сообщений, смотреть на которые очень не хочется - что-то ведь работает. А когда вдруг захочется, то окажется, что за то время, что мы забивали на предупреждения, их количество разрослось до неприличного и придется копаться в свалке.
Та же проблема и с обычными предупреждениями компилятора. Либо стараются свести их количество к нулю (что не сильно отличается от threat warnings as errors либо приходит ситуация каши, и показ предупреждений просто отключается

Dasar

> Вероятно подхода, т.к. при любой реализации, если у нас не все хорошо в программе, мы имеем какое-то количество сообщений, смотреть на которые очень не хочется - что-то ведь работает. А когда вдруг захочется, то окажется, что за то время, что мы забивали на предупреждения, их количество разрослось до неприличного и придется копаться в свалке
Это просто означает, что в компилятор и TEX - не вставлен инструмент для работы с больших кол-вом сообщений.
ps
Могу еще раз повторить свое глобальное мнение, что большая часть текущего ПО не предусматривают удобного интерфейса для работы с больше, чем 10 элементов.

Helga87

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

Dasar

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

bleyman

>>смысл в том - что чем больше правил, проверок и т.д. наворачивается, тем сложнее написать программу - которая полностью им удовлетворяет.
Слушай, я не понимаю - ты опять беспочвенно теоретизируешь что ли?
Если мне компилятор шарпа говорит варнинг, я этот варнинг замечаю и исправляю. Сразу же. Если у меня есть иф с условием, которое в данный момент всегда эвальюэйтится в тру, но откуда-то взялся код и для второго варианта, я а) выделю вторую ветку б) нажму ctrl-c,c в) напишу "// TODO: описание" перед ифом, г) если закомментаренный кусок достаточно большой, засуну его в регион.
Буквально вчера нужно было написать модуль, который компилится немножко поразному в зависимости аж от двух дефайнов, причём прямо вставлять дефайны в код - некошерно имхо. Да никаких проблем, вначале Главного Объекта сидел вот этот маленький кусочек, который я написал за пять минут и больше не смотрел в него никогда:
		#region Defines convertion
// supress CS0162 in release
public
#if !DEBUG
const
#else
static
#endif
bool AllowFrequencyModification =
#if FQLOCK
false;
#else
true;
#endif
public
#if !DEBUG
const
#else
static
#endif
bool AllowTransmitterNumberModification =
#if NUMLOCK
false;
#else
true;
#endif
#endregion

Плюс в пост-билд эвент был засунут батничек, который компилил в релизе три нужных варианта в разные дллки (и, типа, сапрессил этот варнинг). Всё абсолютно замечательно - в дебаге варнинга нет, в релизе он сапрессится.
Я не исключаю возможности, что существует какой-то способ общения с варнингами, который позволяет наплодить их сто штук и не запутаться. Строить какое-нибудь дерево по файлам/классам, помечать варнинги тэгами, писать к ним комменты, выставлять приорити, контролировать изменения от версии к версии. Потратив тыщу человекочасов, наверное, можно написать плагин к вижуальнику (плюс standalone вариант, естественно (плюс кросплатформенность и возможность настроить под любой язык который это всё будет делать. Но, ты знаешь, ИМХО его никто не купит. Потому что я практически не встречался с жизненными примерами (для шарпа, не для плюсов когда подход "видишь варнинг - убей его сразу!" был сопряжён с какими-то трудностями.
Да и в плюсах всё довольно приятно решается как правило. Полезно, кстати, читать микрософтовский код - он рассчитан на /w4, поэтому в некоторых местах там используются разные милые макросы типа UNREFERENCED_PARAMETER(zzz). И ничего, все щасливы.

Dasar

> Потому что я практически не встречался с жизненными примерами (для шарпа, не для плюсов когда подход "видишь варнинг - убей его сразу!" был сопряжён с какими-то трудностями
все это верно - если рассматривать код, как "плоскую" структуру: код пишется одним человеком, смысл кодируется одного уровня и т.д.
Если же код - пишется несколькими людьми - или мы в код вводим несколько уровней - то все уже не так однозначно.
хотя бы банальный пример - когда, например, интерфейсы определяются одним человеком, а реализуются другим.
в этом случае - есть довольно длительный момент времени - когда программа находится в невалидном состоянии.
тем более к сложной программе - кроме проверок самого компилятора, еще накладываются проверки функциональных тестов, тестов на скорость, проверок того же FxCop-а и т.д.
> нажму ctrl-c,c в) напишу "// TODO: описание" перед ифом
чем это отличается от варнинга выдаваемого компилятором?
все отличие - в привычке.

Marinavo_0507

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

Dasar

> эта проблема была решена уже при изобретении структурного программирования
она решается плохо, вручную и "вбок" от основной ветки изменений

bleyman

интерфейсы определяются одним человеком, а реализуются другим.
в этом случае - есть довольно длительный момент времени - когда программа находится в невалидном состоянии.
тем более к сложной программе - кроме проверок самого компилятора, еще накладываются проверки функциональных тестов, тестов на скорость, проверок того же FxCop-а и т.д.
Человек, определяющий интерфейсы, в процессе пишет заглушки, чтобы код типа начал компилиться. Заглушки ничего не делают, но и варнингов никаких не порождают. Имплементатор превращает заглушки в функциональный код по одной за раз, и пока не устранит все варнинги, к следующей не переходит. Все имеющиеся варнинги всегда относятся к текущему редактируемому куску.
Если руководитель проекта не может так организовать процесс, чтобы программа оказалась в валидном состоянии практически сразу - он лох и не должен руководить проектом.
Дополнительные проверки - это очень клёво, конечно. Только они делятся на две категории - те, результаты которых приравниваются к безусловным еррорам/варнингам и должны быть устранены так же, и те, которые применяются позже, к уже почти готовому коду - вот тесты на скорость, например.
Короче, я не очень понимаю, о чём ты. Лично я не вижу необходимости в сложном варнинг менджменте. Ты говоришь какие-то общие слова типа "сложный многоуровневый проект интерфейсы невалидно бла бла бла" и нифига не приводишь никаких примеров из жизни.
>> "// TODO: описание" перед ифом
> чем это отличается от варнинга выдаваемого компилятором?
Хахаха. Всем. Варнинг, выдаваемый компилятором, говорит о том, что что-то с программой не так. Как правило номер строчки, на котором случается варнинг, не имеет практически никакого отношения к тому месту, в котором на самом деле что-то не так, как, впрочем, и текст варнинга.
TODO находится в том самом месте, где нужно что-то изменить/добавить, "описание" там это уже не жалоба компилятора "я не понимаю чо это за фигня", а указание на то, какую именно фигню нужно написать. Ещё TODO выводятся в отдельное окошко. TODO не исчезают мистическим образом при изменении кода в совершенно другом месте.
Вот кстати программка для управления TODO - это добро. Я бы хотел такую поиметь.

Dasar

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

Dasar

> TODO находится в том самом месте, где нужно что-то изменить/добавить
делить сущности - по физическому воплощению - обычно бессмысленно.

bleyman

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

bleyman

Ну вот, опять бла бла бла.
Я не делю сущности, я пишу в конкретном месте программы, что мне потом в это конкретное место нужно будет добавить конкретную функциональность - в том случае, если добавление её сразу выглядит необоснованным (например, ещё не готова какая-нибудь другая важная часть, без которой я никак не смогу оттестировать эту). Если я вдруг решаю подправить то, что написано в очередной туду, я в неё даблкликаю и оказываюсь именно там, где нужно подправлять.
Если бы у меня была какая-нибудь утилиточка, которая бы позволяла в TODO кроме текстовой мессаги вбивать дополнительную структурированную инфу - типа priority, dependencies, тэги какие-нибудь итд, после чего выводила бы её в какое-нибудь красивое деревце - это было бы хорошо, конечно. Я даже что-то когда-то искал такое, но нифига не нашёл клёвого и забил.

Dasar

> Поскольку мы говорили о варнингах, то я под "валидным состоянием" понимал состояние, в котором программа компилится без оных (при использовании внешних утилит, например, тестозапускалок, учитываются и их варнинги тоже)
И кто ты после этого? т.е. хочешь сказать, что ты не читал начало завязки, а просто решил высказаться о чем-то своем?
Вообще-то речь шла о том стоит ли делать так - что нынешние сообщения компилятора, которые выдаются как ошибки, могли выдаваться как варнинги.

bastii

Сегодня хочется видеть в IDE проверку кода налету, т.е. компиляция используется непосредственно перед запуском/отладкой. При такой схеме обычно все ошибки и ворнинги устраняются сразу.
А с TODO тоже заметил проблему, что когда их со временем накапливается слишком много, то начинаешь терять время на просмотр и поиск "интересных" в данный момент. И вообще работа с ТОДО какая-то бессистемная. Возможно что не правильно используются пометки ТОДО в комментариях. Возможно, то что я в них выражаю, нужно выражать используя какие-то другие средства

Marinavo_0507

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

bleyman

>> Вообще-то речь шла о том стоит ли делать так - что нынешние сообщения компилятора, которые выдаются как ошибки, могли выдаваться как варнинги.
Читал. Потом обсуждение плавно перефокусировалось на то, что происходит, когда варнингов становится слишком уж дофига (логично, правда? по поводу чего я предложил не допускать такого состояния никогда, своевременно убивая всё, а ты начал страдать по поводу недостатков Современных Систем Работы С Данными, которые даже не позволяют эффективно и познавательно показать все варнинги. И сказал, что в Реальном Мире достаточно длительное время программа находится в "невалидном состоянии". Что же ты имел в виду, интересно...

bleyman

>>Сегодня хочется видеть в IDE проверку кода налету, т.е. компиляция используется непосредственно перед запуском/отладкой. При такой схеме обычно все ошибки и ворнинги устраняются сразу.
Ээээ.... Чо сказать-то хотел? =)
Если ты хочешь непрерывную проверку ошибок прямо в процессе вбивания кода - решарпер твой выбор.
А тут вообще ДаркГрей говорил, что когда код пишут одновременно много человек, он постоянно находится в состоянии "не компилится", или хотя бы "дофига варнингов" (ну я так понял ремарку про "невалидность"). Очень странное утверждение, имхо =)

Dasar

> что когда код пишут одновременно много человек, он постоянно находится в состоянии "не компилится", или хотя бы "дофига варнингов"
не так,
надо уметь раздеть - то к чему стремится система сама, и к чему стремимся мы.
Чем больше система- тем больше она стремится находиться в целом в невалидном состоянии, причем невалидной с точки зрения всех состояний и проверок - и это нормальный процесс.
Одной из основной причиной такого явления - является то, что чем больше ситуаций хотим поддержать, тем меньше мы можем сказать о них конкретного/категоричного.
Стандартный пример на термины:
Если мы работаем с птицами: воробей, малиновка, снегирь.
То птица - это летает, с клювом, с перьями, маленькая, дикая.
Если мы добавим к списку: страуса и курицу - то термин "птица" сразу станет менее конкретным.
Тоже самое можно сказать, например, и ожиданиях пользователей:
чем больше пользователей, тем все более сумма требований - взаимоисключающая и менее конкретная.
Соответственно для больших систем - находится с точки зрения всех проверок, требований - в невалидном состоянии - это нормально. И даже больше этого - чем больше система - тем больше она стремиться стать невалидной.
Конечно, нас такое положение мало устраивает, потому что с невалидной системой - невозможно работать, поэтому люди с таким положением борятся просто - они говорят, что есть частично валидная система.
И делают все - чтобы сделать из невалидной - частично валидную.
В частичновалидной системе мы, например, решаем - программа обязана всегда компилироваться, но при этом может не проходить какие-то тесты.
действия при этом - как раз и есть - комментируем куски, которые мы сейчас не готовы поддерживать, вводим версии при больших изменениях, делаем жирные классы и интерфейсы и т.д.
И дальше речь идет о том - что если мы хотим, чтобы этот процесс был эффективен, то нужны инструменты для работы с частично-валидными состояниями систем, чтобы мы этот процесс не в голове держали, а чтобы этот процесс вёл "компьютер".
Хочу заметить - что те же компиляторы, IDE - малыми шажками, но идут по этому направлению.
1 шаг - компиляторы стали выдавать как можно больше ошибок, а не стопаться не на первой ошибке.
2 шаг - intellisence/refactoring корректно работает в том числе и на не компилируемом исходнике

Dasar

> Человек, определяющий интерфейсы, в процессе пишет заглушки, чтобы код типа начал компилиться. Заглушки ничего не делают, но и варнингов никаких не порождают.
Все это опять же верно - если интерфейс и реализация определяются одной компанией.
Если же интерфейсы внешние, то в момент перехода: когда мы собираем код уже с новой версией интерфейсов, то опять же есть период - когда заглушек еще нет, а с кодом уже хочеться работать.
например, именно поэтому и продвигается xml в web-сервисах, чтобы по максимуму уйти от жесткого api-шного стыка, который проверяется компилятором.
При использовании xml-я - изменения интерфейсов - уже не так страшны, т.к. нам более наплевать - появилось что-то новенькое в стыке или нет, пропала часть стыка или нет.

bleyman

Полностью согласен.
>>В частичновалидной системе мы, например, решаем - программа обязана всегда компилироваться, но при этом может не проходить какие-то тесты.
Да, да и ещё раз да! Однако ты зачем-то предлагал опустить планку "частичной валидности" как можно ниже - чтобы компилятор сумел скомпилить все классы кроме тех, которые он скомпилить не может в принципе, насколько я понял.
Точнее даже так: в самом начале ты горько сетовал на то, что unreachable code все равно вынужден проходить все проверки. Это вообще бред, ну да ладно.
Так вот, я уже писал про разницу между варнингами и TODO. ИМХО
а) варнингов, ошибок, непройденных основных тестов етс. в закоммиченом в цвс коде быть не должно (коммит - удобный "момент истины").
б) При этом основные тесты - проверка компилятором корректности кода, например - должны быть безусловно пройденными, и я не вижу никаких сложностей в том, чтобы этого добиться.
Для другой части тестов - на скорость, на соответствие заявленным требованиям, какие-то дополнительные тесты вида "этот метод ничего не делает" - должна быть возможность отрубания для единицы компиляции (одного класса, как в жаве с выставлением соответствующего TODO. И менеджить надо именно TODO, потому что, повторюсь, ошибки как правило не имеют никакого отношения к тому, что именно надо поправить. Ну и соответственно неплохо бы иметь тулзу для обработки TODO.
Вот как-то так.

bleyman

Если же интерфейсы внешние, то в момент перехода: когда мы собираем код уже с новой версией интерфейсов, то опять же есть период - когда заглушек еще нет, а с кодом уже хочеться работать.
----------
Это очень плохое желание, его нужно гнать от себя далеко. Следует вначале написать заглушки и TODO, после чего патчить код на предмет соответствия. Иначе получится спагетти.

Ivan8209

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

Ivan8209

>> эта проблема была решена уже при изобретении структурного программирования
> она решается плохо, вручную и "вбок" от основной ветки изменений
Тоже показатель культуры программирования.
---
...Я работаю антинаучным аферистом...

Ivan8209

> варнингов, ошибок, непройденных основных тестов етс.
> в закоммиченом в цвс коде быть не должно
> (коммит - удобный "момент истины")
Почему?
CVS ведь поддерживает ветвление.
---
...Я работаю антинаучным аферистом...

bleyman

А при чём тут ветвление?

Ivan8209

А почему "быть не должно"?
---
...Я работаю антинаучным аферистом...

Dasar

> Однако ты зачем-то предлагал опустить планку "частичной валидности" как можно ниже - чтобы компилятор сумел скомпилить все классы кроме тех, которые он скомпилить не может в принципе, насколько я понял.
Потому что есть ситуации - когда хочеться работать по сценарию: зацепляем новую версию интерфейсов и далее потихоньку начинаем переводить всю систему на новую версию.
При работе по такому сценарию - уже с первых минут зацепления новых интерфейсов - хочеться иметь возможность гонять тесты.
Сейчас чтобы такую возможность заиметь - надо сначала закомментировать 90%-кода и 95% тестов, потом потихоньку разкомментировывать и код, и тесты.
И проблема в следующем: если бы компилятор - умел компилировать частичновалидный код, то мы в этом случае имели бы хотя бы высокоуровневую картинку - что вот в таких-то классах 5 ошибок, в таких-то 120, такие-то не проходят один тест, такие-то 300.
При комментирования кода - мы "слепнем" полностью, т.к. на руках не имеем ничего - ни кода (хоть какого-нибудь ни тестов.
Опять же на частичновалидной компиляции - мы можем уже с первых минут смотреть, как влияют на всю систему наши изменения, и "улучшают" они положение, или нет.
При комментировании кода - часто возникает ситуации, что часть вариантов мы сможем увидеть, только в тот момент, когда мы все-таки вспомним, что надо расскоментировать такие-то куски кода и тестов.
ps
Самое разрушительное, конечно, для программы - это какое-либо измение архитектуры (изменение интерфейсов - это следствие) и как раз при таких изменениях - и может требоваться комментирование до 95% кода.
И опять же в таких случаях - очень важна возможность прогонки тестов с первых минут изменения, чтобы убедиться, что при изменении архитектуры - мы не напоролись на какой-нибудь подводный камень (который может потребовать или дальнейшего модификации архитектуры, или отказ от такого изменения архитектуры).

Dasar

> Следует вначале написать заглушки и TODO, после чего патчить код на предмет соответствия. Иначе получится спагетти.
Почему ты считаешь, что написание заглушек и TODO - это более эффективный путь, чем работа со спагетти?
Я с тобой полностью согласен, что 95% жизни - код должен быть полностью валиден, и стабилен.
Но вот в оставшиеся 5% (например, при серьезных изменениях) - работать на уровне спагетти намного эффективнее, чем писать какие-то заглушки и TODO.

Dasar

> Это говорит лишь о том, что виндузятники плохо знакомы
> с такими не самыми новыми достижениями культуры программирования, как VCS,
Интересно, почему ты часто считаешь, что ты умнее других?
Этому есть объективные доказательства? или это просто высокое самомнение?
Комментирование с последующей прогонкой через vcs - намного более наглядный способ для малых изменений, чем просто прогонка через vcs.
т.к. в случае комментирования - в коде остается подтверждение, что мы были не полностью уверены в том, или ином изменении.

Ivan8209

> Этому есть объективные доказательства?
Да.
Достаточно посмотреть туда, где требуется создать
как можно больше удобства для работы человека.
> Комментирование с последующей прогонкой через vcs -
> намного более наглядный способ для малых изменений,
> чем просто прогонка через vcs.
Это очень вредный способ внесения любых изменений.
Для наглядности VCS поддерживает diff,
а для комментирования есть журнал той же VCS.
---
...Я работаю антинаучным аферистом...

Dasar

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

Ivan8209

Я мимо проходил.
Например, glebius.
---
...Я работаю антинаучным аферистом...

bleyman

>>Почему ты считаешь, что написание заглушек и TODO - это более эффективный путь, чем работа со спагетти?
Потому что работая со спагетти ты получаешь рубленые спагетти =)
Увеличивать энтропию с понтом что щаз мы напряжёмся и резко её уменьшим - это очень плохая привычка. С возрастанием энтропии следует бороться порядком, это, по крайней мере, гарантирует, что она не возрастёт ещё больше.

bleyman

А это ты к чему спросил?
Когда ты отвечаешь на какой-то коммент, тыкай в кнопку "ответить" относящуюся к нему.

Dasar

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

Dasar

> Увеличивать энтропию с понтом что щаз мы напряжёмся и резко её уменьшим
ты в курсе - что переход между двумя состояниями системы с низким уровнем энтропии, в общем случае, требует переход через состояния с высоким уровнем энтропии?
или это надо тебе доказывать?
именно поэтому не пошли редакторы кода, которые позволяли редактировать код только на уровне отдельных конструкций, а не уровне сплошного текста.

bleyman

Я в курсе.
Ещё я в курсе, что любая достаточно жизнеспособная система обладает прямо противоположным свойством.

Ivan8209

То есть, по-твоему, большая часть open source разработчиков
с удовольствием выкинула бы CVS, DARCS или Subversion?
Я наблюдаю совершенно противоположное:
за какие-то полгода мои знакомые так или иначе переползли на VCS.
И среди них есть даже те, кто не занимается разработкой ПО.
---
"Математик может говорить, что ему хочется,
но физик должен, хотя бы в какой-то мере, быть в здравом рассудке."

Ivan8209

> требует переход через состояния с высоким уровнем энтропии
Наглая ложь.
---
"Математик может говорить, что ему хочется,
но физик должен, хотя бы в какой-то мере, быть в здравом рассудке."

bleyman

Я уже нопейсал ему =)

Dasar

> То есть, по-твоему, большая часть open source разработчиков
с удовольствием выкинула бы CVS, DARCS или Subversion?
расскажи - как ты такой вывод сделал из фразы, что
комментирование + vcs - удобнее, чем просто vcs
?
очень интересно посмотреть на логическую цепочку - очень умного человека.

Ivan8209

А почему на вопрос
O> Почему в Правильном Языке C# запрещены
O> static-методы/свойства/эвенты ...
Ты даёшь ответ с обоснованием
DG> именно поэтому не пошли редакторы кода,
DG> которые позволяли редактировать код
DG> только на уровне отдельных конструкций,
DG> а не уровне сплошного текста.
?
---
"Мы так жить будем, что наши внуки нам завидовать будут."

enochka1145

// Ещё я в курсе, что любая достаточно жизнеспособная система обладает прямо противоположным свойством.
А читал, что когда делают такой вывод, перескакивают на новый уровень. То есть, например, если с атомов перейти на молекулы, то хаоса меньше. А если всё-таки не переходить...

Dasar

> почему на вопрос
потому что дисскусия давно вышла за рамки первоначальной темы,
а я как модератор - не разнес тред,
а ты как пользователь - не прислал notify-ай об этом.

Ivan8209

Что ты ещё читал про энтропию?
---
"Математик может говорить, что ему хочется,
но физик должен, хотя бы в какой-то мере, быть в здравом рассудке."

Ivan8209

Ты поддерживаешь нецелевое использование
комментариев на основании устаревшей практики.
Мало того, ещё и необоснованно отвергаешь самые надёжные доводы.
---
"Математик может говорить, что ему хочется,
но физик должен, хотя бы в какой-то мере, быть в здравом рассудке."

bleyman

Неа. Просто жизнеспособная система могла возникнуть только в том случае, если ей не приходилось выходить на более высокий уровень энтропии в процессе развития. И, что самое главное, её "жизнеспособность" как раз и заключается в свойствах, позволяющих развиваться непрерывно уменьшая энтропию.
Теорию "Intelligent Design" мы грамотно обходим стороной, бо откуда у архитекторов софта intelligence
А если серьёзно, то построить офигенно сложную систему с нуля возможно, конечно, но единственный (ИМХО) способ вложить в неё возможность развития - это постоянно думать о том, как бы перейти к следующей версии не проходя через существенно высокоэнтропийную стадию.
Очень жалко ДаркГрея, у которого 90% кода (и 95% тестов) проходят через стадию комментирования после изменения внешних интерфейсов. Я бы так не смог, хнык, хнык.

enochka1145

OK. Я это так прочитал как "Надо не лениться, следить за порядком, а не откладывать это на конец [проекта]". Если да, то я с этим согласен.

enochka1145

"Математик может говорить, что ему хочется,
но физик должен, хотя бы в какой-то мере, быть в здравом рассудке."
---
А инженер (или программист) должен быть в ещё более здравом рассудке. Потому что, в отличие от кабинетных ИДИОТов-идеалистов, которым кроме своей тупой башки терять нечего, он несёт ответственность перед своими коллегами и клиентами, а также перед своим будущим. А занятие математикой позволяют ему лучше организовать мышление и быть беспристрастным в поиске истины, а не передёргивать или навешивать ярлыки на собеседников ("боевики", "насильники", "сантехники"... как политик-проститутка.

bleyman

Хаха, Контра довёл джЮнита до нервного срыва, гы гы.
Не расстраивайся, все жава-программеры по определению сан-техники, но это очень почётное звание, неси его с честью. По крайней мере, Твой Любимый Язык не даст тебе запутать другого сан-техника, который будет читать твой код...
* напряжённо думает про передачу аут-параметров через массивы
... или даст, неважно, всё равно неси с гордостью!

Ivan8209

В отличие от разных кофейников и приплюснутых виндузятников,
open source разработчики подарили мне много удобных средств для работы.
Это насчёт ответственности.
Об истине в математике.
Расскажи, истинна ли аксиома выбора?
А континуум-гипотеза?
Если тебе больше нравится логика,
то как насчёт закона исключённого третьего?
---
"Абстрактной истины нет, истина всегда конкретна."

Ivan8209

Сказал гордый изобретатель функционалов в C#.
---
"Товарищи! Кому не интересно, тот может выйти! Мы никого не держим.
Закройте там двери на ключ и никого не выпускать!
Демократия должна быть для всех!.."

enochka1145

Повышаем... эту... сомооценку, о программист на Microsoft Java (т.е. C#)?
Сразу видно, реальный пацан. И с телепатией полный порядок...

enochka1145

В отличие от разных кофейников и приплюснутых виндузятников,
open source разработчики подарили мне много удобных средств для работы.
Это насчёт ответственности.
Eclipse - open source. И что? При чём здесь ответственность? "Контрим"?
Об истине в математике.
Фраза "... в поиске истины..." мне не очень понравилась своей... э-э... категоричностью, но ничего лучше я не родил. Так что поищи собеседников в другом месте, например, в Study.

Ivan8209

Я не видел ни одного человека, использующего Eclipse.
Хотя видел даже фанатов питона.
Мог бы и родить.
Как-никак, в университете обучался.
---
"Vyroba umelych lidi, slecno, je tovarni tajemstvi."

bobby

А я видел Python-программистов, которые писали в Python-среде, сделанной на Eclipse!

enochka1145

// Я не видел ни одного человека, использующего Eclipse...
Что ты там про narrowness of experience-то говорил?

Ivan8209

Хде?
Где посмотреть на такое чудо?
---
...Я работаю антинаучным аферистом...

bobby

lack of experience там было
Очень клевая фраза

Ivan8209

Я ничего такого не говорил.
---
...Я работаю антинаучным аферистом...

enochka1145

-с?

Ivan8209

Это не я сказал.
---
...Я работаю антинаучным аферистом...

bleyman

Ты ничего такого не говорил?

Ivan8209

Open source Java VM поставляется вместе с Eclipse?
Что в нём есть такое, что даёт выигрыш перед GNU/чего-нибудь униксоподобное?
---
...Я работаю антинаучным аферистом...

enochka1145

ТЕБЕ я этого объяснять не буду. Хватит с меня того случая, когда после многих часов удалось выяснить, что же тебе не нравится в Java - оказалось, что не нравится разделение "один файл - один публичный класс".
Кому надо - узнает сам. Ну или у меня спросит.

Ivan8209


"Vyroba umelych lidi, slecno, je tovarni tajemstvi."

Слив?

enochka1145

A kfoq kemsik as unasoq, Tchapek, y afga tive miah?
Оставить комментарий
Имя или ник:
Комментарий: