Я вступил в дискуссию с коллегой по теме Java против JavaScript, которая с самого начала является проблемной. Затем он упомянул, какой замечательный React Native, я решил, что мне нужно изучить его и, возможно, найти некоторые идеи для Codename One …
Там есть несколько хороших идей, но ни одна из них не является революционной или исключительной, и большинство из них — довольно старые новости для разработчиков Codename One, работающих на Java 8.
Одна вещь, которая мне понравилась, заключалась в том, насколько коротким был демонстрационный код React , поэтому я перенес его на Codename One и получил примерно такой же объем кода и, возможно, лучший / более простой код!
Посмотрите полный список в конце статьи или в проекте github здесь , но давайте сначала рассмотрим, почему код Java «лучше».
Синхронное выполнение
Поклонники JavaScript ненавидят это, но все же факт, что синхронный код проще читать, отслеживать и отлаживать. Например, это версия кода React Native, которая извлекает данные:
|
01
02
03
04
05
06
07
08
09
10
11
|
fetchData: function() { fetch(REQUEST_URL) .then((response) => response.json()) .then((responseData) => { this.setState({ dataSource: this.state.dataSource.cloneWithRows(responseData.movies), loaded: true, }); }) .done(); }, |
У меня более 20 лет профессионального опыта программирования, и это все еще трудно понять. Видимо, если done() опущена, вы не получите никакой обработки ошибок?
Это странно и подвержено ошибкам. Я чувствую, что за этим скрывается большая часть кода, что делает краткость более запутанной, чем упрощенной (вроде как после политической дискуссии в Twitter). Для меня наш код намного проще:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
|
react.add(BorderLayout.CENTER, new InfiniteContainer() { public Component[] fetchComponents(int index, int amount) { try { Collection data = (Collection)ConnectionRequest.fetchJSON(REQUEST_URL).get("movies"); Component[] response = new Component[data.size()]; int offset = 0; for(Object movie : data) { response[offset] = createMovieEntry(Result.fromContent((Map)movie)); offset++; } return response; } catch(IOException err) { Dialog.show("Error", "Error during connection: " + err, "OK", null); } return null; }}); |
Обратите внимание, что это не является точным эквивалентом приведенного выше кода, так как мы также создаем компоненты, добавляем их в пользовательский интерфейс и обрабатываем возникающую ошибку! более справедливое сравнение будет:
|
1
2
3
4
5
6
|
try { Collection data = (Collection)ConnectionRequest.fetchJSON(REQUEST_URL).get("movies"); ...} catch(IOException err) { ...} |
Это фактически одна строка кода, которая может быть даже короче, после чего у нас будет результат … Нет потока, нет обратного вызова!
Разработчики часто ненавидят функцию проверенных исключений Java, и я должен согласиться с тем, что они иногда бывают болезненными (например, InterruptedException глупо), но это прекрасный пример того, почему проверенные исключения имеют значение. Мы ДОЛЖНЫ правильно обрабатывать ошибки, и мы не можем просто игнорировать их, пока наш код не достигнет производства с этим прекрасным комментарием «TODO», который никто не потрудился прочитать.
Один язык — меньше кода
Листинги кажутся примерно одинаковыми по размеру, но вы заметите, что реагирующий код игнорирует специфический для собственной платформы код при работе с кодом JavaScript. Наш список включает в себя все, никакой дополнительный код не требуется, и никаких дополнительных шаблонов, проектов и т. Д.
React Native делает это еще дальше, смешивая теги с кодом JavaScript, эффективно смешивая декларативный код в обычный поток. Да, это сокращает код, но также устраняет огромную часть ценности декларативного программирования, которое заключается в разделении обязанностей.
Обновить == Применить изменения кода
React Native может быть отлажен путем перезагрузки, что поможет при работе с ужасным эмулятором Android. К счастью, Codename One не нуждается в этом эмуляторе, вам также не нужно перезапускать свое приложение для перезагрузки скомпилированных изменений… Например, в NetBeans просто используйте «Apply Code Changes» в отладчике, и ваши изменения мгновенно отражаются в работающем приложении.
Языки сценариев проблематичны «на устройстве»
Это не совсем специфическая «React Native», она относится ко всем инструментам, упаковывающим JavaScript в комплекте приложений. Языки сценариев отлично подходят для Интернета, они похожи на «клейкую ленту». Покажите мне хакера, который не любит клейкую ленту!
Соблазн поставить приложение, созданное с помощью такой клейкой ленты, велик, но в отличие от Интернета, где вы можете просто исправить эту «странную неопределенную» ошибку в производственном процессе, установив новое обновление. С приложениями вам нужно пройти процедуру одобрения Apple … Это означает, что производственные ошибки остаются, пока вы наблюдаете падение рейтинга.
Да, модульные тесты, lint и многие другие решения должны улавливать эти вещи, но когда вы используете современную среду IDE и она обнаруживает потенциальный нулевой вывод благодаря строгому синтаксису языка, это довольно удивительно!
Например, отличный пример для JavaScripts по упрощению проблем был бы в коде, как это:
|
1
2
3
4
5
6
7
|
function reduce(var a) { if(...) { a = a - 1; } else { a = a + 1; }} |
Если бы это был код Java, мы могли бы точно сказать, что здесь произойдет … В JavaScript это не совсем так! Предположим, что из-за ошибки a каким-то образом была строка, равная "11" если условие истинно (что может иметь место во всех тестовых случаях), это будет действовать как число. Например, станет "10" . Но в производстве, если условие по какой-либо причине становится ложным, a станет "111" . Если a представляет что-то ценное (например, долг, кредит и т. Д.), Приложение с этой ошибкой в магазине может быть очень болезненным.
Среда
React native использует собственные среды разработки, а это значит, что для разработки под iOS требуется Mac. Это также означает, что вы выполняете часть работы в Android IDE, часть — в Xcode, а JavaScript — с помощью текстового редактора. Мне удивительно, что разработчики готовы отбросить 30-летнюю эволюцию IDE для какой-нибудь синтаксической конфетки ??? Неужели мы получили травму от «Затмения»? Сегодняшние IDE потрясающие, и тот факт, что вы можете отслеживать / отлаживать весь код с помощью одной IDE, неоценим. У нас, как у команды, есть возможность мгновенно увидеть, кто что использовал и для какой цели поразителен, я не могу понять, как нечто подобное может использовать команда из более чем 2 человек, особенно в распределенной рабочей силе.
Что мне понравилось в JavaScript
Одна вещь, которая мне действительно нравится в работе с JavaScript, — это простота работы с JSON, хотя в приведенном ниже коде я значительно уменьшил его почти до того же размера, но он все еще не так элегантен. Я до сих пор не фанат утилитного типа или языков сценариев, но мне бы очень хотелось добавить что-то вроде объектов свойств в Codename One и улучшить интегрированный синтаксический анализ.
Последнее слово
Одна из проблем, с которыми я сталкиваюсь при кратком программировании, состоит в том, что люди используют его для сокрытия основных понятий, поэтому слишком многое происходит «негласно». Это делает краткий код таким же легким для прочтения, как и твит, к сожалению, если вам нужно выразить даже умеренно сложную идею, Twitter просто не обрезает его, и это большая проблема с некоторыми из этих API.
У React native есть свои поклонники, в конце концов, он, вероятно, лучше, чем PhoneGap, у которого есть свой набор ограничений. Но это все еще ограниченная концепция, стоящая на цыпочках скриптовой инфраструктуры. Он не имеет реального преимущества по сравнению с Codename One и имеет некоторые очевидные потенциальные проблемы.
Листинг Java
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
|
public class ReactDemo { private static final String REQUEST_URL = "https://raw.githubusercontent.com/facebook/react-native/master/docs/MoviesExample.json"; private Form current; private EncodedImage placeholder; public void init(Object context) { UIManager.initFirstTheme("/theme"); } public void start() { if(current != null){ current.show(); return; } placeholder = EncodedImage.createFromImage(Image.createImage(53, 81, 0), false); Form react = new Form("React Demo", new BorderLayout()); react.add(BorderLayout.CENTER, new InfiniteContainer() { public Component[] fetchComponents(int index, int amount) { try { Collection data = (Collection)ConnectionRequest.fetchJSON(REQUEST_URL).get("movies"); Component[] response = new Component[data.size()]; int offset = 0; for(Object movie : data) { response[offset] = createMovieEntry(Result.fromContent((Map)movie)); offset++; } return response; } catch(IOException err) { Dialog.show("Error", "Error during connection: " + err, "OK", null); } return null; } }); react.show(); } Component createMovieEntry(Result data) { Container entry = BorderLayout.center( BoxLayout.encloseY( new SpanLabel(data.getAsString("title"), "Line1"), new Label(data.getAsString("year"), "Line2"))). add(BorderLayout.WEST, URLImage.createToStorage(placeholder, data.getAsString("id"), data.getAsString("posters/thumbnail"))); return entry; } public void stop() { current = Display.getInstance().getCurrent(); } public void destroy() { }} |
| Ссылка: | Java превосходно реагирует практически на собственный язык от нашего партнера JCG Шая Альмога из блога Codename One . |