Участник:Rubynovich: различия между версиями

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


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

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

Версия от 19:16, 24 мая 2006

Жил был программист. И писал он на великом и могучем языке Pascal. И считал он, что программа в несколько тысяч строк -- это показатель высокого мастерства программиста. Но шло время. Поступил он в институт. Первые курсовые работы пришлось ему сдавать на Java. Все бы хорошо, но выполнять курсовые приходилось в стенах университета, т.к. программы написанные дома не работали в университете. Но объектно-ориентированная концепция ему понравилась. И решил наш программист поупражняться. Начал переписывать свои программы на Pascal под C++ (язык Java ему не понравился). И был удивлен тем фактом, что ему удалось в несколько раз сократить размер исходного кода. Но язык С++ тоже не вызывал у него уважения... он искал.

Тем временем в университете преподавали Visual Basic, Haskell, Prolog. Самостоятельно он начал изучать PHP. Но тут один из учителей предложил ему посмотреть Ruby. И тут наш программист решил попробовать... написал один курсовой, второй, третий. Причем эти курсовые занимали все меньше и меньше строчек кода. По мере того, как он постигал тонкости языка, он все сильней понимал, что писать на других языках он уже не может. Ему не хватало их гибкости, выразительности, мощности. Но он не сдавался... Он изучил Perl (был поражен регулярными выражениями), Python (понравилась идея отступов), но все равно не получал того самого удовлетворения от написания программ, которое должно охватывать программиста. И понял тут он, что поиск его завершен... и не найти ему ничего более совершенного.


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

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

a = [1,2,3,4,5,6]
a.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 уже не кажется таким уж сумасшедшим.