CoffeeScript: касивый способ писать JavaScript код

мая 22, 2011  |  Published in ClientSide, JavaScript  |  4 Comments

Я программировал на JavaScript много лет и за это время наплодио много кода. Даже сейчас с моим большим опытом я продолжаю бороться за красоту JavaScript. В этом посте я хочу исследовать почему писать крассивый JavaScript код сложно и как эти сложности исправить с помощью CoffeeScript — маленького языка компилируемого в JavaScript.

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

- Красивый код это минимальный код, который решает возложеную на него задачу,
- Красивый код это читабельный и легко понимаемый код,
- Красивый код это не тод код в который нечего добавить, но тот в котором нечего убрать (как и отличный дизайн),
- Маленькая длина кода — это лишь побочный эфект, а не цель или то, по чем можно производить оценку.

Таким образом, красивый код это совмещение лаконичности, функциональности и читабельности кода, как по моему.


Пример красивого JavaScript кода
Давайте рассмотрим пример с функцией возвращающей последовательность Фиббоначи так как это функция очень известная многим программистам.

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

function f(n) {
  var s= 0;
  if(n == 0) return(s);
  if(n == 1) {
    s += 1;
    return(s);
  }
  else {
    return(f(n - 1) + f(n - 2));
  }
}

А вот вторая реализация, которую я нахожу более элегантной и красивой, особенно если вы знакомы с однострочной реализацией if-else:

function fib(n) {
  return n<2 ? n : fib(n-1) + fib(n-2)
}

Я нахожу эту реализацию также красивой поскольку число строк не имеет значения:

function fib(n) {
  if (n < 2)
    return n
  return fib(n-2) + fib(n-1)
  }

Проблема с JavaScript

Я считаю одной из главных проблем JavaScript то, что он является винигретом из различных парадигм программирования:

- JavaScript — функциональный язык,
- JavaScript — объектно-ориентированный язык основанный на прототипах,
- JavaScript очень динамичный язык, и он больше похож на Lisp, чем на Си или Java, однако имеет синтаксис подобный Си и Java,
- Даже название языка JavaScript смущает, поскольку он не имеет отношения к Java (как, например VBScript к VisualBasic).

В конце-концов мы имеем язык c личностным кризисом и программистов, которые нишут на нем в неприсущем для JavaScript стиле, который они переняли из других языков программирования. И внедрение в JavaScript других стилей/парадигм программирования не ест хорошо ибо JavaScript — это не Java, не Python и не Scheme. JavaScript — это JavaScript, и он имеют свою собственную философию, свои сильные и слабые стороны, как и все остальный языки программирования.

JavaScript был разработан в большой спешке, что отразилось во множестве плохих решений, как, например: динамический this или синтаксис наследования. Этих проблем большое количество, поэтому исправление всех их — очень сложный и длительный процесс поскольку существует проблема обратной совместимости. Ниже приведена отличная цитата от создателя JavaScript, которая описывает среду в которой родился JavaScript:

» JavaScript создавался как маленький, тупой последователь Java. Кроме того, у меня было десять дней на то, чтобы созать JavaScript, в противном случае место JavaScript заняло бы что-то более ужасное. »

- Брендан Эйч.

CoffeeScript: Новый способ писать отличный JavaScript код

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

Я наткнулся на CoffeeScript некоторое время назад, когда я пытался написать несколько скриптов чтобы поиграть с этим новым языком. Я реально полюбил программировать на CofeeScript, но язык в то время был весьма незрел. Сейчас, двайте перенесемся на прошлую неделю, когда я имел серьезные проблемы с JavaScript кодом, который я писал для проекта Wedoist. Я взглянул на него и в мозгу сразу же появилась аналогия со мусорной свалкой. Должен существовать способ сделать это лучше! После этого открытия я решил взглянуть на код написанный для Wedoist на Python и он представился мне очень чистым, минималистичным и читабельным. Затем я открыл много секретов того, как писать на JavaScript лучше. Мой мыслительный процесс имел примерно такую последовательность:

- Наверное, я потерял некоторые идиомы JavaScript?
- Навеное следует взглянуть на JavaScript код других OpenSource проектов, возможно, там я найду лучший способ писать на JavaScript?
- Возможно я должен использовать backbone.js?
- Возможно мне стоит снова перечитать книгу JavaScript: The Good Parts?

Передо мною возникла преграда. Как способ иследовать опции я взял небольшой фрегмен JavaScript кода из Wedoist для исправления. Я пытался провести рефакторинг и переписать код, я могу бы гордиться своей работой… Но не имеет значения как сильно я старался, я все равно не смог сделать мой код на JavaScript таким же великолепным как мой код на Python. Я был очень разочарован, в наибольшей мере благодаря тому, что я так много программирую на JavaScript, но мой код по-прежнему остается плохим.

Вот тот кадр, где в действо вступает CoffeeScript: Я обрел идею переписать мой JavaScript код на CoffeeScript потому, что наверное, это не моя вина, а вина самого JavaScript. Таким образом после небольшого хакинга я переписал небольшую часть кода на CoffeeScript и был восхищен результатом! Та часть кода, которую я переписал на CoffeeScript выглядела так читабельно, так минималистично и непревзойденно красиво. Таким образом я нашел способ писать красивый код на «JavaScript» использую другой, компилируемый в JavaScript, язык.

CoffeeScript не осуждает ваш JavaScript код

Одно из тех качеств CoffeeScript которые я люблю является то, что CoffeeScript компилируется в JavaScript. Это означает, что я могу повторно использовать весь мой имеющийся код на JavaScript вместо того, чтобы переписывать его на CoffeeScript. Это отличное качество, особенно учитывая то, что в Wedoist очень много кода на JavaScript, и трата месяцов работы на его переписывание не рационально.

CoffeeScript также подражает JavaScript. Он ведет себя как очень правильная, наверное, совершенная версия JavaScript, где все уродства удалены или исправлены. Он также отдаляет JavaScript от синтаксиса Си/Java и приближает его к синтаксису Ruby и Python (что очень хорошо, потому, что JavaScript идеологически более близок к Ruby и Python, чем к Си и Java).

На данный момент я имею структуру где я пишу новый код на CoffeeScript и я также планирую переписать старый код c JavaScript на CoffeeScript.

Как CoffeeScript компилируется в JavaScript

Чтобы разъяснить компиляцию давайте рассмотрим пример:

Код на CoffeeScript:

square = (x) -> x * x
cube   = (x) -> square(x) * x

«Скомпилированный» JavaScript код:

var cube, square;
square = function(x) {
  return x * x;
};
cube = function(x) {
  return square(x) * x;
};

Как вы видите, пример выше демонстрирующий разницу между CoffeeScript и JavaScript очень простой и понятный. На сайте CoffeeScript вы можете найти значительно больше примеров того, как CoffeeScript перевоплощается в JavaScript.

CoffeeScript: Пример переписи

Чтобы дать вам почувствовать новый язык я предоставлю вам простой пример кода на JavaScript который я перепишу на CoffeeScript:

get: function(offset, callback, limit) {
  var self = this;

  var data = {
    project_id: Projects.getCurrent().id,
    limit: limit || this.default_limit
  }

  if(offset)
    data.offset = Calendar.jsonFormat(offset, true);

  this.ajax.getArchived(data, function(data) {
    if(!offset)
    self.setCache(data);
    callback(data);
  });
},

Код на CoffeeScript:

get: (offset, callback, limit) =>
  data =
    project_id: Projects.getCurrent().id
  limit: limit or @default_limit

  if offset
    data.offset = Calendar.jsonFormat(offset, true)

  @ajax.getArchived(data, (data) =>
  if !offset
    @setCache(data)
  callback(data)
)

Как вы видите оба фрагмента кода выглядят очень похоже, но вариант на CoffeeScript выглядит более свежо потому, что избыточный синтаксис удален и код содержит только самое важное.

Теперь давайте взглянете на некоторые важные особенности CoffeeScript.

Основные моменты CoffeeScript: Простое наследование

JavaScript обладает гомадной системой наследования, но с наводящим на душу леденящий страх синтаксисом. CoffeeScript исправляет это с элегантной системой наследования которая подражает классам и наследованию, как оно работает в других языках программирования:

class Animal
  constructor: (@name) ->

  move: (meters) ->
    alert @name + " moved " + meters + "m."

class Snake extends Animal
  move: ->
    alert "Slithering..."
    super 5

Основные моменты CoffeeScript: Прокачанные массивы

Мне нравится List Comprehensions в Python и CoffeeScript перенимает это!

list = [1, 2, 3, 4, 5]
cubes = (math.cube num for num in list)

С «нарезкой» массива:

copy = list[0...list.length]

Генераторы массивов:

countdown = (num for num in [10..1])

Основные моменты CoffeeScript: Прокачанные строки

CoffeeScript одалживает у Ruby синтаксис для интерполяции строк, который делает создание строк очень простым моментом:

author = «Wittgenstein»
quote  = «A picture is a fact. — #{ author }»

Многострочные строки также доступны:

mobyDick = «Call me Ishmael. Some years ago -
never mind how long precisely — having little
or no money in my purse, and nothing particular…»

Основные моменты CoffeeScript: Стабильный указатель this

Указатель this в JavaScript не совершенен поскольку является динамическим. CoffeeScript исправляет это если вы используете ключевое слово => (это будет автоматически направлять this или @ для вас):

Account = (customer, cart) ->
  @customer = customer
  @cart = cart

  $('.shopping_cart').bind('click', (event) =>
    @customer.purchase @cart
  )

Исследуем CoffeeScript!

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

Я продолжаю осваивать CoffeeScript и он стал одним из моих любимых языков программирования. Большого уважения заслуживает Джереми Ашкенас, который создал CoffeeScript.

Я всегда рад покопаться в чем-то новеньком, и я надеюсь вы также заинтересуетесь CoffeeScript и попробуете его в работе.

Оригинал поста на английском:

Лучшая благодарность автору блога — Ваши комментарии!

Responses

  1. says:

    мая 22, 2011 at 08:28 (#)

    Воистину CoffeeScript великолепен. Полгода на нем очень плотно пишу клиентский и серверный код, и уже не могу себе представить как можно жить с plain js.

  2. admin says:

    мая 22, 2011 at 09:15 (#)

    Егор, спасибо за отзыв. Я вот только начинаю с ним знакомиться, думаю будет несколько постов о CoffeeScript, например о том, как с ним работать в Rails 3.1.

  3. argent-smith says:

    мая 29, 2011 at 21:08 (#)

    Молодец, Haskell, хорошо замаскировался! ;-)

  4. slavik says:

    февраля 18, 2012 at 19:37 (#)

Leave a Response

Для подсветки кода используйте BB - коды: [language]...[/language], где language может быть: ruby, javascript, css, html.