Ruby и утиный ввод: дизайн невозможного контракта?

В Java все находится в форме класса.

Если вы хотите использовать любой объект, тогда у вас есть две фазы:

  1. Объявить
  2. Инициализация

Пример:

  • Объявление: Object a;
  • Инициализация: a=new Object();

То же самое для концепции массива

  • Объявление: Item i[]=new Item[5];
  • Инициализация: i[0]=new Item();

Если вы не дают секцию инициализации, тогда возникает NullpointerException.

19
задан Andrew Grimm 11 June 2010 в 14:00
поделиться

6 ответов

Я утверждал бы, что, хотя метод Java дает Вам [еще 112] информация, он не дает Вам достаточно информация к удобно программе против.
, Например, то, что Список Строк просто имена файлов или полностью определенные пути?

, Учитывая, что, Ваш аргумент, что Ruby не дает Вам достаточно информации также, относится к Java.
Вы все еще полагаетесь на чтение документации, рассмотрение исходного кода, или вызов метода и рассмотрение его вывода (и достойное тестирование, конечно).

8
ответ дан 30 November 2019 в 02:20
поделиться

То, к чему это сводится, - то, что get_files_in дурная слава в Ruby - позволяют мне объяснить.

В java/C#/C ++, и особенно в цели C, аргументы функции являются частью имени . В рубине они не.
необычный термин для этого Перегрузка метода , и это осуществляется компилятором.

Размышление о нем в тех терминах, Вы просто определяете метод, названный get_files_in, и Вы на самом деле не говорите, что это должно вложить файлы. Аргументы не часть имени, таким образом, Вы не можете полагаться на них для идентификации его.
это должно получить файлы в каталоге? диск? сетевой ресурс? Это открывает возможность для него для работы во всех вышеупомянутых ситуациях.

, Если Вы хотели ограничить его каталогом, затем принять эту информацию во внимание, необходимо назвать метод get_files_in_directory. Кроме того, Вы могли сделать это методом на Directory класс, который Ruby уже делает для Вас .

Что касается типа возврата, это подразумевается от get_files, что Вы возвращаете массив файлов. Вы не должны волноваться об этом являющийся List<File> или ArrayList<File>, или таким образом, на, потому что все просто используют массивы (и если они записали пользовательский, они запишут это для наследования созданному в массиве).

, Если бы Вы только хотели получить один файл, Вы назвали бы его get_file или get_first_file или и так далее. Если Вы делаете что-то более сложное, такое как возврат FileWrapper объекты, а не просто представляет в виде строки, то существует действительно хорошее решение:

# returns a list of FileWrapper objects
def get_files_in_directory( dir )
end

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

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

30
ответ дан 30 November 2019 в 02:20
поделиться

В то время как я люблю статический контроль типов, когда я пишу код Java, нет никакой причины, что Вы не можете настоять на вдумчивых предварительных условиях в коде Ruby (или никакой вид кода в этом отношении). Когда я действительно должен настоять на предварительных условиях для параметрических усилителей метода (в Ruby), я рад записать условие, которое могло выдать исключение на этапе выполнения для предупреждения об ошибках программиста. Я даже даю мне подобие статического контроля типов путем записи:

def get_files_in(directories)
   unless File.directory? directories
      raise ArgumentError, "directories should be a file directory, you bozo :)"
   end
   # rest of my block
end

мне не кажется, что язык препятствует тому, чтобы Вы делали дизайн контракта. Скорее мне кажется, что это до разработчиков.

(BTW, "тип" обращается к искренне Вашему :)

6
ответ дан 30 November 2019 в 02:20
поделиться

Проверка метода через ввод утки:

i = {}
=> {}
i.methods.sort
=> ["==", "===", "=~", "[]", "[]=", "__id__", "__send__", "all?", "any?", "class", "clear", "clone", "collect", "default", "default=", "default_proc", "delete", "delete_if", "detect", "display", "dup", "each", "each_key", "each_pair", "each_value", "each_with_index", "empty?", "entries", "eql?", "equal?", "extend", "fetch", "find", "find_all", "freeze", "frozen?", "gem", "grep", "has_key?", "has_value?", "hash", "id", "include?", "index", "indexes", "indices", "inject", "inspect", "instance_eval", "instance_of?", "instance_variable_defined?", "instance_variable_get", "instance_variable_set", "instance_variables", "invert", "is_a?", "key?", "keys", "kind_of?", "length", "map", "max", "member?", "merge", "merge!", "method", "methods", "min", "nil?", "object_id", "partition", "private_methods", "protected_methods", "public_methods", "rehash", "reject", "reject!", "replace", "require", "respond_to?", "select", "send", "shift", "singleton_methods", "size", "sort", "sort_by", "store", "taint", "tainted?", "to_a", "to_hash", "to_s", "type", "untaint", "update", "value?", "values", "values_at", "zip"]
i.respond_to?('keys')
=> true
i.respond_to?('get_files_in')  
=> false

, После того как у Вас есть то обоснование вниз, сигнатуры методов спорны, потому что можно протестировать их в функции динамично. (это происходит частично из-за неспособности, действительно делают signature-match-based-function-dispatch, но это более гибко, потому что можно определить неограниченные комбинации подписей)

 def get_files_in(directories)
    fail "Not a List" unless directories.instance_of?('List')
 end

 def example2( *params ) 
    lists = params.map{|x| (x.instance_of?(List))?x:nil }.compact 
    fail "No list" unless lists.length > 0
    p lists[0] 
 end

x = List.new
get_files_in(x)
example2( 'this', 'should', 'still' , 1,2,3,4,5,'work' , x )

, Если Вы хотите более assurable тест, можно попробовать RSpec за Поведение управляемая разработка.

5
ответ дан 30 November 2019 в 02:20
поделиться

Короткий ответ: Автоматизированные модульные тесты и хорошие методы именования.

надлежащее именование методов важно. Путем давания имени get_files_in(directory) к методу, Вы также даете подсказку пользователям на том, что метод ожидает получать и что это отдаст в ответ. Например, я не ожидал бы Potato объект, выходящий get_files_in() - он просто не имеет смысла. Только имеет смысл получать список имен файлов или более соответственно, список экземпляров Файла из того метода. Что касается конкретного типа списка, в зависимости от того, что Вы хотели сделать, фактический тип возвращенного Списка не действительно важен. То, что важно, - то, что можно так или иначе перечислить объекты в том списке.

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

3
ответ дан 30 November 2019 в 02:20
поделиться

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

Ваше беспокойство кажется связанным с тем, что любой динамический язык является опасным инструментом, который не может осуществить контракты ввода/вывода API. Факт, в то время как chosing помехи могут казаться более безопасными, лучшая вещь, которую можно сделать в обоих мирах, состоит в том, чтобы сохранить хороший набор тестов, которые проверяют не только тип возвращенных данных (который является единственной вещью, которую компилятор Java может проверить и осуществить), но также и это - правильность и внутренние работы (Черный квадрат / тестирование методом "белого ящика").

Как примечание стороны, я не знаю о Ruby, но в PHP можно использовать теги @phpdoc для вывода подсказок IDE (Eclipse PDT) о типах данных, возвращенных определенным методом.

1
ответ дан 30 November 2019 в 02:20
поделиться
Другие вопросы по тегам:

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