Каковы некоторые преимущества ввода утки по сравнению со статическим контролем типов?

Рассмотрим следующий пример из Java Programming by James Gosling, в котором мы хотим объединить 2 SinglyLinkQueue:

public static <T1, T2 extends T1> void merge(SinglyLinkQueue<T1> d, SinglyLinkQueue<T2> s){
    // merge s element into d
}

public static <T> void merge(SinglyLinkQueue<T> d, SinglyLinkQueue<? extends T> s){
        // merge s element into d
}

Оба вышеупомянутых метода имеют одинаковую функциональность. Итак, что предпочтительнее? Ответ второй. В собственных словах автора:

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

Примечание. В книге указывается только второй метод и имя параметра типа S вместо «T». Первый метод в книге отсутствует.

27
задан codeLes 10 February 2009 в 16:41
поделиться

10 ответов

Затем, который лучше: EMACS или vi? Это - одна из рабочих религиозных войн.

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

Это не, как будто динамический контроль типов является новой и другой вещью: C, например, эффективно с динамическим контролем типов, так как я могу всегда бросать foo* к bar*. Это просто означает, что это - тогда моя обязанность в качестве программиста C никогда не использовать код, который является соответствующим на bar*, когда адрес действительно указывает foo*. Но в результате проблем с большими программами, C вырастил инструменты как линт (1), усилил его систему типов с typedef и в конечном счете разработал вариант со строгим контролем типов в C++. (И, конечно, C++ в свою очередь разработал пути вокруг строгого контроля типов со всеми вариантами бросков и дженериков/шаблонов и с RTTI.

Еще одна вещь, хотя---не путают "гибкое программирование" с "динамическими языками". Гибкое программирование о способе, которым люди сотрудничают в проекте: проект может адаптироваться к изменяющимся требованиям для удовлетворения потребностей клиентов при поддержании гуманной среды для программистов? Это может быть сделано с динамически типизированными языками, и часто, потому что они могут быть более продуктивными (например, Ruby, Smalltalk), но это может быть сделано, был сделан успешно, в C и даже ассемблере. На самом деле, Ралли Development даже использование гибкие методы (ТОЛПА в особенности), чтобы сделать маркетинг и документацию.

7
ответ дан Charlie Martin 14 October 2019 в 13:21
поделиться

Нет ничего неправильно со статическим контролем типов при использовании Haskell который имеет невероятную статическую систему типов. Однако, если Вы используете языки как Java и C++, которые имеют ужасно наносящие вред системы типов, утиный ввод является определенно улучшением.

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

10
ответ дан Nick Retallack 14 October 2019 в 13:21
поделиться

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

Мой новый любимый аргумент против [1 111] утиный ввод прибывает из DTO проекта Grails:

class SimpleResults {
    def results
    def total
    def categories
}

, где results оказывается чем-то как Map<String, List<ComplexType>>, который может быть обнаружен только следующим след вызовов метода в различных классах, пока Вы не находите, где он был создан. Для оконечно любопытного, total сумма размеров List<ComplexType>, с и categories является размером Map

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

9
ответ дан Ken Gentle 14 October 2019 в 13:21
поделиться

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

7
ответ дан Jason Baker 14 October 2019 в 13:21
поделиться

По моему скромному мнению, преимущество утиного ввода становится увеличенным, когда Вы придерживаетесь некоторых соглашений, таких как именование Вас переменные и методы последовательным способом. Беря пример от [1 115] Ken G, я думаю, что это читало бы лучше всего:

class SimpleResults {
    def mapOfListResults
    def total
    def categories
}

Скажем, Вы определяете контракт на некоторой операции, названной 'calculateRating (A, B)', где A и B придерживаются другого контракта. В псевдокоде это читало бы:

Long calculateRating(A someObj, B, otherObj) {

   //some fake algorithm here:
   if(someObj.doStuff('foo') > otherObj.doStuff('bar')) return someObj.calcRating());
   else return otherObj.calcRating();

}

, Если Вы хотите реализовать это в Java, и A и B должны реализовать некоторый интерфейс, который читает что-то вроде этого:

public interface MyService {
    public int doStuff(String input);
}

Кроме того, если Вы хотите обобщить Вас контракт для вычисления оценок (скажем, у Вас есть другой алгоритм для оценки вычислений), также необходимо создать интерфейс:

public long calculateRating(MyService A, MyServiceB);

С утиным вводом, можно угробить Ваш интерфейсы и просто положиться, что на времени выполнения, и A и B правильно ответят на Ваш doStuff() вызовы. Нет никакой потребности в определенном определении контракта. Это может работать на Вас, но это может также работать против Вас.

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

Примечание, которое это ухудшает особенно в Java, где синтаксис не является столь кратким, как это могло быть (по сравнению с Scala, например). Контрпример этого платформа Лифта , где они говорят, что количество SLOC платформы подобно направляющие , но тестовый код имеет меньше строк, потому что они не должны реализовывать проверки типа в тестах.

4
ответ дан Miguel Ping 14 October 2019 в 13:21
поделиться

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

1
ответ дан Chris Bunch 14 October 2019 в 13:21
поделиться

Набор @Chris

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

Жаль, но я должен был сделать это...

1
ответ дан Vincent Robert 14 October 2019 в 13:21
поделиться

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

Groovy кажется мне таким же образом. Конечно, вы можете написать очень краткий код и определенно есть какой-то хороший сахар в том, как мы добились работы со свойствами, коллекциями и т. Д. В какой-то момент ваша царапающая голова задавалась вопросом, почему проект стал 80% тестированием и 20%. Урок вот что «меньше» не делает «более читаемый» код. Извините, люди, его простая логика - тем больше вы должны интуитивно знать, чем более сложный процесс понимания того, что кодекс становится. Поэтому GUI отступил к чрезмерно сланскому искочеству в течение многих лет - наверняка выглядит красиво, но WTH идет не всегда очевидно.

Люди в этом проекте, казалось, имели проблемы «прибиты» извлеченные уроки, но когда у вас есть методы, возвращающие один элемент типа T, массив T, ошибочно или нулевой ... это становится довольно очевидной Отказ

Одна вещь, работающая с Groovy сделала для меня, однако - потрясающие платежные часы Woot!

16
ответ дан 28 November 2019 в 04:46
поделиться

Вот один сценарий, в котором утка сокращает работу.

Вот очень простой класс

class BookFinder {
    def searchEngine

    def findBookByTitle(String title) {
         return searchEngine.find( [ "Title" : title ] ) 
    }
}

Теперь о модульном тесте:

void bookFinderTest() {
    // with Expando we can 'fake' any object at runtime.
    // alternatively you could write a MockSearchEngine class.
    def mockSearchEngine = new Expando()
    mockSearchEngine.find = {
        return new Book("Heart of Darkness","Joseph Conrad")
    }

    def bf = new BookFinder()
    bf.searchEngine = mockSearchEngine
    def book = bf.findBookByTitle("Heart of Darkness")
    assert(book.author == "Joseph Conrad"
}

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

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

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

Это преимущество утиного набора текста. Это не означает, что динамическая типизация - правильная парадигма для использования во всех ситуациях. В моих проектах Groovy мне нравится возвращаться к Java в обстоятельствах, когда я чувствую, что предупреждения компилятора о типах мне помогут.

3
ответ дан 28 November 2019 в 04:46
поделиться

Мое мнение:

Динамически типизированные или duck-типизированные языки - это игрушки. Вы не можете получить Intellisense и теряете проверку кода во время компиляции (или редактирования - при использовании настоящей IDE, такой как VS, а не того мусора, который другие люди считают IDE).

Держитесь подальше от всех языков, которые не являются статически типизированными, все остальное - просто мазохизм.

1
ответ дан 28 November 2019 в 04:46
поделиться
Другие вопросы по тегам:

Похожие вопросы: