Nauka szybkiego programowania: czy jest gotowa na Prime Time?
Opublikowany: 2022-03-11Wprowadzenie przez Apple w czerwcu Swift, nowego języka programowania do pisania aplikacji na iOS, wywołało wiele szumu i ekscytacji w społeczności programistów iOS.
Od momentu premiery wielu programistów iOS zmagało się z pytaniem, czy, jak i kiedy przejść z Objective-C na Swift. Odpowiedź na to pytanie będzie oczywiście inna dla każdego zespołu i każdego projektu.
Istnieje wiele artykułów, które można przeczytać, opisujących wiele zalet Swift. Dlatego zamiast powtarzać te same punkty, w tym artykule skupimy się na niektórych problemach, które warto rozważyć przed nauką tworzenia aplikacji za pomocą Swift.
Ale najpierw cofnijmy nieco zegar…
Przed Swiftem: użyjesz celu-C i spodoba ci się…
Był rok 2010. iPhone nie miał jeszcze 3 lat, a możliwość pisania natywnych aplikacji dla iPhone'a istniała dopiero od około 2 lat. 8 kwietnia tego roku Apple ogłosił wersję iPhone OS. iPhone OS (to było, zanim zmienił nazwę na iOS) zawierał takie kuszące nowe funkcje, jak wielozadaniowość, szybkie przełączanie aplikacji i usługi w tle. Zrozumiałe jest, że programiści iPhone'a byli chętni do zdobycia nowego SDK i rozpoczęcia zabawy z tymi wszystkimi ekscytującymi nowymi funkcjami.
Ale iPhone OS 4 SDK zawierał nieoczekiwaną bombę. Ta bomba nie znajdowała się w oprogramowaniu, była w umowie użytkowania. W przypadku iPhone OS 4 SDK sekcja 3.3.1 Umowy programisty została zaktualizowana i zawiera następujący problematyczny język:
Aplikacje muszą być pierwotnie napisane w Objective-C, C, C++ … i tylko kod napisany w C, C++ i Objective-C może skompilować i bezpośrednio połączyć się z Udokumentowanymi interfejsami API.
– Sekcja 3.3.1 umowy deweloperskiej iPhone OS 4 SDK
Nie trzeba dodawać, że to nowe ograniczenie zaskoczyło wielu programistów. Oficjalnym powodem zmiany, podanym przez samego Steve'a Jobsa, było uniemożliwienie korzystania z narzędzi międzyplatformowych, takich jak niedawno ogłoszony Flash CS5. Cytowano, że Jobs powiedział, że „warstwy pośrednie między platformą a deweloperem ostatecznie wytwarzają [sic] aplikacje niespełniające standardów”. Ale fakt, że podejście Apple do zwalczania tych „warstw pośrednich” polegało na ograniczeniu języków programowania, które można wykorzystać do pisania aplikacji na iPhone'a, ujawnił coś więcej w sposobie myślenia Apple: Objective-C powinien być wystarczająco dobry dla każdego.
Można by wybaczyć, że zgadza się z tym stwierdzeniem, ponieważ Objective-C dwa lata z rzędu zdobył nagrodę Tiobe Index „Język programowania roku”. Ale rzeczywistość była taka, że popularność Objective-C była funkcją rozwijającego się ekosystemu aplikacji, a nie odwrotnie. Nawet w 2010 roku wiele osób było już niezadowolonych z Objective-C, w wyniku czego pojawiały się już alternatywne sposoby pisania aplikacji na iPhone'a w innych językach programowania.
Ostatecznie, pod naciskiem społeczności programistów, Apple cofnęło te zmiany w sekcji 3.3.1 Umowy programistycznej SDK zaledwie pięć miesięcy później. Wiadomość była jednak jasna: jeśli chcesz pisać aplikacje na iPhone'a, prawdopodobnie powinieneś używać Objective-C.
… albo może nie. Wprowadź nowy język iOS Swift.
Przewiń do przodu o 4 lata od tego incydentu do czerwca 2014 r., Kiedy Apple przedstawił programistom swój nowy język, Swift. Jeśli komunikat sprzed 4 lat mówił, że Apple jest całkowicie zadowolony z Objective-C, to komunikat wysłany przez wprowadzenie Swifta brzmiał, że Apple jest w końcu gotowy do przyznania się do prawdy. Objective-C niekoniecznie musi być najlepszym językiem do pisania aplikacji mobilnych.
Wiele powiedziano o tym, że Swift jest bardziej „nowoczesnym” językiem niż Objective-C. Jeśli interesuje Cię, jak nauczyć się języka programowania Swift, możesz zapoznać się z przewodnikiem dotyczącym przejścia z Objective-C na Swift.
Należy jednak zauważyć, że istnieją dwie ważne różnice między językami Objective-C i Swift:
- Swift nie jest ścisłym nadzbiorem języka C.
- Swift jest wpisywany statycznie, a nie dynamicznie.
Brak ścisłego nadzbioru języka C oznacza, że Swift może swobodnie korzystać z konstrukcji składni, które w innym przypadku byłyby niedozwolone. Umożliwia to np. implementację operatorów niestandardowych w Swift.
Bycie napisanym statycznie oznacza, że Swift może korzystać z wielu najnowszych osiągnięć w systemach pisma, zapoczątkowanych przez języki takie jak Haskell.
Pomimo tego, że był rozwijany przez 4 lata, zanim został ujawniony publicznie, Swift jest wciąż młodym językiem programowania, więc ma wiele zastrzeżeń.
Kompatybilność z Objective-C
iOS ma wspólne dziedzictwo z OS X, który z kolei czerpie swoją historię z systemu operacyjnego NeXTSTEP wydanego po raz pierwszy w 1989 roku. NeXTSTEP został pierwotnie napisany w dużej mierze w Objective-C, a wiele podstawowych bibliotek w OS X i iOS śledzi ich korzenie droga powrotna do tych oryginalnych realizacji. (Nawiasem mówiąc, stąd pochodzi wszechobecny przedrostek „NS” występujący w klasach podstawowych, takich jak NSString
.) Chociaż Swift teoretycznie mógłby istnieć przy braku tych podstawowych bibliotek, w rzeczywistości każdy program Swift, który możesz napisać w najbliższej przyszłości będzie musiał połączyć się z Objective-C.
Trzeba przyznać, że twórcy Swift wykonali fantastyczną robotę, czyniąc interakcję z istniejącymi bibliotekami Objective-C tak bezbolesną, jak to tylko możliwe. Nie oznacza to jednak, że proces jest całkowicie bezbolesny. Firma Apple udostępniła pomocny przewodnik wyjaśniający, jak wywoływać kod Objective-C ze Swift i odwrotnie, ale istnieją pewne ważne niedopasowania impedancji, o których należy pamiętać.
Być może najbardziej oczywista niezgodność dotyczy plików nagłówkowych. Objective-C, ze względu na swoje korzenie C, nadal wymaga zadeklarowania funkcji przed wywołaniem. Podczas wołania do biblioteki deklaracje te zostaną znalezione w plikach nagłówkowych biblioteki. Swift nie używa jednak plików nagłówkowych. Tak więc, jeśli chcesz wywołać kod Swift z Objective-C, musisz najpierw utworzyć „nagłówek pomostowy”. Chociaż koncepcyjnie może to nie wydawać się skomplikowane, w praktyce może to być dość trudne zadanie.
Kolejny zestaw komplikacji w połączeniu między Swiftem a Objective-C wynika z nieodłącznych różnic w ich systemach typów. Swift, wzorując się na innych współczesnych językach, zlikwidował pojęcie nil
. W jego miejsce znajdują się opcjonalne typy Swifta. Na przykład metoda, która otwiera plik tylko wtedy, gdy już istnieje, miałaby typ zwracany File?
(zamiast tylko File
) w Swift. Śledząc wszystkie miejsca, w których typy są opcjonalne, kompilator Swift może skutecznie uniemożliwić napotkanie przerażającego „Błądu wskaźnika zerowego”. To znaczy, oczywiście, chyba że wywołujesz Cel-C. Ponieważ cel-C nie daje takich gwarancji dotyczących nie zwracania nil
, Swift ma specjalną kategorię typów o nazwie niejawnie nieopakowane opcje , które są używane podczas wywoływania kodu celu-C. Te typy mogą być traktowane jako opcjonalne w języku Swift, wraz z całym towarzyszącym narzutem wymaganym do sprawdzania istnienia. Alternatywnie mogą być używane tak samo, jak każdy nieopcjonalny typ, ale jeśli Objective-C zwróci nil
, skończy się błędem w czasie wykonywania, więc tracisz niektóre gwarancje bezpieczeństwa Swift w czasie kompilacji.
Wreszcie, nieco bardziej subtelna niezgodność do rozważenia podczas programowania między Swift i Objective-C ma związek z tym, jak obiekty i klasy są tworzone pod przykrywką w tych dwóch językach. Objective-C, ze względu na swoją dynamiczną naturę, wykorzystuje dynamiczną wysyłkę do wywoływania metod na obiektach (poprzez objc_msgSend
). Swift z pewnością może używać dynamicznej wysyłki, ale ponieważ jest statycznie typowany, ma również możliwość użycia vtable
do przechowywania wskaźników funkcji dla każdej metody. Który z tych dwóch mechanizmów, z których korzysta Swift, zależy od kilku czynników. Plane Old Swift Objects użyje mechanizmu vtable
, chyba że klasa lub metody w klasie są opisane przy użyciu atrybutu @objc
Swift. Klasy Swift, które dziedziczą z klas Objective-C, będą używać dynamicznego wysyłania dla metod dziedziczonych, ale nie dla żadnych nowych metod wprowadzonych przez podklasę (chociaż ponownie można wymusić użycie dynamicznego wysyłania za pomocą atrybutu @objc
). Niezależnie od tego kod Swift zawsze będzie mógł współpracować z klasami Swift, ale kod Objective-C może wykorzystywać tylko obiekty i metody Swift, które zostały odpowiednio opisane.

Szybszy niż Cel-C?
Kiedy Apple wprowadziło swoją premierę, jedną z zalet Swift, która została szczególnie podkreślona, była jego szybkość. Jest to zrozumiałe, jeśli weźmie się pod uwagę, że często podawanym powodem niechęci Apple do przejścia z Objective-C na język wyższego poziomu był fakt, że Objective-C, będąc zasadniczo rozszerzeniem C, był w stanie tworzyć znacznie szybsze i wydajniejsze programy niż coś takiego jak Python czy Ruby. Mimo to Objective-C nie jest statkiem rakietowym, jeśli chodzi o absolutne osiągi, a wiele z tego można przypisać dynamicznemu typowaniu. Tak więc, gdy Swift przyjmuje statyczny system typów, można by oczekiwać, że Swift powinien być co najmniej tak szybki lub szybszy niż Objective-C.
Oczywiście, jak mówi przysłowie: „Istnieją trzy rodzaje kłamstw: kłamstwa, cholerne kłamstwa i wzorce”. (Lub coś takiego…) Z pewnością istnieje wiele powodów, dla których język Swift może działać szybciej. Niestety, wydaje się, że sposób, w jaki Swift wykorzystuje technikę ARC (Automatic Reference Counting) firmy Apple do zarządzania pamięcią, czasami powoduje, że kompilator Swift generuje znacznie wolniejsze programy, zwłaszcza przy niższych ustawieniach optymalizacji (takich jak te, których można używać podczas programowania). Dobrą wiadomością jest to, że wydaje się, że ulepszenia Swift stale rozwiązują ten problem, dlatego jest prawdopodobne, że w niedalekiej przyszłości Swift będzie generował pliki wykonywalne co najmniej tak szybko lub szybciej niż Cel-C.
Jest jednak jeszcze jedno zastrzeżenie dotyczące szybkości Swifta. Cały sens Swift polega na tym, że programiści nie będą pisać tego samego kodu, który pisaliby w Objective-C. Co to oznacza dla wydajności? Cóż, z pewnością oznacza to, że porównywanie wydajności między Swift i Objective-C jest bardziej skomplikowane, niż mogą to ujawnić proste testy porównawcze. Oznacza to również, że porównanie bezwzględnej wydajności wygenerowanych plików wykonywalnych w czasie wykonywania mówi tylko połowę.
Każdy chce szybkich programów, ale często szybkość rozwoju jest równie ważna, jeśli nie ważniejsza. Język, który jest bardziej ekspresyjny, zdolny wykonać więcej pracy w mniejszej liczbie linijek kodu, może być pod tym względem ogromną korzyścią. Z drugiej strony, pracując w języku kompilowanym, w którym cykl edycji-kompilacji-uruchamiania-debugowania zajmuje dużą część dnia programisty, powolny kompilator może naprawdę obniżyć produktywność. Chociaż dowody są głównie anegdotyczne, wydaje się, że kompilator Swift jest obecnie wystarczająco wolny, aby być denerwującym, zwłaszcza podczas pracy z kodem, który wykorzystuje zaawansowany system typów Swift. Jedna grupa uznała nawet, że szybkość kompilacji jest wystarczająco problematyczna, aby zmotywować do powrotu do celu C.
Kompilator
Mówiąc o kompilatorze Swift, sam jest źródłem jeszcze większych zastrzeżeń, gdy rozważamy przejście na nowy język Swift. Oprócz szybkości kompilacji, ponieważ Swift wyłonił się z niewielkiej kadry programistów pracujących z nim w Apple i został uwolniony masowo, kompilator zaczął wykazywać pęknięcia pod wpływem stresu. Istnieje nawet całe repozytorium GitHub poświęcone zbieraniu przykładów kodu, który spowoduje awarię kompilatora Swift.
Pojawia się też pytanie, jak zmieni się kompilator Swift. Innym projektem na GitHub jest zbieranie spekulacji i analiz społeczności na temat zmian, które mogą być w przygotowaniu dla Swift. Na przykład operatory niestandardowe mogą znacznie obciążać parser. Początkowo operatorzy niestandardowy w Swift nie mogli używać znaku zapytania (?). Chociaż zostało to naprawione w najnowszej wersji Swift, żądania nadal napływają od rosnącej społeczności programistów Swift, aby uzyskać jeszcze większą elastyczność w zakresie tego, co można uznać za prawidłowy operator niestandardowy.
Za każdym razem, gdy słyszysz, że parser dla języka jest w ruchu, powinien dać ci pauzę. Parser języka jest sercem i duszą języka programowania. Zanim jakakolwiek semantyka języka będzie mogła zostać zastosowana w celu nadania znaczenia kodowi, to właśnie parser określa, co jest, a co nie jest prawidłowym kodem. To zachęcające, że Apple obiecał zapewnić pewien poziom kompatybilności środowiska uruchomieniowego dla Swift. To jednak niekoniecznie gwarantuje, że kod Swift będzie działał bez ponownej kompilacji dla każdej nowej wersji Xcode i/lub iOS. Nie gwarantuje to również, że nie będziesz musiał przepisywać części kodu Swift, aby zachować zgodność z przyszłymi wydaniami Swift. Ale znowu, zobowiązanie Apple do uczynienia tego procesu tak bezbolesnym, jak to tylko możliwe, jest przynajmniej małą pociechą.
Społeczność
Niektóre z najgorszych języków programowania, jakie kiedykolwiek stworzono (które pozostaną bezimienne) były wspierane długo po tym, jak zdrowy rozsądek mówi, że powinny one zostać zepchnięte na śmietnik nieudanej technologii wyłącznie dzięki sile ich społeczności. Jednocześnie zbiór naprawdę fajnych języków programowania, które nie zadomowiły się z powodu braku społeczności, są zbyt liczne, aby je zliczyć. Silne społeczności tworzą samouczki, odpowiadają na pytania dotyczące Stack Overflow, spędzają czas online lub osobiście na konferencjach, dzieląc się historiami, wskazówkami i sztuczkami oraz piszą i udostępniają sobie nawzajem przydatne biblioteki. Wybierając język używany w projekcie, społeczność jest zdecydowanie czymś do rozważenia.
Niestety, społeczność iOS/Objective-C nie ma najlepszej reputacji jako przyjaznej i gościnnej. To się stopniowo zmienia, a open source odgrywa coraz ważniejszą rolę w rozwoju Objective-C. Mimo to na tym wczesnym etapie trudno jest powiedzieć, jak będzie wyglądać społeczność Swiftów w przyszłości. Czy będzie się składać głównie z wyspiarskich programistów pracujących tylko na oficjalnych interfejsach Apple API i własnych prywatnych kolekcjach kodu? A może będzie to dynamiczna społeczność grup dzielących się wskazówkami, sztuczkami i przydatnymi bibliotekami?
Innym aspektem roli społeczności jest rola samych programistów Swift. Ogólny trend w programowaniu polega na odchodzeniu od własnych języków programowania i platform na rzecz rozwiązań open source. Rozwój Open Source, zwłaszcza na poziomie języków programowania i środowisk wykonawczych, może być prawdziwą zaletą. Podczas gdy programiści Swift wielokrotnie stwierdzili, że ich intencją jest całkowite otwarcie kodu źródłowego języka i środowiska uruchomieniowego Swift, to jeszcze się nie wydarzyło, więc ostrożność jest uzasadniona.
To powiedziawszy, programiści stojący za Swiftem to jedni z tych samych programistów, którzy stoją za długotrwałym projektem LLVM. LLVM nie jest idealną analogią, ponieważ rozpoczął życie na otwartej przestrzeni jako projekt z University of Illinois, Urbana-Champaign. Ale trzeba przyznać, że główni programiści pozostali bardzo otwarci i angażowali się w społeczność, nawet po tym, jak większość z nich przeszła do pracy dla Apple. Całkowicie rozsądne jest oczekiwanie, że język Swift będzie nadal rozwijany (głównie) w sposób otwarty, choć to, czy poprawki i sugestie dotyczące funkcji od społeczności kiedykolwiek trafią do tego języka, okaże się, czy nie.
Czy powinienem nauczyć się szybkiego?
Oczywiście nie ma tutaj odpowiedzi „jeden rozmiar dla wszystkich”. Jak zawsze, wybór odpowiedniego narzędzia do pracy wymaga dokładnej znajomości wszystkich szczegółów danego projektu. Z pewnością w tym momencie Objective-C pozostaje „bezpiecznym” wyborem dla rozwoju iOS, ale Swift jest zdecydowanie wart rozważenia.
Jednak najważniejszą zmianą, jaką Swift wnosi do rozwoju iOS, jest to, że wielu programistów po raz pierwszy zada sobie pytanie: „Jakiego języka powinienem używać?” Biorąc pod uwagę historię Apple, Objective-C i platformy iOS, sama ta zmiana jest dość ekscytująca, zwłaszcza biorąc pod uwagę, że wybór nie jest binarny. Chociaż Apple jasno określiło swoje preferencje, społeczność programistów iOS od lat ciężko pracuje, dostarczając jeszcze więcej możliwych odpowiedzi na to pytanie.