Перейти к содержанию

Участник:Rubynovich

Материал из Викиучебника — открытых книг для открытого мира

Rubynovich. Это прозвище дали первые студенты своему преподавателю по предмету «Программирование на языках высокого уровня». Для демонстрации высокоуровневых алгоритмов он использовал язык Ruby, что и послужило предпосылкой для появления такого прозвища.

Rubynovich преподает предмет «Программирование на языках высокого уровня» в МЭТТ с 2003 года. За это время он сумел сформировать собственную программу обучения и свое уникальное видение сути предмета.

Высокоуровневое программирование

[править]

Вот некоторые принципы программирования, которых должен придерживаться высокоуровневый программист:

  • отсутствие переменных (чем меньше переменных, тем меньше ошибок);
  • отсутствие циклов (все циклы должны быть заменены на итераторы);
  • отстутствие условных конструкций if, case и т.д. (если они есть, то вы делаете, что-то не так);
  • должны выполняться правила рефакторинга (код должен «хорошо пахнуть»).

Отсутствие переменных

[править]

Если переменные отсутствуют, то что-то же использовать вместо них? Параметры методов/замыканий и константы. Это значит, что строки вида:

a = 0
a += 5

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

a = 5

Это выражение является более правильным с точки зрения высокоуровневого программирования. Давайте рассмотрим немного более сложный пример неправильного кода:

sum = 0
(1..5).each{ |i| sum += i }
p sum

Как мы видим, внутри блока присутствует второе присваивание, что противоречит нашему принципу. Как от него избавиться? Использовать не .each, а специализированный метод .inject для суммирования/умножения/конкатенации:

 p (1..5).inject( 0 ){ |sum,i| sum + i }

Как мы видим, нам не только удалось избавиться от двух присваиваний, но и превратить переменную в параметр. Кстати, решение задачи получилось «в одну строчку».

Отсутствие циклов

[править]

Чем же так плохи циклы? Тем, что «зацикливаются» и заранее нельзя указать количество итераций, которые они выполнят. Эта неопределенность погубила не одно поколение программистов. Поэтому и была придумана концепция итераторов, т. е. циклических конструкций, количество итераций которых заранее известно. Пример цикла:

a = [1,2,3,4,5,6]
i = 0
while i < a.size do
  puts a[i]
  i += 1
end

Как вы можете видеть, здесь не только использование цикла, но и двойного присваивания. С итератором эта программа будет выглядеть так:

[1,2,3,4,5,6].each{ |elem|
  puts elem
}

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

Отсутствие условных конструкций if, case и т.д.

[править]

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

a, b = 5, 6
if a > b
   puts "a > b"
elsif a == b
   puts "a == b"
else puts "a < b"
end

Казалось бы, все очевидно и по другому быть не может. Rubynovich же предлагает заменить результаты массивом вариантов:

["a == b","a > b","a < b"]

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

a, b = 5, 6
puts ["a == b","a > b","a < b"][ a <=> b ]

Естественно, что пример был выбран искусственно, но сама по себе идея достаточно интересна. Кстати, как написать программу, которая выводит "a == b" или "a != b"?

Должны выполняться правила рефакторинга

[править]

Мартин Фаулер написал замечательную книгу "Рефакторинг". Что же такое этот рефакторинг? Рефакторинг — это процесс переработки программного кода с сохранением его функциональности. Делается это для того, чтобы стабильный код становился еще и изящным (лишенным конструктивных изъянов). Это необходимо для улучшения способности кода к безболезненной модификации. Многие программисты используют рефакторинг и как средство повышения профессионализма, и как повод получше разобраться в своем или чужом коде.

Вместо заключения

[править]

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