...

суббота, 13 июня 2015 г.

[Перевод] 9 анти-паттернов, о которых должен знать каждый программист

В программировании самокритика – это умение распознать контрпродуктивные решения в дизайне, коде, процессах и поведении. Знание о вредных шаблонах решений полезно для программиста. В этой статье я опишу анти-паттерны, которые я встречал на своём личном опыте время от времени.

Некоторые из них напрямую или косвенно связаны с когнитивными искажениями человеческого сознания – в этих случаях я даю ссылки на соответствующие вики-статьи. Также интересен список известных когнитивных искажений.

1 Преждевременная оптимизация


В 97% случаев надо забыть об эффективности малых частей программы: преждевременная оптимизация – корень всех зол. Но в 3% случаев об оптимизации забывать не нужно.
Дональд Кнут


Хотя, «никогда» чаще лучше, чем «прямо сейчас»
Тим Питерс, Зен языка Python

Что это

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

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

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

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

Сложность в том, чтобы знать, когда оптимизация будет преждевременной. Важно заранее оставлять место для роста. Нужно выбирать решения и платформы, которые позволят легко оптимизировать и расти. Также иногда можно использовать преждевременную оптимизацию в качестве оправдания за плохой код. Например, использование алгоритма O(n2) просто потому, что алгоритм O(n) сложнее.
Слишком длинно, не читал

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

2 Байкшеддинг


(прим.перев. – англосаксы любят придумывать глаголы. Этот термин также называется «Закон тривиальности Паркинсона», и появился после того, как этот Паркинсон обратил внимание, как люди любят тратить время на совещаниях на всякую ерунду, вместо того, чтобы обсуждать насущные проблемы. Конкретно, проектировщики атомной электростанции очень долго спорили, какой материал должен пойти на навес для велосипедов – bike-shed).

Периодически мы прерывали разговор, чтобы обсудить типографику и цвет страницы. После каждого обсуждения мы голосовали. Я думал, что эффективнее всего будет проголосовать за тот же цвет, который мы выбрали на предыдущей встрече, но я всегда оказывался в меньшинстве. Наконец, мы выбрали красный (а в итоге получился синий).
Ричард Фейнман, «Почему вас заботит, что о вас думают другие?»

image

Что это

Склонность тратить время на обсуждение тривиальных и субъективных вещей.
Почему это плохо

Трата времени. Подробное письмо от Пола-Хенинга Кэмпа по этому поводу.
Как избежать

Напоминайте другим членам команды об этой склонности, и о том, что в этих случаях главное – быстрее принять решение (бросить монетку, проголосовать, и т.п.). Если речь идёт о вещах вроде пользовательского интерфейса, обратитесь к A/B тестированию, вместо того, чтобы обсуждать это в команде.
Примеры и признаки

Часы или дни проводятся в обсуждениях цвета фона или расположения кнопки в интерфейсе, или использования табуляции вместо пробелов в коде.
В чём сложность

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

Не тратьте много времени на простейшие решения.

3 Аналитический паралич


Желание предсказать что-либо, нежелание действовать, когда это было бы просто и эффективно, недостаток ясности мысли… Всё это свойства, заставляющие бесконечно повторять историю.
Уинстон Черчилль, Дебаты в парламенте


Сейчас – лучше, чем никогда
Тим Питерс, Зен языка Python

Что это

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

Переизбыток анализа может замедлить или остановить прогресс. В тяжёлых случаях, результаты анализа становятся не нужны к тому моменту, когда они готовы, или даже проект вообще не покидает фазу анализа. Часто кажется, что чем больше у вас информации, тем больше это поможет принятию тяжёлого решения. См. информативное искажение и иллюзию допустимости.
Как избежать

Наблюдайте за итерациями и улучшениями. Каждая итерация даёт обратную связь и информацию, которую можно использовать для более осмысленного анализа. Без этой информации анализ будет лишь спекулятивным.
Примеры и признаки

Месяцы и годы, проведённые в анализе требований проекта, интерфейса или структуры БД.
В чём сложность

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

Вместо чрезмерного анализа и спекуляций используйте пошаговое развитие.

4 Класс Бога


Простое лучше сложного
Тим Питерс, Зен языка Python


Что это

Классы, контролирующие множество других классов, имеющие много зависимостей и много ответственности.
Почему плохо

Классы Бога разрастаются до тех пор, пока не превращаются в кошмар поддержки. Они нарушают принцип одной ответственности, с ними тяжело проводить юнит-тесты, отлаживать и документировать.
Как избежать

Разбивайте ответственность по мелким классам, с единственной ответственностью, которая чётко определена, юнит-тестируется и задокументирована.
Примеры и признаки

Ищите классы с именами «manager», «controller», «driver», «system» или «engine». Подозрительно смотрите на классы, импортирующие или зависящие от других, контролирующие слишком много других классов или имеющие много методов, занимающихся чем-то, не связанным с основной деятельностью.
В чем сложность

Проекты, запросы и количество программистов растет, и маленькие специализированные классы медленно превращаются в классы Бога. Рефакторинг таких классов может занять впоследствии много времени.
Слишком длинно, не читал

Избегайте больших классов со слишком большими ответственностями и зависимостями

5 Страх перед добавлением классов


Редкое лучше, чем густое
Тим Питерс, Зен языка Python


Что это

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

Добавление классов уменьшает сложность. Распутать несколько мелких клубков пряжи проще, чем один крупный. Несколько простых в поддержке и документировании классов предпочтительнее одного большого и сложного класса со множеством зависимостей (класс Бога).

image

Как избежать

Замечайте те места, в которых добавление классов может упростить дизайн и разрубайте ненужные связи между частями кода
Примеры и признаки
class Shape:
    def __init__(self, shape_type, *args):
        self.shape_type = shape_type
        self.args = args

    def draw(self):
        if self.shape_type == "круг":
            center = self.args[0]
            radius = self.args[1]
            # Draw a circle...
        elif self.shape_type == "квадрат":
            pos = self.args[0]
            width = self.args[1]
            height = self.args[2]
            # Draw rectangle...

А теперь сравните со следующим:

class Shape:
    def draw(self):
        raise NotImplemented("Подклассам Shape необходимо определить метод 'draw'.")

class Circle(Shape):
    def __init__(self, center, radius):
        self.center = center
        self.radius = radius

    def draw(self):
        # Нарисовать круг...

class Rectangle(Shape):
    def __init__(self, pos, width, height):
        self.pos = pos
        self.width = width
        self.height = height

    def draw(self):
        # Нарисовать квадрат...

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

В чем сложность

Добавление классов – не панацея. Упрощение дизайна разбиванием больших классов требует глубокого анализа областей ответственности и требований.
Слишком длинно, не читал

Большое число классов – не признак плохого дизайна

6 Эффект внутренней платформы


Те, кто не понимает Unix, обречены на переизобретение его плохих копий
Генри Спенсер


Любая достаточно сложная программа на Си или Фортране содержит заново написанную, неспецифицированную, глючную и медленную реализацию половины языка Common Lisp.
Десятое правило Гринспена


Что это

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

Задачи уровня платформы – планировка задач, дисковый буфер и т.д. непросто реализовать правильно. В плохих решениях часто встречаются узкие места и ошибки, особенно с ростом системы. Воссоздание альтернативных конструкций для того, что уже возможно сделать при помощи языка, приводит к усложнению кода и к подъёму кривой обучения для новичков. Также это ограничивает пользу от рефакторинга и инструментов для анализа кода.
Как избежать

Используйте имеющиеся возможности и свойства платформы или операционки. Не создавайте языковые конструкции, конкурирующие с существующими (особенно, если вы не привыкли к новому языку и скучаете по старому).
Примеры и признаки

Использование базы данных как очереди задач. Переизобретение дискового буфера вместо использования возможностей операционки. Написание менеджера задач для веб-сервера на PHP. Определение макроса в С для поддержки конструкций, напоминающих Python.
В чём сложность

В очень редких случаях всё-таки может потребоваться воссоздание имеющихся у платформы возможностей (JVM, Firefox, Chrome и т.д.).
Слишком длинно, не читал

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

7 Магические числа и строчки


Явный лучше, чем неявный
Тим Питерс, Зен языка Python


Что это

Использование безымянных чисел или строковых констант вместо именованных констант в коде.
Почему это плохо

Без поясняющего имени семантика числа или строки скрыта от нас. Это усложняет понимание кода, а необходимость поменять константу может привести к ошибкам. Рассмотрим следующий код:
def create_main_window():
    window = Window(600, 600)
    # и т.д....

Что это за числа? Допустим, первое – ширина, второе – высота. Если в дальнейшем придётся поменять ширину на 800, то поиском и заменой можно будет зацепить случайно и такую же высоту.

Использование неименованных строковых констант не так подвержено ошибкам, но затрудняет возможную локализацию, и также может привести к ошибкам из-за использования одинаковых строк в разных смыслах. Слово «точка» может обозначать пиксель, знак препинания или окончание рассуждений – в результате, поиск и замена слова приведут к ошибкам. Этого можно избежать, заменяя строки механизмом получения строк извне.

Как избежать

Используйте именованные константы, средства для получения ресурсов извне
Примеры и признаки

Даны выше. Такой анти-паттерн легко распознать.
В чем сложность

Иногда сложно сказать, будет ли используемое число магическим. 0 в языках, в которых индексирование начинается с нуля. 100 для подсчёта процентов, 2 для проверки чётности и т.д.
Слишком длинно, не читал

Избегайте использования чисел или строковых констант без имён и пояснений.

8 Управление через количество


Измерение прогресса программиста по количеству строк кода – то же самое, что измерение прогресса строительства самолёта по весу.
Билл Гейтс


Что это

Принятие решений на основании одних лишь чисел.
Почему это плохо

Числа – это хорошо. Первые два анти-паттерна, преждевременную оптимизацию и байкшеддинг, надо избегать при помощи A/B-тестирования и получения неких количественных результатов. Но основываться только на числах опасно. К примеру, числе переживают те модели, в которых они имели смысл, или же модели устаревают и перестают корректно отражать реальность. Это приводит к плохим решениям, в особенности, когда они принимаются автоматически (искажение автоматизации).

image

Ещё одна проблема в использовании чисел для принятия решений (а не для простого информирования) – процессами измерения можно манипулировать для достижения желаемой цели (эффект наблюдателя и ожиданий). В сериале The Wire красочно показано, как полицейское управление и система образования перешли от осмысленных целей к игре с числами. Следующий график иллюстрирует этот вопрос. На нём изображено распределение оценок по тесту, в котором минимальная оценка для прохождения теста – 30.

image

Как избежать

Используйте измерение и числа мудро, не слепо.
Примеры и признаки

Использование количества строк, количества коммитов и т.д. для оценки эффективности программистов. Измерение эффективности сотрудника по количеству часов, проведённых в офисе.
В чём сложность

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

Используйте числа для информирования, а не как основу для принятия решений

9 Бесполезные (полтергейстные) классы


По-видимому, совершенства достигают не тогда, когда нечего добавить, а тогда, когда нечего отнять.
Антуан де Сент-Экзюпери


Что это

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

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

Не пишите бесполезные классы и избавляйтесь от них при возможности.
Примеры и признаки

Несколько лет назад при работе над дипломом я обучал первокурсников программированию на Java. Для одной из лабораторных работ мне дали материал по теме стэка и использования связанных списков. И мне дали «решение». Вот такое это было решение, почти дословно:
import java.util.EmptyStackException;
import java.util.LinkedList;

public class LabStack<T> {
    private LinkedList<T> list;

    public LabStack() {
        list = new LinkedList<T>();
    }

    public boolean empty() {
        return list.isEmpty();
    }

    public T peek() throws EmptyStackException {
        if (list.isEmpty()) {
            throw new EmptyStackException();
        }
        return list.peek();
    }

    public T pop() throws EmptyStackException {
        if (list.isEmpty()) {
            throw new EmptyStackException();
        }
        return list.pop();
    }

    public void push(T element) {
        list.push(element);
    }

    public int size() {
        return list.size();
    }

    public void makeEmpty() {
        list.clear();
    }

    public String toString() {
        return list.toString();
    }
}

Представьте моё замешательство, когда я его читал, пытался понять, зачем нужен класс LabStack и что студенты поймут из такого бесполезного упражнения. Если это ещё непонятно, этот класс не делает вообще ничего. Он просто передаёт вызовы в объект LinkedList. Также он меняет имена нескольких методов (makeEmpty вместо clear), что ещё больше запутывает. Логика проверки ошибок не нужна, поскольку методы в LinkedList делают то же самое (просто через другое исключение, NoSuchElementException). По сию пору не могу понять, что было в голове у авторов этого материала.

В чём сложность

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

Избегайте классов без реальной ответственности.

This entry passed through the Full-Text RSS service - if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.

Знакомство с OsmocomBB: 0x03 Software

И снова здравствуйте! Пришло время рассказать о сборке програмного обеспечения для работы с OsmocomBB. На данном этапе у начинающих исследователей могут возникнуть трудности, поэтому постараюсь разложить все по полочкам. В этой части я расскажу о структуре проекта, принципах взаимодействия телефона и компьютера, а также подробно опишу процесс компиляции. Рекомендую вооружиться каким-нибудь дистрибутивом Linux, потому-что серверная часть проекта разрабатывалась именно под данное семейство операционных систем. Также советую воздержаться от использования виртуальных машин, так как возможны проблемы с запуском приложений на телефоне из-за временных задержек.

Навигация


Основы основ


Стек протоколов GSM, регулирующих процессы взаимодействия мобильных телефонов и базовых станций, можно разделить на 3 логических уровня:
  • Layer 1: Физический уровень. Местные протоколы описывают принципы взаимодействия устройств в радиоэфире. Для обеспечения одновременного взаимодействия сети и нескольких мобильных устройств в GSM-сетях применяются две технологии множественного доступа: FDMA (Frequency-Division Multiple Access) и TDMA (Time-Division Multiple Access). FDMA подразумевает разбиение доступного диапазона частот на каналы (ARFCN), каждый из которых позволяет передавать данные от абонентов к сети (uplink) и от сети к абонентам (downlink). TDMA подразумевает мультиплексирование физического канала с разделением по времени, то есть, каждому устройству предоставляется возможность приема и передачи данных в определенные моменты времени. Согласно TDMA физический канал (ARFCN) разбивается на несколько логических каналов, например, PCH (Paging channel), на котором базовая станция уведомляет телефон о входящем вызове, или BCCH (Broadcast Control channel), используемый для идентификации базовой станции мобильными телефонами. И так далее...
  • Layer 2: Канальный уровень, основными задачами которого являются: установление, поддержание и разрыв соединений между устройствами сети; контроль потоков данных, обнаружение ошибок, а также транзит данных третьего уровня. На данном уровне работают протоколы LAPD и LAPDm, обеспечиваются множественные соединения, а также функциональность логических каналов BCCH, PCH, AGCH и DCCH.
  • Layer 3: Сетевой уровень, подразделяющийся на три подуровня:
    • Radio Resource (RR) — подуровень, отвечающий за создание и освобождение логических каналов между устройствами;
    • Mobility Management (MM) — подуровень, выполняющий аутентификацию пользователей, а также отслеживающий перемещения абонентов между зонами покрытия (сотами) различных базовых станций;
    • Call Control (CC) — подуровень, отвечающий за телефонные звонки.

Подробное описание данной темы можно найти в Википедии. Больше всего нас интересует расстановка ролей между телефоном и компьютером:

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

Обзор OsmocomBB


Начнем с того, что OsmocomBB разрабатывается на базе системы контроля версий Git, и его исходные коды доступны на официальном сайте git.osmocom.org. Большинство возможностей проекта, таких как RSSI, интерфейс для приема/совершения голосовых звонков и обмена SMS-сообщениями, доступны в основной ветке проекта (master). Однако наиболее интересные возможности доступны в виде ответвлений репозитория — веток (branch):
  • luca/catcher
    Возможно, Вы когда-нибудь слышали об IMSI-Catcher. Чаще всего под IMSI-Catcher подразумевают устройство, маскирующееся под настоящую базовую станцию с целью сбора IMSI (международный идентификатор мобильного абонента) ближайших абонентов (что, например, позволяет отслеживать их местоположение). Правильнее считать, что IMSI-Catching — это только одна из возможностей поддельных базовых станций (FakeBTS), принцип работы которых довольно прост. IMSI и IMEI коды абонента передаются базовой станции лишь в момент его подключения, затем абоненту присваивается временный идентификатор TMSI, на основе которого происходит их дальнейшее взаимодействие. TMSI в отличии от IMSI не является постоянным и меняется при подключении к другим базовым станциям. Для деанонимизации абонента злоумышленник запускает свою базовую станцию (например, на базе USRP), мощность сигнала которой превышает мощность настоящих базовых станций. Благодаря этому, телефон абонента подключается к станции с более мощным сигналом, а затем передает свои IMSI и IMEI коды. Иногда FakeBTS могут выступать в роли посредников между абонентом и настоящей базовой станцией, позволяя злоумышленнику выполнять различные MiTM-атаки, а также тратить деньги абонента. Как бы пугающе это не звучало, присутствие таких «чудес» в эфире можно обнаружить, например, с помощью проектов: FakeBTS или Android IMSI-Catcher Detector. Автор данной ветки также интегрировал в проект возможность обнаружения подобной активности. Подробнее об этом можно узнать тут.
  • jolly/emi
    Здесь интегрировано приложение EMI, предназначенное для проведения стресс-тестов беспроводного оборудования. Подробнее на сайте проекта wiki/emi-firmware. Так же не стоит забывать о том, что вещание на частотах GSM во многих странах, включая Российскую Федерацию, требует наличия лицензии. Если же с лицензией все сложно, можно воспользоваться клеткой Фарадея.
  • sylvain/burst_ind
    Основной упор в данной ветке делается на сниффинг GSM-трафика, о чем более подробно я расскажу в одной из следующих статей.
  • jolly/menu
    Данная ветка позволит Вам записывать приложения во Flash-память телефона. Зачем? Например, если потребуется автономность при использовании телефона в каких-либо переносимых проектах. Имеется возможность прошить загрузочное меню, которое с помощью графического интерфейса будет предоставлять выбор приложения для загрузки. Процесс прошивки описан на странице wiki/flashing_new.
  • luca/libosmosim
    Данная ветка позволит Вам использовать OsmocomBB-совместимый телефон для взаимодействия с SIM-картой. После сборки проекта в папке src/host/layer23/src/libosmosim/.libs будет доступна библиотека libosmosim.so, на базе которой работает проект SIMTester. С его помощью можно проверять криптостойкость SIM-карт, а также безопасность установленных на них приложений.
  • sylvain/testing
    Здесь можно найти приложение TRX, которое превращает OsmocomBB-совместимый телефон в небольшую базовую станцию. Подробнее об этом я расскажу позже, а пока можно почитать небольшое HOWTO wiki/Software/Transceiver и посмотреть презентацию Further hacks on the Calypso platform or how to turn a phone into a BTS.

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

Сборка проекта


Давайте определимся с местоположением файлов и папок. Исходя из своего опыта, рекомендую создать папку /opt/osmocom — в ней мы будем хранить библиотеки и кросс-компилятор. А для сборки проекта использовать, например, домашнюю папку, или другое место, для работы в котором не требуются права администратора. В результате компиляции проекта Вы получите приложения (прошивки), выполняемые на телефоне, и программы для взаимодействия с ними со стороны компьютера (сервера). Процесс сборки описан на примере Ubuntu 14.04, поэтому на других дистрибутивах синтаксис команд может немного отличаться. Итак, что нам нужно?
  • libosmocore — основная библиотека проекта, подробнее о которой можно почитать в разделе wiki/libosmocore. Не смотря на то, что часть ее исходного кода поставляется при клонировании репозитория OsmocomBB, ее необходимо собирать отдельно;
  • Кросс-компилятор — OsmocomBB-совместимые телефоны в основном построены на базе платформы ARM, поэтому для сборки прошивок понадобится кросс-компилятор (toolchain). Разработчики рекомендуют использовать именно ту версию кросс-компилятора, которая указана на сайте, так как при использовании сторонних прошивки могут работать нестабильно. Сборка кросс-компилятора описана в разделе wiki/GnuArmToolchain, однако при компиляции на современных системах часто возникает ошибка, поэтому я создал форк с исправленным инсталлятором.

Для компиляции исходных кодов нам понадобятся autoconf, automake, libtool, pkg-config, make and GCC. Заодно создадим директорию /opt/osmocom:
# Все действия выполняются от имени суперпользователя, чтобы постоянно не писать sudo.
$ sudo su
# Устанавливаем зависимости.
$ apt get update
$ apt-get install libtool shtool automake autoconf git-core pkg-config make gcc
# Создаем папку для библиотек и кросс-компилятора.
$ mkdir /opt/osmocom


В процессе сборки исходных кодов часто возникают ошибки. Чаще всего не хватает каких-либо библиотек. На сайте baseband-devel.722152.n3.nabble.com можно найти способы решения большинства из них — пользуйтесь поиском. Если ошибка возникает в процессе конфигурации (команды autoreconf или ./configure), попробуйте устранить ее и выполнить повторную конфигурацию.

Начнем с libosmocore:

$ cd /opt/osmocom
$ git clone git://git.osmocom.org/libosmocore.git
$ cd libosmocore
$ autoreconf -i
# Библиотека pcsclite требуется для сборки libosmocore.
$ apt-get install libpcsclite-dev
$ ./configure
$ make
$ make install


Идем дальше. Сборка кросс-компилятора является основным источником ошибок и занимает наибольшую часть времени. В большинстве случаев возникает ошибка "@itemx must follow @item". Дело в том, что для сборки требуется более старая версия TexInfo. Можно выполнить downgrade вручную, а можно воспользоваться моей исправленной версией инсталлятора:
$ cd /opt/osmocom
# Зависимости кросс-компилятора.
$ apt-get install build-essential libgmp3-dev libmpfr-dev libx11-6 libx11-dev flex bison libncurses5 libncurses5-dbg libncurses5-dev libncursesw5 libncursesw5-dbg libncursesw5-dev zlibc zlib1g-dev libmpfr4 libmpc-dev
# Клонируем скрипты инсталлятора.
$ git clone http://ift.tt/1HDddpt gnu-arm-toolchain
$ cd gnu-arm-toolchain
# Загружаем все необходимое.
$ ./download.sh
# Запускаем процесс компиляции
$ ./build.sh


Если возникнут ошибки, Google всегда придет на помощь. Возможно, потребуются дополнительные библиотеки. Все зависит от Вашего дистрибутива. В любом случае необходимо добиться успешной сборки и сообщения «Build complete!», после чего нужно добавить путь к исполняемым файлам кросс-компилятора в переменную среды PATH.
# Права администратора теперь не нужны.
$ su <ваша учетная запись>
$ cd ~
# Убедитесь, что директория /opt/gnu-arm-toolchain/install/bin/ доступна и содержит 
# исполняемые файлы кросс-компилятора, например, с помощью команды ls.
# Редактируем переменные среды:
$ gedit .bashrc
# Добавляем в самый конец файла строку:
# export PATH=$PATH:/opt/gnu-arm-toolchain/install/bin/
# Не забываем сохраниться.
$ source .bashrc
# Проверим доступность исполняемых файлов:
$ arm-elf-gcc -v
# В результате чего должна появиться информация о компиляторе.
# В случае ошибки проверьте правильность пути к папке bin и его наличие в переменной PATH.


Поздравляю! Теперь Ваша система готова к сборке OsmocomBB. Пришло время собрать ветку master.
# В домашнем каталоге создадим директорию osmocombb:
$ mkdir ~/osmocombb
$ cd ~/osmocombb
# Клонируем репозиторий:
$ git clone git://git.osmocom.org/osmocom-bb.git master
# Собираем:
$ cd master/src
$ make


Если возникает ошибка "no such instruction: `eor %edx,%ecx,%ecx,ror'", значит исполняемые файлы Вашего кросс-компилятора не доступны — проверьте все еще раз. Запомните эту последовательность действий — она используется каждый раз при сборке новой ветки. Для того, чтобы клонировать определенную ветку репозитория, используйте флаг -b, например:
# Пример клонирования ветки sylvain/burst_ind:
$ cd ~/osmocom
$ git clone git://git.osmocom.org/osmocom-bb.git -b sylvain/burst_ind burst_ind


Запускаем Hello, world!


Самый долгожданный момент. Сначала следует уточнить платформу Вашего телефона (на странице wiki/Hardware/Phones), например, для C123, C115 и С118 — это Compal E88. Прошивки для каждой платформы располагаются в одноименных директориях по пути src/target/firmware/board/. Итак, выключаем телефон, подключаем кабель к компьютеру, затем:
# Идем в папку проекта:
$ cd ~/osmocom/master/src/
# Запускаем загрузчик, в моем случае для платформы E88:
$ host/osmocon/osmocon -m c123xor -p /dev/ttyUSB0 target/firmware/board/compal_e88/hello_world.compalram.bin
# На телефоне однократно нажимаем кнопку выключения.
# Начнется процесс загрузки, после которого прошивка запустится на телефоне.


Вывод:
Received PROMPT1 from phone, responding with CMD
read_file(target/firmware/board/compal_e88/hello_world.compalram.bin): file_size=25180, hdr_len=4, dnload_len=25187
got 1 bytes from modem, data looks like: 1b.
got 1 bytes from modem, data looks like: f6.
got 1 bytes from modem, data looks like: 02.
got 1 bytes from modem, data looks like: 00.
got 1 bytes from modem, data looks like: 41 A
got 1 bytes from modem, data looks like: 02.
got 1 bytes from modem, data looks like: 43 C
Received PROMPT2 from phone, starting download
handle_write(): 4096 bytes (4096/25187)
handle_write(): 4096 bytes (8192/25187)
handle_write(): 4096 bytes (12288/25187)
handle_write(): 4096 bytes (16384/25187)
handle_write(): 4096 bytes (20480/25187)
handle_write(): 4096 bytes (24576/25187)
handle_write(): 611 bytes (25187/25187)
handle_write(): finished
got 1 bytes from modem, data looks like: 1b.
got 1 bytes from modem, data looks like: f6.
got 1 bytes from modem, data looks like: 02.
got 1 bytes from modem, data looks like: 00.
got 1 bytes from modem, data looks like: 41 A
got 1 bytes from modem, data looks like: 03.
got 1 bytes from modem, data looks like: 42 B
Received DOWNLOAD ACK from phone, your code is running now!
battery_compal_e88_init: starting up

OsmocomBB Hello World (revision osmocon_v0.0.0-1754-gfc20a37-modified)
======================================================================
Device ID code: 0xb4fb
Device Version code: 0x0000
ARM ID code: 0xfff3
cDSP ID code: 0x0128
Die ID code: 14190d16f00215c6
======================================================================
REG_DPLL=0x2413
CNTL_ARM_CLK=0xf0a1
CNTL_CLK=0xff91
CNTL_RST=0xfff3
CNTL_ARM_DIV=0xfff9
======================================================================
REG_DPLL=0x2413
CNTL_ARM_CLK=0xf0a1
CNTL_CLK=0xff91
CNTL_RST=0xfff3
CNTL_ARM_DIV=0xfff9
======================================================================
entering interrupt loop
BAT-ADC: 549 4 0 0 1023 392 449 127
Charger at 34 mV.
Battery at 3753 mV.
Charging at 0 mA.
Battery capacity is 69%.
Battery range is 3199..3999 mV.
Battery full at 468 LSB… full at 585 LSB
Charging at 239 LSB (204 mA).
BCICTL2=0x3ff
battery-info.flags=0x00000000
bat_compal_e88_chg_state=0


Если при загрузке что-то пойдет не так, загрузчик может зависнуть. Просто извлеките батарею на пару секунд и вставьте обратно.

Что происходит и как это работает?


Разберемся со всем по порядку. При запуске программа osmocon блокирует последовательный порт и ожидает сообщений загрузчика, рассылая специальные beacon-сообщения. Встроенный загрузчик телефона при нажатии кнопки включения отправляет на последовательный порт запрос на загрузку прошивки (ACK). Если ему никто не отвечает, он просто посылает сообщение "@ftmtoolerror". В нашем случае osmocon принимает запрос (о чем говорит строка «Received PROMPT1 from phone, responding with CMD») и отвечает специальным сообщением (file_size=25180, hdr_len=4, dnload_len=25187). Далее загрузчик телефона либо соглашается грузить прошивку (Received PROMPT2 from phone, starting download), либо сообщает об ошибке. Как только прошивка будет загружена (handle_write(): finished) в оперативную память, загрузчик снова уведомляет нас (Received DOWNLOAD ACK from phone, your code is running now!) и подает питание на плату (battery_compal_e88_init: starting up). Ваш телефон показывает всем известные слова «Hello, world!», а в консоль пишет уже код, запущенный на нем. Круто!

Ошибка FTMTOOL


Данная ошибка в большинстве случаев возникает из-за проблем с кабелем и/или преобразователем, когда osmocon не может связаться с загрузчиком. Убедитесь, что контакты GND, RxD и TxD подключены правильно, а наименование чипсета Вашего USB-TTL преобразователя содержится в списке рекомендуемых. Попробуйте повторно нажать кнопку включения через несколько секунд. Также для некоторых моделей телефонов и преобразователей значение ключа -m программы osmocon следует указывать без окончания xor, например, -m c123 вместо -m c123xor.
Вывод osmocon в случае ошибки:

got 1 bytes from modem, data looks like: 00.
got 1 bytes from modem, data looks like: 00.
got 1 bytes from modem, data looks like: 81.
got 4 bytes from modem, data looks like: 1b f6 02 00…
got 1 bytes from modem, data looks like: 41 A
got 1 bytes from modem, data looks like: 01.
got 1 bytes from modem, data looks like: 40 @
Received PROMPT1 from phone, responding with CMD
read_file(chainloader): file_size=32, hdr_len=4, dnload_len=39
got 1 bytes from modem, data looks like: 66 f
got 1 bytes from modem, data looks like: 74 t
got 1 bytes from modem, data looks like: 6d m
got 1 bytes from modem, data looks like: 74 t
got 1 bytes from modem, data looks like: 6f o
got 1 bytes from modem, data looks like: 6f o
got 1 bytes from modem, data looks like: 6c l
Received FTMTOOL from phone, ramloader has aborted
got 1 bytes from modem, data looks like: 65 e
got 1 bytes from modem, data looks like: 72 r
got 1 bytes from modem, data looks like: 72 r
got 1 bytes from modem, data looks like: 6f o
got 1 bytes from modem, data looks like: 72 r
got 1 bytes from modem, data looks like: 00.


Не нарушает ли это закон?


Запущенное нами приложение не взаимодействует с сотовой сетью, однако перед запуском других приложений хотелось бы остановиться на вопросе легальности. В некоторых странах использование стороннего програмного обеспечения для взаимодействия с сотовыми сетями является незаконным. Условия, на которых предоставляются услуги сотовой связи, могут отличаться у разных операторов, и, чаще всего, не допускают использования несертифицированного ПО. Поэтому, по умолчанию, возможность передачи данных в сеть отключена. Если Вы знаете, что делаете, и Ваши действия не нарушают действующие законы, передачу данных можно включить перед сборкой проекта в файле src/target/firmware/Makefile, раскомментировав строку «CFLAGS += -DCONFIG_TX_ENABLE». Авторы проекта посвятили данному вопросу небольшую страницу wiki/LegalAspects.

Структура проекта, процесс загрузки приложений (прошивок)


В корневой папке можно найти три папки: doc, include и src. В doc или include врядли найдется что-либо полезное. Больше всего нас интересует папка src, которая содержит следующие директории:
  • host — исходный код программ, исполняемых на серверной строне;
  • target — исходный код прошивок, а также библиотек для их компиляции;
  • target_dsp — инструменты для работы с исполняемым кодом DSP и плагины для IDA;
  • wireshark — патчи для старых версий Wireshark;
  • shared — содержит копию библиотеки libosmocore, используемую для сборки прошивок.

Подробнее о структуре проекта можно почитать в файле README.development. Исходные коды приложений OsmocomBB хранятся в папке src/target/firmware/apps, а их скомпилированные версии доступны отдельно для каждой платформы в папке /src/target/firmware/board. Вы можете встретить два варианта скомпилированного приложения (прошивки): compalram и highram. Первый вариант предназначен для загрузки с помощью стандартного загрузчика телефона. Некоторые «объемные» приложения, например, RSSI, не могут быть загружены стандартным загрузчиком, поэтому выполняется «загрузка по цепочке»: сначала загружается кастомный загрузчик loader.compalram.bin, который загружает прошивку типа highram. Синтаксис «загрузки по цепочке»:
# На сайте проекта можно встретить устаревший синтаксис:
$ host/osmocon/osmocon -m c123xor -p /dev/ttyUSB0 -c target/firmware/board/compal_e88/rssi.highram.bin target/firmware/board/compal_e88/chainload.compalram.bin
# Однако в текущей версии проекта chainload интегрировали в osmocon, поэтому последний аргумент не требуется.
# Просто используйте ключ -c:
$ host/osmocon/osmocon -m c123xor -p /dev/ttyUSB0 -c target/firmware/board/compal_e88/rssi.highram.bin


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

Что интересного здесь есть?


Пару слов о приложениях, доступных в различных ответвлениях проекта. Более детальному обзору будет посвящена следующая статья, а пока можно почитать официальную документацию wiki/Applications.

Взаимодействие с оборудованием


  • osmocon — выполняет загрузку прошивок в оперативную память телефона, а также создает интерфейс обмена информацией между прошивкой и другими серверными программами. Параметр -m позволяет указать протокол обмена данными для различных моделей телефонов, а с помощью параметра -с выполняется «загрузка по цепочке» (chainloading) тяжеловесных приложений, которые не способен загрузить стандартный загрузчик телефона.
  • osmoload — позволяет читать и записывать содержимое flash-памяти телефона. Используется при прошивке приложений. Подробнее на странице wiki/flashing.
  • calypso_pll, rita_pll — используются для получения информации о чипсете и трансивере телефона.

Приложения 2 и 3 уровней стека протоколов GSM


  • mobile — приложение, реализующее функционал обычного телефона, расширенное дополнительной функциональностью для взаимодействия с сетью GSM. Подробнее на странице wiki/mobile.
  • cell_log — позволяет выполнять сканирование диапазона частот, находить ближайшие базовые станции, а также получать информацию о них (мощность принимаемого сигнала, MNC, MCC и другую системную информацию). Позволяет синхронизироваться с базовой станцией и получать информацию, передаваемую на канале BCCH.
  • ccch_scan, bcch_scan — позволяют синхронизироваться с базовой станцией и получать ее служебную информацию.
  • cbch_sniff — позволяет записывать служебную информацию сети в файл.
  • gsmmap — используя вывод cell_log, генерирует KML-файл для Google Maps, визуализирующий расположение базовых станций на карте.

Приложения, выполняемые на телефоне


  • loader.bin — загрузчик, написанный разработчиками проекта. Используется для чтения и записи flash-памяти, а также при «загрузки по цепочке».
  • compal_dsp_dump.bin — позволяет получать дамп содержимого DSP-процессора.
  • menu.bin — предоставляет возможность выбора приложения для загрузки из flash-памяти.
  • rssi.bin — приложение, позволяющее отслеживать мощность принимаемого сигнала на различных каналах сотовой сети.
  • emi.bin — приложение для проведения стресс-тестинга беспроводного оборудования.
  • layer1.bin — используется для взаимодействия с сотовой сетью и SIM-картой.
  • trx.bin — превращает телефон в Transceiver для работы OpenBTS или OsmoBTS.

Конец?


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

Навигация


This entry passed through the Full-Text RSS service - if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.

В ReactOS значительно улучшили поддержку тем оформления

сегодня в 16:58

Вслед за обновлением эксплорера, благодаря стараниям и патчам разработчиков Ismael Ferreras Morezuelas и Jared Smudde, в ReactOS значительно улучшилась поддержка как собственных, так и сторонних тем оформления. Ниже скриншоты примеров, как теперь может выглядеть рабочий стол.

image
image

image

image

Пакет тем для самостоятельного тестирования можно найти на странице по ссылке.
Как видно на скриншотах, ряд небольших проблем еще ожидают своих исправлений.

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

This entry passed through the Full-Text RSS service - if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.

Upgrade до Middle PHP-разработчика за 3 месяца

В очередной раз на меня свалилась задача найти хорошего PHP-программиста.
По результатам прозвона потенциальных кандидатов, 90% тех, кто мнит себя Middle, на самом деле Junior и годы опыта не спасают, потому что клепают однотипный код в пределах заданий, посланных свыше.

Прописал минимальный план желающим сделать рывок и перейти на следующий уровень без отрыва от производства.

Месяц 1


Прочитать книжки (по неделе на книжку, читая вечерами и на выходных):
  1. PHP+MySQL — ozon.ru
  2. ООП и паттерны — ozon.ru
  3. Совершенный код — ozon.ru
  4. Symfony 2 book — скачать на английском, частичный перевод на русский

Можно заменить на аналогичные, почти всё можно скачать без смс.

Предвидя холивар "почему Symfony": если у вас IQ меньше 120 (без обид, многое заложено генетически, но вы точно хотите быть программистом?), то выберите Yii или Laravel — они проще в изучении. Symfony иногда неоправданно сложный, но интересен в плане изучения концепций. Зная его, другой фреймворк потом будет понять элементарно. И даже если вы не будете использовать его полностью, можно брать отдельные компоненты (список пострадавших), которые как паттерны, могут быть знакомы вашим коллегам.
Хотя если у вас неподалёку есть старший товарищ, который хорошо знает другой фреймворк, можно выбрать его.

Месяц 2


Прочитать по 3-5 статей и на практике поработать с (1 вечер — статьи, 1 вечер — практика):
  1. PSR: PSR-1, PSR-2, PSR-4, Symfony Code Standards
  2. BashОсновы, в примерах — 1, 2
  3. nginx+PHP5-FPMустановка, Nginx изнутри, Тюнинг nginx
  4. Mercurial (1, 2, 3, 4, 5, 6) или Git (интерактивный тур, Workflow, книжка)
  5. PHPUnitосновы, перевод 8 глав документации
  6. PHPStormQuick Start, видео-уроки
  7. Vagrantдокументация, в PhpStorm
  8. Twitter Bootstrapсайт
  9. Twigнебольшая книжка
  10. Composerосновы, свой vendor

Месяц 3


Сделать свой проект на GitHub, используя всё вышеперечисленное (1 месяц вечерами и на выходных).
Цель: закрепить знания, пройдя самому весь путь от ТЗ до готового проекта, на который можно зайти в Интернете и давать ссылку в резюме.

Рекомендации:

  1. минимум функционала, забыть слова "универсальное решение"/"платформа"/"плагины", иначе надоест быстрее, чем доделате
  2. не использовать готовые движки вроде Wordpress/Joomla/Magento, но использовать фреймворк, чтобы не велосипедить
  3. не обращать внимания на вёрстку — только Twitter Bootstrap
  4. ответы на вопросы — Google и StackOverflow, не пытайтесь долго думать сами, полезнее научиться правильно формулировать вопрос

Идеи проектов:

  1. блог
  2. интернет-магазин
  3. форум
  4. сайт прогноза погоды
  5. сайт с актуальными курсами валют
  6. ваш вариант

Бонус:

  1. Записаться на курсы английского (кроме хабра, все интересные статьи и документация к библиотекам — на английском). Вот есть даже специализированное Skype-обучение для IT-шников, хотя я — за классические групповые занятия.
  2. Научиться набирать вслепую (2 недели по вечерам)
  3. Выучить на память TOP100-300 функций PHP (1 неделя)
  4. Изучить еще один язык программирования на уровне написания простеньких приложений. Желательно совсем другой парадигмы: Go (отличная обучалка), Lisp (аргументация — 1, 2), Haskell (как-то так)

Удачи!

This entry passed through the Full-Text RSS service - if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.

Эльфийский язык программирования

Как известно, если ты серьёзный программист, синтаксический сахар тебе не нужен, это баловство. Ещё несколько лет назад Python считался детской погремушкой именно из за этого. Чем вам фигурные скобки мешали? Ребячество какое-то придумали: заменить фигурные скобки на отступы табуляции. Сказал солидный дядя. Маличики согласно покивали, виновато глядя в потолок. Через год все работали в коллективах где Питон основной язык.
Правильное развитие языков какое? А вот какое. Берётся паттерн программирования, который применяется в нынешнем языке, и делается попытка внедрить этот паттерн на уровне самого языка в уже новом языке. То есть жила-была функция без имени, вы её называли лямбда, может быть даже имя было, но оно было не нужно вам, просто компилятор требовал, ну называли «f1», а в новом языке это сразу — лямбда! Или был массив, вы как то ограничивали его длину и состав, и как следствие называли его кортежем, а теперь, вуаля, он у вас сразу — кортеж и удобнее пользоваться. Использовали вы отложенные расчёты сложно ухищраясь на С++, а теперь — бамс! и у вас прямо на уровне языка то же самое, называется lazy eval, только с монадами осторожнее, Люк. А что такое монады, мастер Йода? Ой всё!

Подразумевается, что если ты используешь такой новый язык, то ты уже обязан ЗНАТЬ эти паттерны и уметь их применять. Повышается репутация и рыночное преимущество уже от того, что в си-ви написано название языка содержащего новую семантику ассоциирующуюся у сообщества с лучшими достижениями. С другой стороны, кто круче шарит, например, в замыканиях, тот, кто применяет их в современном языке с лямбдами или тот, кто их много лет применял на Си? Вопрос риторический.

Так что синтаксический сахар или семантическое мясо, это вопрос открытый.

Ещё одно направление в новых языках это изменения под капотом. Ура! В нашем языке теперь новый сборщик мусора, который можно ставить на паузу, а значит достижима мягкая многозадачность! А у нас теперь целочисленный код оптимизируется на порядок лучше, только надо ставить одну «зюзюку» в начале функции и не делить дробно!

Это всё замечательно, как говорится, «мамы всякие важны». Но мне вспоминаются основы языкознания, если у вас есть синтаксический сахар, семантическое мясо и подкапотный фарш, то где спрашивается остальные части любого языка: грамматика, лексика? Соответственно возникла идея «лексического крема» или «грамматического варенья».

Сегодня хочу представить вам экспериментальный язык программирования, Elfu. Название довольно внезапное, просто один мой друг, сумасшедший учёный из Новосибирского Академгородка, изобретающий систему автоматического доказателства теорем, увидев пример кода воскликнул: «это что такое, эльфийский!?».

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

Просто для примера, картинка абстрактного искусства:

this.a = this.compare((this.b + this.c) && this.d, this.x + this.y / this.z,

(function() { var closure = 'val'; return function() { alert(closure); }; })())

И так на пол экрана! Мне ужасно захотелось, просто чтобы понять, что происходит стереть все упоминания this, примерно так:

a = compare((b + c) && d, x + y / z

И вдруг, всё что было на экране стало понятно. Удалось окинуть взглядом всё поле боя и разобраться что к чему.

Тогда я решил сделать экспериментальный язык, где заменить this на ⚫, function на ➮.

⚫a = ⚫compare((⚫b + ⚫c) && ⚫d, ⚫x + ⚫y / ⚫z,
(➮() { var closure = 'val'; return ➮() { alert(closure); }; })())

Опыт транспилеров у меня уже был, с проектом dotcall, а вообще система транспиляции в JavaScript мне приглянулась в coffeeScript. Дело сразу пошло. Сделав маленький траспилер в JavaScript я стал активно пользоваться своим детищем, чтобы посмотреть, насколько это удобно на практике. Ввод необычных символов сразу меня беспокоил, ведь на клавиатуре всего 32 символа. Но использование замены по табу решило эту задачу, набирать на практике оказалось очень удобно и легко.

Поскольку я каждый день много раз вынужден набирать конструкции вроде такой:

for (var i = 0; i < data.length; i++) {

и давно мечтал иметь её сокращёный аналог, у меня даже прижилось в С++ макро each(i, array), я решил сразу сделать и такое:

i ⬌ data {

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

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

Поскольку я не пользуюсь отладчиком, а пользуюсь выводом в консоль и отладочными кодомодификациями, то есть фактически набираю console.log() десятки и сотни раз за трудовую сессию, то мне сразу захотелось упростить этот набор, и вместо:

console.log('hello world', '!')

набирать

ロ 'hello world', '!'

Собственно предыдущая строчка это и есть hello.yy, то есть «hello world in elfu programming language»!

Потом, в функциональном программировании часто встречаются упрощённые функции, вроде того:

this.data = this.data.map(function (item) { if (item > 20) return item } )

после замены function на ➮, было решено попробовать пойти дальше, гулять так гулять:

⚫data = ⚫data ⧉ (➮ item { ⌥(item > 20) $ item } )

как видите: ⌥ это if, ⧉ это map, $ это return.

Теперь я вспомнил, что мне постоянно приходится придумывать как назвать этот аргумент item каждый раз, а название ему часто и не нужно, как например в данном случае, вполне подойдёт a. Тогда я решил, что если у функции объявленой через ➮ нет параметров, то по умолчанию объявлены три параметра a, b, c. А если нужно, чтобы у функции фактически не было параметров, то надо указать явно ().

⚫data = ⚫data ⧉ (➮ { ⌥(a > 20) $ a } )

Как написал один автор в одной статье на Хабре, жаль я забыл ссылку скопировать тогда, «удобно когда не надо глазами парсить лишние кейворды и идентификаторы». Привет тебе, о забытое имя.

Подчеркну, язык мой экспериментальный, он ничего не заменяет, ничего не отменяет, и претендует только на звание эксперимента в заданном направлении.

Вот ещё несколько любопытных экспериментальных фич Эльфу:

A ⬊ 1 // A.push(1)

A ⬋ 22 // A.unshift(22)

n⁰ = nˣ + mⁱ // n[0] = n[x] + m[i]

⌥ (⬤ a ≟ '∅')
// ⌥ (typeof a == 'undefined')

⌥ (name ≠ ⦿ && id ≠ ⦾) ⏀ ⚫name
//if (name != true && id != false) delete this.name

ロ ⍽(⚂ * 100)
// console.log(Math.floor(Math.random() * 100))

То есть ⚂ это игровой кубик, который легко ассоциируется с датчиком случайных чисел. ∅ перечёркнутый кружок, то есть неопределённость. А вот ⏀ это разрубание пополам, то есть уничтожение объекта. Наконец-то можно снова, как в школе на математике произосить mⁱ «эм итое». Правда это суперскрипт, субскрипта в юникоде нет, точнее он есть но очень неполный, в Эльфу он не используется пока.

Многие символы настолько коротки и понятны, что стало очевидно, что скобки к аргументам после них выглядят громоздко. Пришла идея сделать скобки необязательными, в некоторых случаях. Например str ≀ 'a' аналогично str.indexOf('a'). ≣'fs' аналогично require('fs').

Уже более полугода, ежедневно я пользуюсь Эльфу. Он работает в node.js (и в браузере при некоторых ухищрениях аналогичных применяемых в других транспилерах, вроде coffeeScript). Я взял расширение файла .yy. Можно просто сделать:

npm i -g elfu
require('elfu')
require('library.yy')

Все символы используемые в Эльфу это просто символы из набора Unicode. Ничего не изобретено, в болшинстве своём они из странички Unicode спецификации Math and other symbols, но есть и из рэнжей разных языков. Чтобы не было проблем, я сделал шрифт elfu.ttf в котором соединил все на данный момент используемые символы. Но на современных Linux, Windows, MacOS, iOS, Android всё из коробки отображается как надо, хотя некоторые символы берутся из разных шрифтов и могут выглядеть не очень красиво, и быть слегка разного размера.

Расширение файла .yy это отсылка на эльфийский алфавит, будем воображать, что это некий эльфийский знак, руна. На самом деле на эльфийском языке, надо говорить «Хости ламмен», что значит «Язык чисел». Впрочем, наверное надо расширение .elfu тоже обрабатываеть в require(). Кстати пакет npm elfu устанавливает три утилиты коммандной строки: yy, yyj, jyy. yy можно использовать вместо node: «yy hello.yy», yyj компилирует elfu файл в Javascript с выводом в STDOUT, jyy компилирует обратно из Javascript в Elfu.

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

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

http://ift.tt/1KLJlZ0
http://ift.tt/1KLJoE6
http://ift.tt/1KLJlZ2

Чего бы хотелось от почтенной публики, так это участия, хотя бы понарошечку. Если вас тема заинтересовала, кидайте сюда или на гитхаб ваши предложения, что можно ещё добавить или поменять. Очень много ещё Unicode символов и всяких возможностей! Даже если Эльфу останется лишь экспериментом сумасшедшего философа, многие символы могут пригодиться в других языках и разработках. Кстати, например в Эльфу стандартизованы последовательности для ввода символов по tab-completion. Например io|TAB превращается в ≀ и означает .indexOf(). Есть и готовые конфиги для Sublime Text и Geany.

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

This entry passed through the Full-Text RSS service - if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.

Реализация Single Sign On в Symfony2 приложении

Что такое Single Sign On?


Single Sign On — это технология, с помощью которой пользователь, будучи аутентифицированным на удостоверяющем центре (далее Identity Provider, IdP), будет автоматически аутентифицирован на другом сервисе (далее Service Provider, SP или Consumer[1-N]) этой компании.

Механизм Single Sign On используют такие сайты, как ХабраХабр, Yandex, Google. Приемущества такого подхода к аутентификации пользователей очевидны:

  • Пользователь вводит пароль только 1 раз
  • Или вовсе не вводит пароль на IdP, если там был использован вход через социальную сеть или с использованием OpenID
  • Автоматически аутентифицируется на всех проектах компании
  • Данные пользователя могут плавать между сервисами от IdP до SP прозрачно для пользователя

Минусы, конечно, вытекают, как всегда, из плюсов:
  • Потеря пароля от IdP влечет за собой проблему входа во все сервисы
  • Потенциально возросший риск кражи мастер сессии с IdP (может быть уменьшен с помощью привязки сессии к подсети провайдера, а также использования HTTPS, HTTP Only Cookies и SSL Only Cookies)
  • Потенциально возросший риск кражи пароля от IdP
  • ...

Несмотря на это, с точки зрения бизнеса, а также user experience, реализация данного функционала перевешивает все минусы, и начинается эпопея по имплементации SSO в компании.

Перед тем как приступить к имплементации SSO в компании, хорошо было бы убедиться, что вы хорошо знаете, что такое:


а еще лучше, как применять их самому.

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

На хабре есть еще одна отличная статья по базовым принципам работы с Cookies и как надо правильно ставить Cookies, чтобы не остаться без штанов: http://ift.tt/1e907F5.

Итак, после ознакомления с базовой теорией: что такое SSO, аспектами безопасности, которые связаны с этой задачей, — мы можем приступить к ее реализации.

Как это будет работать


В общем случае аутентификация будет проходить по следующему сценарию:

image

Рассмотрим сценарий, когда пользователь через закладки переходит на какую-либо защищенную авторизацией страницу (п. 1 на схеме).
Далее в Symfony2 активируется механизм Entry point и переадресовывает нас на наш IdP, где нам должны докинуть OTP. Тут есть несколько сценариев развития событий:

  1. Пользователь аутентифицирован на IdP, тогда IdP просто докинет в цепочку переадресаций OTP (п. 3 на схеме, зеленая линия)
  2. Пользователь не аутентифицирован на IdP, тогда его надо отправить на форму ввода логина/пароля (п. 3 на схеме, красная линия)
  3. Пользователь вообще в первый раз нас видит, но хочет зарегистрироваться и уходит на форму регистрации (В этот момент в сессии на IdP сохранен SP, с которого он пришел.)

После того как пользователь, например, прошел регистрацию, его надо перенаправить на п. 3 по зеленой линии на валидацию OTP на SP, с которого он пришел к нам на IdP. Когда мы на SP валидируем OTP, мы делаем доверенный REST запрос к нашему IdP, чтобы удостовериться, что такой OTP действительно существует и еще не истек по времени. В этот момент REST сервис должен инвалидировать этот OTP. Ставьте лок, эта операция должна быть атомарна. Дальнейшие запросы с таким OTP должны возвращать либо HTTP 400, либо HTTP 404 для SP.

В случае, когда IdP ответил, что такой OTP существует и валиден, SP аутентифицирует пользователя посредством выдачи ему PreAuthenticatedToken'а.

Выход будет работать по следующей схеме:

image

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

Предположим, что пользователь был на некой странице /secured_area и нажал на «Выход». В этот момент происходит локальный логаут в рамках SP. Затем мы уходим на IdP на специальный URL /sso/logout, который будет управлять процессом выхода со всех сервисов для этого пользователя. Т.к. пользователь уже пришел с SP, то IdP выбирает следующий сервис, который есть в компании, и отправляет на него делать выход. Тот сервис, в свою очередь, снова по завершению, отправляет нас на IdP и в случае, если сервисы кончились, выполняет локальный выход (п. 5 на схеме). После пользователь отправляется обратно на SP, с которого он начал делать выход.

Есть и другой вариант развития событий, в котором пользователь начинает процесс выхода не с SP а с IdP. И выглядит это примерно так:

image

Удостоверяющий центр (IdentityProvider)


Чтобы сделать удостоверяющий центр, сначала вы должны выбрать приложение в вашей компании, которое будет за это отвечать, наподобие, как это сделано у Yandex (Яндекс.Паспорт) или у Google (Google Accounts).

В это приложение мы будем устанавливаеть первую часть: SingleSignOnIdentityProviderBundle

SingleSignOnIdentityProviderBundle отвечает за:

  • Генерацию одноразовых паролей (OTP)
  • Запоминает в сессию, с какого SP пришел пользователь
  • Функциональность для выхода со всех SP-ов

Ставим через composer:
php composer.phar require "korotovsky/sso-idp-bundle:~0.2.0"

Далее обновляем зависимости и прописываем наш бандл в AppKernel:
app/AppKernel.php
// app/AppKernel.php
$bundles[] = new \Krtv\Bundle\SingleSignOnIdentityProviderBundle\KrtvSingleSignOnIdentityProviderBundle();


Подключаем роуты /sso/login и /sso/logout из бандла:
app/config/routing.yml
# app/config/routing.yml:
sso:
    resource: .
    type:     sso


Теперь настраиваем IdP бандл:
app/config/config.yml
# app/config/config.yml:
krtv_single_sign_on_identity_provider:
    host:             idp.example.com # Хост нашего IdP приложения
    host_scheme:      http            # Схема нашего IdP приложения.

    login_path:       /sso/login/ # Путь, где будет вызваться OTP
    logout_path:      /sso/logout # Путь, где будет осуществляться централизованный контроль для выхода

    services:
        - consumer1 # Кодовое имя SP может быть любым, но обязательно уникальным среди всех остальных

    otp_parameter:    _otp   # Имя OTP параметра
    secret_parameter: secret # Имя параметра в Dependency Injection для подписи всех урлов переадресации, 
                             # значение этого параметра должно быть одинаковое на всех приложениях.


Правим security.yml:
app/config/security.yml
# app/config/security.yml
security:
    access_control:
        - { path: ^/sso/login$, roles: [ROLE_USER, IS_AUTHENTICATED_FULLY] }


Теперь необходимо зарегистрировать SP в наш бандл, для этого создадим класс, который имлементирует интерфейс \Krtv\Bundle\SingleSignOnIdentityProviderBundle\Manager\ServiceProviderInterface и зарегистрируем его в сервис контейнере с помощью тега
src/Acme/Bundle/AppBundle/Resources/config/security.yml
services:
    acme_bundle.sso.consumer1:
        class: Acme\Bundle\AppBundle\Sso\ServiceProviders\ServiceProvider1
        tags:
            - { name: sso.service_provider, service: consumer1 }


На этом настройка IdP закончена, переходим к настройке SP части.

Ставим через composer:

php composer.phar require "korotovsky/sso-sp-bundle:~0.2.0"

Далее обновляем зависимости и прописываем наш бандл в AppKernel:
app/AppKernel.php
// app/AppKernel.php
$bundles[] = new \Krtv\Bundle\SingleSignOnServiceProviderBundle\SingleSignOnServiceProviderBundle();


Подключаем роут /otp/validate/ для валидации OTP:
app/config/routing.yml
# app/config/routing.yml:
otp:
    # this needs to be the same as the check_path, specified later on in security.yml
    path: /otp/validate/


Теперь настраиваем IdP бандл:
app/config/config.yml
# app/config/config.yml:
krtv_single_sign_on_service_provider:
    host:             idp.example.com # Хост нашего IdP приложения
    host_scheme:      http            # Схема нашего IdP приложения.

    login_path:       /sso/login/ # Путь где будет вызваться OTP

    # Configuration for OTP managers
    otp_manager:
        name:       http
        managers:
            http:
                provider:    service # Active provider for HTTP OTP manager
                providers:           # Available HTTP providers
                    service:
                        id: acme_bundle.your_own_fetch_service.id

                    guzzle:
                        client:   acme_bundle.guzzle_service.id
                        resource: http://ift.tt/1MP9x3W

    otp_parameter:    _otp   # Имя OTP параметра
    secret_parameter: secret # Имя параметра в Dependency Injection для подписи всех урлов переадресации, 
                             # значение этого параметра должно быть одинаковое на всех приложениях.


Чтобы у нас был «честный» SSO в качестве менеджера необходимо выбирать http метод, а в качестве провайдера выбирать service. Для этого надо имплементировать интерфейс Krtv\SingleSignOn\Manager\Http\Provider\ProviderInterface.

Правим security.yml:

app/config/security.yml
# app/config/security.yml
    firewalls:
        main:
            pattern: ^/
            sso:
                require_previous_session: false
                provider:                 main
                check_path:               /otp/validate/ # Same as in app/config/routing.yml

                sso_scheme:       http              # Required
                sso_host:         idp.example.com   # Required
                sso_otp_scheme:   http              # Optional
                sso_otp_host:     consumer1.com     # Optional
                sso_failure_path: /login
                sso_path:         /sso/login/       # SSO endpoint on IdP.
                sso_service:      consumer1         # Consumer name

            logout:
                invalidate_session: true
                path:               /logout
                target:             http://ift.tt/1e905NG


На этом настройка наших приложений завершена.

Чтобы следить за обновлениями бандлов, ставьте «звездочки» для них:

This entry passed through the Full-Text RSS service - if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.

Эмуляция ведомых 1-wire устройств на MSP430


Как-то раз я купил на eBay диммер для светодиодной ленты с ИК-пультом управления. Помимо того, факта, что через пару часов использования умер выходной MOSFET и его пришлось менять, со временем обнаружились следующие проблемы:
  1. Слишком низкая частота ШИМ. При низкой яркости мигание было видно невооруженным глазом. Наверное, это связано с параметрами работы выходного транзистора — если, например, время включения/выключения слишком большое, то частоту ШИМ повышать нельзя.
  2. Отсутствие каких-либо возможностей для коммуникации, кроме ИК-пульта. На плате обнаружилось много разных дополнительных разъемов (питание +5V, выход ШИМ и еще какие-то), но никакого другого интерфейса управления. Что, впрочем, логично.

Иногда такие недостатки можно устранить доработкой прошивки, но на микроконтроллере была стерта маркировка, и ничего похожего в таком корпусе я на Digikey/Mouser не нашел. Было решено реализовать аналогичную схему, лишенную указанных недостатков. Из интерфейсов управления рядом оказался 1-wire. Так появилась библиотека для эмуляции slave-устройств, совместимых с 1-wire.

Протокол работы

1-wire — двунаправленная шина связи. Устройства используют выход с открытым коллектором для изменения состояния линии данных, которая подтянута к +5V. Кодирование информации осуществляется с помощью времени, на которое устройство притягивает линию данных к 0. Более подробно о шине можно прочитать здесь.

Реализация на базе микроконтроллера MSP430G2553

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

Линейный стабилизатор нужен, если планируется питать МК от 1-wire линии.

Код

Созданная библиотека состоит из двух частей:

  1. Код, обрабатывающий передачу отдельных бит (таймслотов), байтов, сигнала сброса и работающий с командами SEARCH и MATCH
  2. Код, отвечающий за какое-либо конкретное устройство. Эта часть обрабатывает доступ к регистровому пространству

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

Чтобы полученное устройство было совместимо с существующими решениями, был написан код для эмуляции микросхемы, частично совместимой с DS2408, которую по каким-то причинам перестали выпускать. Это позволяет использовать устройство вместе с owserver и owhttpd. В случае с диммером байт, отвечающий за состояние выходов микросхемы, задает скважность ШИМ-выхода.

Инициализировать библиотеку можно довольно просто:

#include <msp430.h> 
#include <stdint.h>

#include "one-slave.h"
#include "one-2408.h"

// Массив с описаниями устройств
static one_device devices[] = {
    {
        // (ROM-адрес) | (Family code)
        .rom = 0x0011223344556600 | ONE_2408_FC,
        // Функция инициализации предоставляется конкретным устройством
        .init = &one_2408_init,
        // Параметры устройства: в данном случае указатель на область регистров,
        // отвечающих за PORT1 в микроконтроллере
        .device = &(one_2408) {
            .port_base = &P1IN
        }
    },
    {
        .rom = 0x00AA000000000100 | ONE_2408_PWM_FC,
        .init = &one_2408_pwm_init,
        // PWM-выход: P2.1
        .device = &(one_2408_pwm) {
            .out_bit = BIT1,
            .port_base = &P2IN
        }
    }
};

void main(void) {
    WDTCTL = WDTPW | WDTHOLD;
    one_init(
        (one_device *) &devices,
        ARRAY_SIZE(devices)
    );
    _EINT();
    while (1) {
        one_process_state();
    }
}

Железо

Вместо существующей платы была создана другая:

В реальности плата выглядит хуже, потому что нашлось несколько огрехов, которые нужно было исправить. Использовать переменный резистор для ручной регулировки, к сожалению, не получилось — не хватило таймеров, из двух два были заняты. Создавать на основе аппаратного таймера много «программных» в данном случае нельзя, так как на линии все происходит довольно быстро (для МК) и код обработки прерывания таймера может испортить какой-нибудь таймслот длиной в 30 мкс.

В новой плате частота PWM составляет 15 кГц, увидеть мерцание глазами и камерой не получилось.

Подключение к Openhab

Подключение к Openhab осуществляется довольно просто — с использованием биндинга HTTP. Для изменения яркости достаточно отправить запрос к owhttpd следующего вида:

http://owhttpd:2121/29.0100000000AA/PIO.BYTE/?PIO.BYTE=VALUE

VALUE — значение от 0 до 255.

На телефоне это выглядит так:

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

Заключение

В заключение перечислю еще раз основные особенности библиотеки:

  • Работа на прерываниях, в промежутках между транзакциями микроконтроллер находится в режиме низкого энергопотребления
  • Возможность эмуляции нескольких устройств на одном микроконтроллере
  • Работа проверялась на MSP430G2553, теоретически, на других контроллерах этой серии тоже заработает

Исходники можно найти здесь: http://ift.tt/1B8nbOs

This entry passed through the Full-Text RSS service - if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.

пятница, 12 июня 2015 г.

Как я нашел лучший в мире язык программирования. Часть Йо (2.72)

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

Тем кто изначально отнесся скептически, хочу сказать, что я не собирался и не собираюсь агитировать кого-либо за тот или иной язык. Написал же я просто с одной искренней целью: поделится радостью открытия. Когда прёт (а с возрастом прёт все реже и реже, тем более от такой, вроде, мелочи по жизни, как язык программирования) хочется поделится. Вот такое вот редкое и детское желание: ребята, смотрите как круто! Тем более что я действительно ждал, искал, и переживал из-за вопроса долгие годы, и ответ от него не был мне очевиден, хоть я и не раз проходил мимо.

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

Язык программирования — зачем?

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

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

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

Кроме того в дискуссиях о языках мы разбиваем языки на классы (динамическая типизация, managed runtime, и так далее), разбиваем задачи на классы, но вот почему-то практически никогда не разбиваем “программистов” на классы. Иногда, конечно, мы это делаем, но чаще всего разбивая на программистов на “новичков” и остальных «программистов», и это обычно происходит только тогда когда “новичок” сам относит себя к этому классу. Впрочем эта классификация тут же теряется, потому что даже самый махровый ламер, в ответ может начать вещать с позиции гуру, совершенно не задумываясь о том к каком классу относится он сам. Если, помимо языков и задач, начать классифицировать еще и участников дискуссии (а это надо делать), то зоопарк рисуется еще тот.

Тема, классификации программистов — отдельная и безусловно интереснейшая история на грани с психологией (или психиатрией), которой можно заняться на досуге. Сейчас же я приведу пару примеров, которые уже говорят о том, что влияние субъекта и его мотивов в вопросах оценки языка не менее велико (а скорее более), чем сам язык или задачи под которые он выбирается. Ну например:

Мудак

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

Я конечно сказал что это дурдом, и что они сам себя раком поставил, да и забыл эту историю, пока не встретил знакомца в очередной раз, где-то полгода назад. Знакомец рассказал что едет в Бразилию, в командировку. Помогать бразильцам делать очень навроченную систему чего-то там на Scala. Едет он к сожалению один, поскольку для написания столь хитромудрого кода у его соратников не нашлось достаточно интеллекта, но ничего он и один справится. И в конце добавил что очень рад работать с такими умными бразильцами и восхищен их планом. План был простой: писать все на Scala обязательно, и архитектура должна быть такой, чтобы обычному человеку в голову не влезла. Что позволит им захватить маленький, но денежный нишевый рынок в Северной Америке, и жить долго и счастливо, получая ежемесячно чеки за саппорт сложнейшего продукта.

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

Микроблоггер

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

Есть, например, популярные в узких кругах микроблоггеры которые многие годы рассказывают о крутости всего того, что я считаю слишком умным для меня, и даже не лезу эти истории, микроблоггер же чморит всех “лохов” направо и налево, даже если вы пишете на Haskell, но не успели оценить красоту Idris (или чего-то там). Беда в том, что микроблоггера слушает молодежь, кивает и рисует в голове картину успешного программиста, который занимается умными вещами, а не бытовухой, как они и, наверное, хочет стать таким же умным. И не знают, что в реальной жизни “звезда функционального программирования”, например, копается в миллионах строк на Perl в команде из 100 человек, и практики применения всего о чем рассказывает не имеет никакой. Звезде идет четвертый десяток лет, и ни на одном месте работы его не держали более трех, да и не смог он оставить следа в жизни. Во всем интернете нет ни строчки его кода, разве что портированные чужие либы с чего-нибудь на Haskell, или с PHP на Perl.

Микроблоггер тоже ищет в языке волшебную палочку, которая наконец даст ему возможность хоть что-нибудь создать самому, но не находит, и прыгает с одного языка на другой, с надеждой, что вот он: тот самый язык который ляжет на его ментальную модель, и он сможет творить, но нет, и нет, и нет. И он опять на унылой работе наедине с Perl… Сейчас я заплачу… Но микроблоггер не плачет! Он выходит в социальные сети, и вот уже миру видится гуру функционального программирования, гигант мысли, вершина профессиональной карьеры. И десятки вдохновленных юношей бросают программировать и начинают изучать Haskell (или то, что микроблоггер в данный момент рассматривает как палочку), в надежде стать таким же как он.

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

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

Прочие заболевания

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

Пораженный таким вирусом юноша ведет себя, примерно, следующим образом: был у нас такой кадр, которого мы только взяли и дали отдельную задачу. Ну кадр что-то поделал пару недель и приходит посоветоваться, мол вот я тут напридумывал так и так, на доску схема не влазит, но вроде все хорошо, только вот еще пара use cases никак одновременно не получается, типа давайте выберем только один (CAP-теоретик, блин). Ну ему говорят, а давай все это твое нахер выкинем, и сделаем две такие штуки. Чувак зависает на пять минут в деадлоке, потом начинает выдавать какие-то звуки: «ну», «ну»… — «что ну?» — «ну это же слишком просто». Вирус отрубающий способность думать просто вообще распространен как простуда. Студент приходит в какую нибудь контору, там уже построен монстр который рассыпается и нужно через разные места этого монстра поддерживать, а не дай бог еще и развивать. Гавно, палки, костыли, дырки, десять человек вместо двух, и все давно заражены одним из мозговых вирусов программистов. Кстати, большинство юношей все же приходит здоровыми, поэтому мы часто слышим что «неопытные программисты стремятся переписать весь код». Но ему это сделать никто не дает, он привыкает, расслабляется, и пипец, заболел. Через пару лет у него никогда не возникнет мысли что так не должно быть. Программный продукт это сложная вещь. Программисты получают много денег за то, что эти сложные вещи делают, и по-другому не бывает.

Кстати, практически в любом городе, когда на собес приходят люди из известных контор, можно с высокой степенью вероятности предсказать здоров он или болен, а если болен то чем, так как зараза со временем поражает практически всех. Я отличаю это от культуры, которая как бы магнитное поле, перестающее влиять на программиста после выхода из конторы, хоть и иногда оставляющая в нем след. Программисты пораженные разнообразными вирусам редко задумываются над главным требованием к языку — их волнует множество разнообразных деталей, но не продуктивность, как и в целом вопрос зачем? их мало волнует.

Язык программирования — почему?

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

Как бы не так. Цели создателей языков тоже на удивление разнообразны. Вот c какой целью Odersky создавал Scala? Может быть это были сугубо академические (исследовательские) цели, и ему, как исследователю, было интересно сделать что-то новое вокруг идеи связки функционального и объектно-ориентированного программирования. Из презентации: в создании Scala он был мотивирован двумя гипотезами. Причем большинство других языков не мотивированы одной или обоими из этих гипотез. А если гипотезы не верны, то где будет Скала? А если верны то где будут другие языки? А может эти гипотезы вообще фуфло для “красоты”. Может быть он просто выполнял некий университетский “план” и типа вот вам как просите: гипотезы и брюки для птиц. А может быть Sun его чем то обидел, пока он c ними работал:

Sun hired Martin Odersky to design Generics for Java, and the GenericJava compiler actually became the standard javac compiler shipped with the SDK as early as Java 1.2 (with the bits about generics disabled). Later on, a modified design of generics (with wildcards being the main new addition) was released with Java 1.5. Odersky, of course, went on to first design Funnel, then Scala, but his compiler still ships with Java 8.

Почему нет? Вот представьте Мартин такой толкает Сану идеи, вот так говорит надо, а они его заворачивают. В результате вообще его работа в свет не выходит ни в 1.2 ни в 1.3. А в 1.5 выходит нечто не совсем то, что он считал правильным (у меня нет никакой информации просто вот прямо сейчас родившаяся теория заговора). Ну и он такой обозлился и типа “щас я вам, [синонимы] штопаные, покажу язык, перед которым вы будете тем что вы есть — [синоним]” и понеслось… И язык создавался совсем не для того, для чего вы думаете, а чтобы уделать кого-то, и показать кто тут главный по языкам.

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

Вот замечательная Clojure. Родилась она изначально из замечательных идей Rich Hickey о “state, identity, value, time, types”, чувак задумался о том какие новые конструкции нужны для решения текущих и будущих проблем канкаренси и параллелизма. Изначально была проблема, идея, и решение, которое было в области Persistent Data Structures, STM, и так далее. Я абсолютно уверен что сначала появился Persistent Vector а потом язык Clojure. И то что горячо любимая некоторыми Clojure выглядит как Лисп и диалектом чего является, может быть лишь стечением обстоятельств. Вероятнее всего Лисп — был тем языком который Rich был готов реализовать максимально быстро, и который в принципе его устраивал. Сложись звезды по-другому, он мог взять или придумать другой язык. Я к тому что язык тут вообще вторичен.

Мне хочется обозначить важность целей создателей. Вот кто-то говорит Clojure это круто потому что я могу элегантно управлять стейтом, канкаренси там бла-бля. Нет! Это не язык программирования (Clojure как диалект Лиспа) позволяет вам делать это, а идеи Рича. Язык был добавлен к этим идеям как средство использования идей. Эти концепции, будучи реализованными в других языках, а для них не нужен особый “специальный” язык, программист получит все те же радости, за которые многие любят Clojure. Нужно четко осознавать что вам нравится в языке: концепции, которые легко переносятся в другие языки, как например те же PDS во всю тащат в JavaScript или вы претесь от самого языка (диалекта Лиспа в данном случае).

Я хочу сказать что создатели языков очень редко задаются целью создать язык с помощью которого программист будет более продуктивен. Зачастую они решают какие-то другие задачи и язык появляется как результат решения этих задач. Хороший пример JavaScript. Никто же не думает, что JavaScript сделали для того, чтобы вы повысили свою продуктивность и писали код мощнее, быстрее, качественнее. Или кто-то думает? (улыбаюсь).

От создателя: http://ift.tt/1L3a5lG. Вообще Brebdan Eich был приглашен в Mozilla, чтобы написать Scheme для браузера, и если бы этот изначальный план не был скорректирован то писали бы вы сейчас все на Scheme и рассказывали как это круто, можно, молодежно (простите, чуть не подавился). Почему вы сейчас пишете не на Scheme а на JavaScript — тоже никак не связанно с желанием сделать вас более продуктивными. Начиная с того, что Scheme не проканала потому что менеджмент хотел язык с синтаксисом похожим на выходящий в то же время из Sun язык Java. По массе причин вообще никак не связанным с программированием и продуктивностью вам на лопате вывалили язык сделанный в рекордно короткие сроки и сам автор даже в 2010 не понимает популярен ли он и как к этому относится, и причины популярности языка уж точно не связаны с тем что он прекрасно выполняет свое главное предназначение (в моем понимании) — увеличение производительности программиста.

Главная и единственная цель

Имея такое многообразие программистов, языков, и задач, все эти три параметра могут собраться абсолютно любым образом идеальным для данного случая, и как бы глупо говорить о “лучшем в мире языке программирования”, но я все же буду настаивать. Я все же вернусь к языку как к инструменту и буду говорить только за себя.

Язык можно адекватно оценить только с одной лишь целью — производство.

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

Правда в том (и возможно одна из причин столь разнообразных мнений о языках), что большинство из нас проявляет интерес к языкам с разнообразными целями (обучение, любопытство, увеличение ЧСВ), но не для повышения продуктивности на производстве. Зачастую мы просто не имеем производственной возможности поменять язык. Поэтому большую часть нашего времени самый важный — производственный интерес к языкам у нас отсутствует. Он в лучшем случае либо образовательный либо просто любопытство. Либо ты дизайнишь язык — но это тоже редкость.

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

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

В 1999 я работал в довольно большой конторе и тогда были популярны две холиворные темы, поскольку тем было всего две, а не как сейчас десятки, то рубились не на жизнь а насмерть. Темы эти естественно Windows vs Linux и C++ vs Java. Так вот пока люди срались в курилки за Java или против я стоял в стороне и тихо ржал (а иногда громко). Причина была проста: был у меня тогда проектик, ну скажем поисковик в Intranet, или типа того. И собрался я его писать сдуру на C по причинам которые молодежь сейчас приводит как аргумент (экосистема). Так вот следуя этому аргументу, на Java писать тогда было никак нельзя (ибо 1.2 по моему была еще только в бете) а экосистема вообще никакая. А на плюсах были какие-то типа полезные либы и фреймворки.

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

На творческую переработку того, что успелось сделать плюсами на Java у меня ушло в 10 раз меньше времени чем на оригинал (да я был конечно уже в теме, но во время написания оригинальной версии ресерча не было — благо были документы описывающие алгоритмы индексации и crawling от пары чуваков из Стенфорда — Сергей и Ларри их по-моему звали, все было просто и понятно, а их патентованый алгоритм ранжирования результатов поиска при наших объемах был не нужен, да и бесполезен. Те чуваки, кстати, как раз тогда только открыли компанию занимающуюся поиском в интернете).

Ну и вот стою я, значит в курилке, слушаю треп за темплейты, перегрузку и переопределение чего только можно, макросы-шмакросы, аллокаторы, производительность и множественное наследование (!). Гуру C++ нападают на маленьких студентов и вываливают на них всю мощь этого языка. Типа вы тут на своей Java и так не сможете, и вот так не сможете, и вот так неполучится (как в том анекдоте, сделай меня раком). А я чо то про себя ржу, и довольно улыбаюсь. Вертел я все эти ваши аллокаторы с темплейтами на своем множественном наследовании. Какая мне разница что вы там можете, и как вы можете, если я могу писать код в 10 раз быстрее вас, ну хорошо, опытный С++ программист у которого уже всё в крови и других частях тела будет писать быстрее, значит я буду быстрее его в 5 раз. Да хотя бы в 2-3 раза. Если я буду делать то же самое в 2 раза быстрее какое мне дело что у него там за темплейты. А ограничения? Да их нет — скорости нам хватало, памяти тоже, а ядра операционок мы писать не собирались.

Это безумный кайф, когда ты пишешь код свободно, почти не думая, не ожидая core dumped перед каждым запуском, когда фичи добавляются прямо на глазах, вот теперь мы так можем, а теперь еще так, то скажите мне пожалуйста, какая мне разница что у меня нет темплейтов, если я даже не скучал по ним? Продуктивность — вот главная цель программиста, который делает вещи, и единственная задача инструмента который он использует.

Таких ярких вспышек, когда ты вроде бы программировал как обычно, тяжело, как на стройке кирпичи таскают, а потом вдруг получил в руки чудесный инструмент, волшебную палочку, и кирпичи начали сами летать туда, куда ты хочешь, я испытал всего лишь пару за вот уже двадцать с лишним лет программирования за деньги. Про переход с С++ на Java я уже сказал. Примерно так же было, когда мы программировали десктопные аппликухи на Visual C++ 1.0, 1.5 или около того. Тогда сделать какой-нить диалог с тремя кнопками (которые еще не скоро начнут работать как надо) была большая задача, на денек так. Все эти макросы, и прочая хрень, которую я к счастью не помню. Чтобы, если что, понять как на самом деле твой код общается с виндой надо было с ума сойти продравшись через горы плюсовых библиотек.

И тут появляется Delphi. Кто то может посмеяться, но это была реальная революция (ну а тем кто опять не верит скажу, что архитектора Delphi, Anders Hejlsberg обалдевший Microsoft почти сразу переманил, и в том же Microsoft Anders был ведущим архитектором C#). Так вот, ты садишься за Delphi и делаешь что хочешь, хочешь пользовательский интерфейс, хочешь низкий уровень, все flow понятны, вызовы в операционку, можешь дописать сам чего хочешь (например поддержку новых контролов от Microsoft, не дожидаясь выхода новой версии Dephi). Понятно, и на расстоянии вытянутой руки ты видишь все вплоть до лайаута таблиц виртуальных методов в памяти (ну если вдруг надо), и самое главное, ты пишешь такой же софт, что писал раньше в 10, а то и больше раз быстрее. Ограничения? Да нет их. Вообще нет, ломануться куда нибудь в недра операционки проще чем раньше.

Из этих двух рассказов можно сделать вывод, что я за простоту. Нет это не так и с самой простотой не все так просто :) Загнул так, что вспомнил толк замечательного Rich Hickey, скажем просто “про простоту” — очень хорошая вещь. В контексте языков программирования я не за сложность или простоту языка, а за мощь компилятора и простоту его использования. Чем лучше он меня понимает (выразительность) и чем больше за меня делает — тем лучше, при исполнении того же самого, и единственного условия: любое усложнение языка/компилятора, должно увеличивать мою производительность а не уменьшать.

В JVM мире есть хорошие примеры. Да и сама Java — такой пример, если сравнивать Java с C++ скажем так пофичечно — Java проиграет, ну прям с разгромным счетом. Но есть внутри JVM сложная штука, которой нет в плюсах — Garbage Collector. Java без GC (хотя это было бы совсем не Java) не дала бы мне возможность писать код в разы быстрее. Как ты не упрощай дальше или не усложняй опять. Продуктивность программиста выросла в разы по большому счету благодаря сборке мусора (это когда компилятор и рантайм думают за вас, причем постоянно), а помех она не создает (разве что последнее время, в связи с дешевизной памяти и трендом писать на Java вообще всё, GC в некоторых случаях опять становится проблемой).

Генерики в 1.5, ничуть не усложнили использование Java, а лишь увеличили продуктивность. То же самое видимо с лямбдами (но честно скажу, что уже не застал). Ровно эта причина — увеличение продуктивности, заставила меня задуматься о более продуктивном языке чем Java в 2008, и поэтому я надеялся на Fantom. Его я хочу привести как пример языка, основной идеей которого была и есть увеличение продуктивности програмииста. Ребята которые сделали Fantom главной целью ставили продуктивность, сдесь и сейчас, в нашей реальной работе:

Fantom is designed as a practical programming language to make it easy and fun to get real work done. It is not an academic language to explore bleeding edge theories, but based on solid real world experience. During its design we set out to solve what we perceived were some real problems with Java and C#. Our background is heavily Java, but many of Java's problems are shared by C# and .NET also.

Если кто-нибудь заморочится почитать их форум, то четко это поймет. Именно эта ориентированность на продуктивность инженера привлекла меня в языке, и духовный опыт вовлечения в язык был хоть и не так силён, но похож на опыт перехода с плюсов на Java, когда код льется из под пальцев и ты понимаешь что Java не дала бы тебе делать то же самое с такой скоростью, когда ты чувствуешь больше свободы (а Fantom ничем не ограничивает Java программиста предоставляя удобный FFI и native classes, но дает еще и браузер как платформу), и ты понимаешь — вот она, та самая доза продуктивности, которую ты ищешь, находишь, но со временем тебе ее снова перестает хватать.

Fantom я хотел привести в пример потому что в нем нет генериков, и продуктивность, которую фантом дает программисту по сравнению с Java не связана с наличием или отсутствием генериков. Про отсутствие генериков в Фантоме я хочу сказать тому подавляющему классу программистов, которые ищут в языках фичи а не продуктивность. Неужели вы думаете, что авторы языка не смогли бы добавить в язык и генерики и черта лысого? Тем более что фантом прекрасный пример языка, который люди просто написали для себя, даже не так, для своего бизнеса. Для собственной продуктивности и продуктивности бизнеса в целом.

Не для нас (по большому счету), не для того чтобы померятся с другими языками, не для научных статей или непонятно для кого за зарплату. Просто для себя, чтобы быть еще более продуктивными программистами. Тут они абсолютно честны и для меня авторитетны. Генериков в фантоме не было потому что авторы сомневались в том, что их добавление в язык сделает пользователя языка более продуктивным, а не наоборот. Просто сомневались, и если ошиблись, то значит язык несколько потерял в той пользе, что он мог бы дать программисту (ключевое слово если).

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

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

В свое время я испытал шок. Будучи фанатом объектно-ориентированного программирования с 90-х годов, я всегда стремился писать максимально абстрактный (но все же достаточно разумный чтобы работал) код. Вообще писать объектно-ориентированный код в 90-х — это было бунтарство. Объектно-ориентированых программистов было не больше чем тех кто пишет исключительно в функциональном стиле.

Так вот, эти мои склонности к абстракциям были облиты холодным душем, когда в 2002 году я “нашел” (улыбнулся, поскольку перекликается с данной статьей) eclipse. Eclipse меня очаровал своей архитектурой и дизайном. Сейчас про eclipse к сожалению услышишь мало что хорошего, но это от тех кто никогда ее не видел внутри, а если и заглядывал, то не достачно чтобы рассмотреть.

Я же в жизни видел единицы столь качественно задизайненых платформ, но это и не удивительно — один из архитекторов Eclipse Platform — Erich Gamma. Он же один из банды четырех — авторов популярной в те времена книжки под названием Design Patterns. Не знаю на сколько она популярна сейчас, но на рубеже 2000 годов во всех конторах как правило гоняли по дизайн паттернам на собесах.

Ну так вот, гляжу я внутрь eclipse и не понимаю, что за ерунда. С одной стороны все выглядет красиво, качественно, я бы сказал восхитительно, с другой стороны — вот тут же можно было переиспользовать, и тут, и тут, вот тут вообще чуваки сознательно копи-пастят. Что-то думаю не то, они точно могли переиспользовать код, но не делают этого. Для ответа на вопрос мне надо было выйти за рамки своих детских программистских потребностей и посмотреть на мир глазами взрослых мужчин.

Любой факт (пере)использования чего либо, явно или неявно рожает зависимость на эту штуку. И там где для меня благо (эффективное переиспользование) и, как следствие, увеличение продуктивности, то для людей создающих платформу, на которой предполагается одновременный запуск сотен плагинов, различных версий и от десятка не знающих друг о друге вендоров любая лишняя зависимость — зло. Собственно это все добавило мне адекватности, напомнив об инь и янь, и о том что в нашей профессии ты всегда за что-либо платишь. И когда кто-нибудь показывает очередную решающую все проблемы фичу, или говорит про новый язык программирования с высокоуровневыми абстракциями, первый адекватный вопрос в ответ должен быть: “а что мы за это должны заплатить?”, если ответ “бесплатно”, тогда запишите себе вопрос: “хорошо, а когда мы за это будем платить?”

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

Подводя итог

Пара слов про экосистему. Экосистема безусловно важна, но аппелировать к экосистеме — это переводить вопрос в другую плоскость. С новыми технологиями и языками — это как на бирже, обыватель сливает депозит в 90% случаев. Ну не так жестоко как на бирже, но суть та-же. Когда толпа ломится покупать актив — весь рост там уже закончен и сливки (продуктивности в том числе) давно собраны. Я взял «акции» Java в 1999 (далеко не в первых рядах), в то время когда экосистемы была мягко скажем неразвита. Но тот рост продуктивности для себя и команд, и безумный рост акций Java в следующие десять лет позволяет мне скромно улыбаться когда программисты начинают аппелировать к экосистеме. Это то же самое когда вы начинаете говорить что покупать акции Apple не стоит — потому что они очень дешевы.

Ха-ха. Вот как раз покупать акции когда они дороги не стоит, поскольку потенциал роста там уже исчерпан. Все что вы можете купить — это относительно долгую или не долгую стабильность. Хотя для того чтобы купить правильный актив — нужно действительно понимать его ценность (несмотря на низкую цену), и быть уверенным в том, что покупка начнет приносить вам дивиденды сразу, а не в далеком будущем. Точно так же мы выросли на «акциях» eclipse с 2002 года, когда у eclipse был сумасшедший потенциал к росту, и которые подросли до максимума году к 2008. С того времени я и пытался выйти из акций Java и eclipse в другие технологии, ибо потенциал роста исчерпан, а раз так — надо выходить. Языки и технологии дают вам конкурентное преимущество, а если вы сидите на тех же самых языках и технологиях, что и половина программистов вокруг — о каком технологическом преимуществе может идти речь?

Возвращаясь к выбору правильного языка. Мне не важны фичи языка, их может быть сколь угодно много или сколь угодно мало. Мне интересно насколько язык увеличит продуктивность меня и команды, сейчас и в будущем, для известных и неизвестных задач. Вот и все. Все остальное не важно. Как часть продуктивности, язык должен разгрузить мне голову. Я не должен думать про язык, как мне приходится на Scala или Rust. Я не хочу держать в голове кучу вещей которые можно не держать как в языках с динамической типизацией. Увидев чужой код я должен сразу понимать что тут делается а не заниматься долгими исследованиями всего, что есть вокруг, как в примере со Scala из части 2. Не потому что не могу, а потому что я не вижу в этом смысла, я не вижу как все это сделает меня более продуктивным, и соответственно не верю.

Все же в третьей части, кому она инетересна, я напишу о том, что такой язык я нашел, и раз уж интрига убита — это действительно Nim. Но я очень хочу чтобы была понятна позиция с которой я подхожу к этому выбору. Я хочу мощи. Мощи компилятора, который будет делать за меня многое, и которым в то же время просто управлять. Да и требования ровно такие, как и к автомобилю. Я хочу мощный, надежный, комфортный автомобиль, которым просто управлять и который рвет всех со светофора. Ну и, желательно с доводчиками дверей, и прочими мелкими радостями добавляющими комфорта, заставляющими меньше думать об автомобиле и меньше делать ненужных движений. Я хочу комфортного и продуктивного использования. Те кто хочет погоняться по пустыням и болотам — это не ко мне, таких людей прет от желаний отличных от желания продуктивно работать над созданием программного обеспечения.

Вам знакомо чувство, когда вы выходите из унылого Reno Logan, на котором таксист вез вас до стоянки, долго втапливая педаль в пол чтобы кого-то обогнать, и садитесь за руль современного автомобиля с тремя-четырьмя сотнями кобыл под капотом, который вас разгоняет до той же сотни за 5 секунд? Это прекрасно — чувствовать всю мощь железных технологий под капотом, мощь, которой вы управляете по собственному желанию, и вся эта мощь делает то, что вы хотите, и так как вы хотите. А еще это называется свобода.

Пока,
Платов

This entry passed through the Full-Text RSS service - if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.