[Перевод] Про Swift, и почему мои большие проекты будут на Objectve-C еще какое-то (возможно долгое) время

От переводчика: C пятницей, дорогие хабровчане! Хочу поделиться сегодня с вами переводом стататьи с небольшого блога о опыте работы с языком Swift. Вряд-ли она претендует на лавры серьезного и скурпулезного анализа, но думаю будет интересна всем, кто задумывался «а не пора ли оправить на свалку истории этот Objective-C.

Когда Apple представила нам Swift, это было круто! Наконец то мы получили next-gen (т. е. модный-скриптоподобный) язык для разработки под яблочные девайсы (но без поддержки приватных членов класса, хм....). Теперь этот [языкДинозавр квадратноскобочный] может отправиться в музей, а мы начнем тыкать эти новые блестящие фичи языка. Безусловно наивно предполагать что язык, которому менее года, будет без тараканов: очевидное некоторое время нужно дать ему на избавление от детских болячек. Именно поэтому я не бросился переписывать все мои проекты на Swift сразу после анонса.

5d2304cf756b4f3d815d8ca0f309fe3e.jpg
Заметили, что птица падает вниз?

Через год после выпуска, я наконец решил выучить язык. Для этого я начал писать игрушку про самую ужасную вещь в мире (в мире Windows 3.1, окей) — монстра из игру SkiFree. Вы можете прочесть об этом здесь

Дисклеймер: я пишу о годовалом свифте. Уверен ребята из Apple починят все эти проблемы, и язык станет очень элегантным инструментом. Ну либо неповоротливым бегемотом вслед за XCode 7.

Вернемся к Swift. Одна ночь с книгой „The swift programming language“ и я готов к свершениям. Язык очаровал меня простотой и прозрачностью конструкций и скрытой мощью, позволяющей писать безопасный код (и да, они добавили приватные члены классов). Я начал писать SripteKit игрушку и…

image

Это что серьезно? Мой проект на Objective-C в 60 тысяч строк собирается всего лишь в два раза дольше ем мой 600-строчный Hello World на свифте. Внезапно мне вспомнились те славные времена (вообще-то всего несколько месяцев назад это было), когда я работал над огромным проектом, и картинка ниже прекрасно описывает некоторые мои рабочие дни:

8631877ea4074035a361ddbf961a1904.png

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

В конце концов человек может привыкнуть к чему угодно. Но компилятор снова меня поразил:

eadda9fd57284388bd16db4c882b1df1.png

Эээ… Не может сложить два float'а… хорошо…

Для тех из вас, кто уже точит свои ножи, чтобы отучить это обезьяну-кодера от использования захардкоженых значений и использования одновременно float и double типо в коде хочу сказать: во первых, CGFloat ко мне пришли из UIKit, а double из стороннего кода. Так что это не слишком экзотическая ситуация, когда вам придется миксовать эти два типа. А вынос захардкоженых значений в константы помог бы коду стать более толковым, но едва ли это спасет от удивительного кульбита, которым нас порадовал компилятор. Кончено этот мерзавец может сложить два float'а — дело то в том, что он укрывает от меня настоящую проблему!

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

b9c1e148f4d14d519556690eb7ac5821.jpg

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

090ba4a806e04164b737d2c98f422d11.jpg

Черный ритуал надо кодом, и наконец он заработал. Вот зачиненный вариант.

2579983baaca4b3e9b227ee948f8cb10.png

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

Еще одна проблема, связанная с первой — это низкая скорость статического анализа в сравнении с Objective-C. Было время, когда я отключал подсветку синтаксических ошибок в ХСode в реальном времени, так как я писал код гораздо быстрее, чем он успевал его анализировать (человек против машины: 1:0, хо-хо). Подлагивающие подсказки только раздражали меня. С покупкой нового мака анализ стал почти мгновенным — и я с огромным удовольствием стал использовать эту фичу. Но со Swift я снова встретил ту же проблему (2:1. человек побеждает).

Ну и наконец жемчужина моей коллекции:

ddf44029e2cb438b84a2083a0d5fe207.jpg

Я многое повидал в жизни…
Я видел оптимизации компилятора, рушившие производительность из-за вставленного 'if (0) {… }' выражения
Я видел чудовищные баги, связанные с пропущенным 'volatile' ключевым словом
Я видел, какие жуткие разрушения может привнести неопределенное поведение языка

Но никогда я еще не видел, что бы компилятор жаловался на свою тяжелую жизнь (как и я:) )

Это сообщение было бы очень полезным, если бы оно было warning'ом. Но это критическая ошибка. Так что да, вам придется упрощать это выражение. Я бы понял эту ситуацию, если бы эта ошибка вылезла для очень длинной конструкции, но она была длинной менее 120 символов. Для некоторых разработчиков такая ситуация может показаться нормальной, но я был взрашен с волками языков C/C++ и x86 ассемблером. Так что для меня это выглядит странно.

Что же в сухом остатке? Мы получили язык, похожий на модные Python/Go/Ruby. Но есть ли причина начинать большой проект на нем?

Дженерики? Да, это очень хорошо, но в Objective-C есть поддержка дженериков (да, уродливая, но есть). А ребята из Go вообще говорят, что им без дженериков нормально.

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

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

Так что эпл. Ну серьезно, выглядит так, будто вы создали язык только потому, что над вам смеялись из-за квадратных скобочек (»Пишите код, будто на разговорном английском", хехех) и YES/NO в Boolean. А какова цена? Теперь у нас язык с тормознутой сборкой и, порой, странным поведением компилятора.

Итак старик сказал все, что хотел. Но вы, любители модных-скриптоподобных языков, не должны принимать мои слова слишком близко к сердцу: по сути Swift это хороший язык с неплохим дизайном. Все пробелмы, что я описал, могут быть зачинены без существенных изменений в языке, так что однажды они уйдут. Свифт — прекрасный язык для написания Hello World, но крупные проекты я пока не советую начинать на нем.

© Habrahabr.ru