Здравствуйте, Курилка, Вы писали:
К>Не знаю, туда ли пощу, но вот МС выложила новое расширение шарпа К>Хотелось бы услышать мнения — нужно ли оно и насколько?
Здравствуйте, Andrei N.Sobchuck, Вы писали:
ANS>Здравствуйте, Курилка, Вы писали:
К>>Не знаю, туда ли пощу, но вот МС выложила новое расширение шарпа К>>Хотелось бы услышать мнения — нужно ли оно и насколько?
ANS>non null types — мечта многих.
К>>>Не знаю, туда ли пощу, но вот МС выложила новое расширение шарпа К>>>Хотелось бы услышать мнения — нужно ли оно и насколько?
ANS>>non null types — мечта многих.
К>Просвети чайника — почему я о них не мечтаю?
Не знаю. Я о них тоже не мечтал. Но людям постоянно хочется чего-нибудь эдакого...
Здравствуйте, Курилка, Вы писали:
К>Не знаю, туда ли пощу, но вот МС выложила новое расширение шарпа К>Хотелось бы услышать мнения — нужно ли оно и насколько?
Мысль конечно здравая:
class ArrayList
{
void Insert(int index , object value)
requires 0 <= index && index <= Count otherwise ArgumentOutOfRangeException;
requires !IsReadOnly && !IsFixedSize otherwise NotSupportedException;
{
//...
}
//...
}
Но чем это принципиально лучше того что и так есть (извиняюсь за код на другом языке):
Здравствуйте, Сергей Губанов, Вы писали:
СГ>Здравствуйте, Курилка, Вы писали:
К>>Не знаю, туда ли пощу, но вот МС выложила новое расширение шарпа К>>Хотелось бы услышать мнения — нужно ли оно и насколько?
СГ>Еще один синтаксический сахар? Еще одна помощь для intellisense?
Мегасуть в том, что требования наследуются (code reuse), их нельзя убрать из предка (целостность интерфейса) ну и можно проверить целостность на этапе компиляции (есть тулза Boogie для этого).
Здравствуйте, Сергей Губанов, Вы писали:
СГ>Здравствуйте, Курилка, Вы писали:
К>>Не знаю, туда ли пощу, но вот МС выложила новое расширение шарпа К>>Хотелось бы услышать мнения — нужно ли оно и насколько?
... СГ>Но чем это принципиально лучше того что и так есть (извиняюсь за код на другом языке):
...
Здравствуйте, Oyster, Вы писали:
O>Мегасуть в том, что требования наследуются (code reuse), их нельзя убрать из предка (целостность интерфейса) ну и можно проверить целостность на этапе компиляции (есть тулза Boogie для этого).
Это кстати очень странно. Я понимаю, что постусловия нельзя убирать, равно как и инварианты.
Но предусловия
Как я тогда смогу написать новый класс, который обрабатывает более широкий класс входных параметров?
... << RSDN@Home 1.1.4 beta 5 rev. 395>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, Oyster, Вы писали:
O>>Мегасуть в том, что требования наследуются (code reuse), их нельзя убрать из предка (целостность интерфейса) ну и можно проверить целостность на этапе компиляции (есть тулза Boogie для этого). S>Это кстати очень странно. Я понимаю, что постусловия нельзя убирать, равно как и инварианты. S>Но предусловия S>Как я тогда смогу написать новый класс, который обрабатывает более широкий класс входных параметров?
потому что если ты это делаешь при помощи виртуальной функции, которая нагружена предусловиями в базовом классе, то и с новым ты можешь работать так же, как и со старым, а старый выдавал ошибку.
В общем, та же противоречивая байда, что и со спецификациями исключений.
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, Oyster, Вы писали:
O>>Мегасуть в том, что требования наследуются (code reuse), их нельзя убрать из предка (целостность интерфейса) ну и можно проверить целостность на этапе компиляции (есть тулза Boogie для этого). S>Это кстати очень странно. Я понимаю, что постусловия нельзя убирать, равно как и инварианты. S>Но предусловия S>Как я тогда смогу написать новый класс, который обрабатывает более широкий класс входных параметров?
Ты сможешь сделать предусловия строже, но не сможешь их ослабить. Вообще — речь об одном и том же методе. Если, скажем, у тебя такой вот метод:
class Base
{
public int Subtract10(int n)
requires n > 10 otherwise ArgumentOutOfRangeException;
{
return n - 10;
}
}
то в наследнике нельзя потребовать, чтобы метод Subtract10() принимал любые целые, зато можно сказать, например, n < 20. И это правильно, потому что вызывающая сторона ожидает, что n должно быть больше 10, даже если у нас в руках экземпляр наследника с перекрытым методом...
Ну а если хочешь делать новые методы — так делай, никто ж не против Потому как предусловия касаются только метода, насколько я понял.
ASSERT( ~IsReadOnly & ~IsFixedSize), 21);
O>Мегасуть в том, что требования наследуются (code reuse), их нельзя убрать из предка (целостность интерфейса).
Наверное я чего-то не совсем понимаю, но мне кажется, что вся суть наследования виртуального (абстрактного, или реализация интерфесного) метода как раз в том и состоит, что он будет реализован по разному. А значит и пред/пост-условия у разных реализаций, как бы, практически всегда разные. В самом деле, если какая-то реализация того самого List является динамически расширяемой в размерах, то предусловие ~IsFixedSize зачем для нее проверять-то, оно ведь и так всегда true. Или для записываемой реализации, зачем каждый раз при каждой активации этого метода проверять ~IsReadOnly если для данной реализации это всегда истинно?
Короче, мне кажется что пред/пост условия принадлежат реализации, а не интерфейсу (у каждой реализации эти условия могут быть своими).
Или же тогда должна быть возможность отменять в потомках ставшие более не нужными проверки. Например в расширяемой записываемой реализации List-а, проверка на ~IsReadOnly & ~IsFixedSize должна быть отключена, как все равно всегда истинная (нечего ее производить при каждом вызове данной реализации метода Insert).
Но если сначала дать возможность наследовать пред/пост-условия, а потом отменить их проверку в некоторых частных случаях, то это какая-то ерунда будет.
Механизм пред/пост-условий осуществляемй с помощью обычного старого доброго ASSERT слишком прост чтобы выйти из под контроля, в то же время использование механизма наследования пред/пост-условий с возможностью отключения некоторых из них в потомках мне кажется слишком многословным, громоздким.
Имхо всё-таки не совсем понимаешь. В чём идея наследования? В общем интерфейсе и разных конкретизациях.
На примере многострадального ArrayList-а — если, например, наследник всегда не read-only, то у него IsReadOnly всегда вернёт false и компайлер вполне сможет соптимизить этот момент в проверке (это про performance). Но суть ограничений от этого не меняется — нельзя вставлять в read-only список, в не зависимости от того, что там в наследнике. Мы абстрагируемся от реализации не только общим интерфейсом (метод Insert будет вставлять элемент и в потомке, и caller будет на это рассчитывать), но и общими условиями (нельзя вставлятьл в read-only список, и caller будет рассчитывать и на это). Так безопаснее.
И действительно безопаснее определить constraints на декларативном уровне, потому что в случае "классического" assert caller узнает про ограничения только из документации. Да и в наследнике приходится надеяться на то, что программист не забыл сунуть assert.
PS: И снова про compile-time. Assert — исключительно runtime-средство, в то вреня как в предлагаемой в Spec# концепции проверка может осуществляться и в compile-time (Spec# — это не только язык, но и набор тулзов).
Здравствуйте, jazzer, Вы писали: J>потому что если ты это делаешь при помощи виртуальной функции, которая нагружена предусловиями в базовом классе, то и с новым ты можешь работать так же, как и со старым, а старый выдавал ошибку.
Очень странно. А почему тогда усиливать можно? Ведь старый не выдавал ошибку!
... << RSDN@Home 1.1.4 beta 5 rev. 395>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Oyster, Вы писали: O>Ты сможешь сделать предусловия строже, но не сможешь их ослабить. Вообще — речь об одном и том же методе.
Вот я и спрашиваю — почему? Это бред. O>Если, скажем, у тебя такой вот метод: O>
O>class Base
O>{
O> public int Subtract10(int n)
O> requires n > 10 otherwise ArgumentOutOfRangeException;
O> {
O> return n - 10;
O> }
O>}
O>
O>то в наследнике нельзя потребовать, чтобы метод Subtract10() принимал любые целые, зато можно сказать, например, n < 20. И это правильно, потому что вызывающая сторона ожидает, что n должно быть больше 10, даже если у нас в руках экземпляр наследника с перекрытым методом...
Бред. Ничего правильного в этом нету. Принцип Лисков нарушается. Потому что вызывающая сторона привыкла к тому, что можно передавать 30. А теперь, видите ли, нельзя. Предусловие — это требование к вызывающему!
Должно быть все наоборот: перекрытые предусловия монут быть такими же и слабее. Т.е. наследник всегда может только усиливать свои обязательства. Вот с постусловиями все верно. Если у нас есть контракт, в котором оговорено, что результат != 0, то вызывающая сторона спокойно на него делит. И ожидает, что наследники не будут отменять это условие.
O>Ну а если хочешь делать новые методы — так делай, никто ж не против Потому как предусловия касаются только метода, насколько я понял.
Нет, я хочу расширять поведение метода. В соответствии с принципами ООП.
... << RSDN@Home 1.1.4 beta 5 rev. 395>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, Oyster, Вы писали: O>>Ты сможешь сделать предусловия строже, но не сможешь их ослабить. Вообще — речь об одном и том же методе. S>Вот я и спрашиваю — почему? Это бред.
Упс. Бред, конечно Это я доку левым глазхом читал ВОобще нельзя с ними ничего поделать.
O>>Если, скажем, у тебя такой вот метод: O>>
O>>class Base
O>>{
O>> public int Subtract10(int n)
O>> requires n > 10 otherwise ArgumentOutOfRangeException;
O>> {
O>> return n - 10;
O>> }
O>>}
O>>
O>>то в наследнике нельзя потребовать, чтобы метод Subtract10() принимал любые целые, зато можно сказать, например, n < 20. И это правильно, потому что вызывающая сторона ожидает, что n должно быть больше 10, даже если у нас в руках экземпляр наследника с перекрытым методом... S>Бред. Ничего правильного в этом нету. Принцип Лисков нарушается. Потому что вызывающая сторона привыкла к тому, что можно передавать 30. А теперь, видите ли, нельзя. Предусловие — это требование к вызывающему!
Согласен. См. выше.
S>Должно быть все наоборот: перекрытые предусловия монут быть такими же и слабее. Т.е. наследник всегда может только усиливать свои обязательства. Вот с постусловиями все верно. Если у нас есть контракт, в котором оговорено, что результат != 0, то вызывающая сторона спокойно на него делит. И ожидает, что наследники не будут отменять это условие.
O>>Ну а если хочешь делать новые методы — так делай, никто ж не против Потому как предусловия касаются только метода, насколько я понял. S>Нет, я хочу расширять поведение метода. В соответствии с принципами ООП.
Тогда юзай C# там этого сахара нету.
А ещё лучше — почитай доку — я сам только сегодня этот Spec# первый раз в жизни увидел.
Spec# does not allow any changes in the precondition, because callers expect the specification at the static resolution of the method to agree with the dynamic checking.
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, jazzer, Вы писали: J>>потому что если ты это делаешь при помощи виртуальной функции, которая нагружена предусловиями в базовом классе, то и с новым ты можешь работать так же, как и со старым, а старый выдавал ошибку. S>Очень странно. А почему тогда усиливать можно? Ведь старый не выдавал ошибку!
Здравствуйте, Курилка, Вы писали:
К>Не знаю, туда ли пощу, но вот МС выложила новое расширение шарпа К>Хотелось бы услышать мнения — нужно ли оно и насколько?
С одной стороны весьма занимательно и обнадёживающе, с другой стороны — я озадачен
Всё, что пытается решаеть Spec# — задачи АОП. Радует то, что MS вообще этим занимается. Признаться честно, я отковенно рад. Но озадачивает способ, который используют ребята. Не думаю, что введение нового ключевого слова на каждый случай — это хорошая идея. Возможно существующие исследования в АОП не отражают всех чаяний народа, но изобретение своего собственного велосипеда тоже не лучший вариант
... << RSDN@Home 1.1.4 beta 5 rev. 395>>
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, Курилка, Вы писали:
К>Не знаю, туда ли пощу, но вот МС выложила новое расширение шарпа К>Хотелось бы услышать мнения — нужно ли оно и насколько?
Расширение касается не столько разработки, сколько верификации и тестировния ПО.
Основная идея: пишем спецификации каждого (или почти каждого) метода, а затем среда выполнения проверяет насколько корректно вызывается метод, короче почти assert но более навороченный, поскольку позволяет описывать действия не только в явномном, н (как assert)о и неявном виде.
Это вообще-то не представляет особого интереса, а вот верификация программ "The Spec# static program verifie" это шаг в перед. С помощью его можно по составленным спецификациям каждого из методов, сгенерить кучу тестов, которые переберут множество комбинаций входных параметров метода, и скажут (ласково ) при каких входных параметрах чего не заработало.
Общее название подобных пометодов — тестирование на основе моделей. Строим модель (спецификации методов) и по ней генерим тесты. Что интересно эти технологии достаточно неплохо развиты у нас в России (можно сказать появились здесь) http://unitesk.com/ru/.
У этих ребят из unitesk есть реализации подобных технологий на различных языках программирования: С, Ява, и в частности С#. Т.е. МС не первые в этом деле (пока ).
К>Хотелось бы услышать мнения — нужно ли оно и насколько?
Короче. Эта хрень не нужна. . А если нужна, то только для проектов в которых огромное!! внимание уделяется тестированию, верификации и пр.