Как (программирование) языки формируют решение проблем

Быть многоязычным разработчиком становится все более важным. Быть разработчиком, свободно владеющим многими языками программирования, не только повышает вашу конкурентоспособность, но и улучшает ваши навыки решения проблем. Это поможет вам стать более влиятельным разработчиком, который сможет решать проблему с более глубоким пониманием, более информированными архитектурными решениями и мыслить за пределами ограничений, присущих любому отдельному языку. За последние шесть месяцев я выучил языки, которые раньше использовал лишь случайно (например, Ruby, Python и JavaScript), стремясь оставаться на переднем крае развивающегося технологического ландшафта. В течение этого периода я осознал, что мое мышление и решение проблем в разработке программного обеспечения ограничивалось идиоматикой Swift и Objective-C. Став многоязычным разработчиком, я улучшил свои навыки решения проблем.

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

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

Например, предположим, что вы младший разработчик iOS и когда-либо читали или писали только на Swift, а не на Objective-C. Есть парадигмы программирования, которые вы упускаете.

Objective-C и Swift

Одно из ключевых различий между Objective-C и Swift - это способ вызова функций. Objective-C реализует свою функциональность путем передачи сообщений времени выполнения между объектами, тогда как вызовы функций Swift должны быть известны во время компиляции. Это имеет несколько серьезных последствий: можно скомпилировать и выполнить программу Objective-C, в которой объект, отправляющий сообщение (то есть вызов функции), ничего не знает о получателе этого сообщения. Верно и обратное: объект, получающий сообщение, может не знать, что делать с этим сообщением (т.е. отсутствует объявление функции). Это означает, что в Objective-C вам не нужно знать, какой вызов функции (т. Е. сообщение) будет выполняться вашим кодом при компиляции приложения. Эта система обмена сообщениями (которая может допускать множество злоупотреблений) включала и продолжает поддерживать невероятное количество приложений и библиотек iOS и macOS, которые были бы невозможны или даже невозможны в Swift. (Так Dropbox разместил эти зеленые галочки в Finder до того, как официальный API стал доступен в OS X 10.10« Yosemite »).

Вот еще один пример того, что вы упускаете, если когда-либо писали или читали только на Swift:

Async/Await

До недавнего времени я никогда не использовал шаблон _3 _ / _ 4_. Хотя я хорошо знаком с параллелизмом и огромной мощностью Grand Central Dispatch, я полностью пропустил _5 _ / _ 6_.

Одна из лучших сторон работы в Livefront - это акцент на лидерство в области программного обеспечения и его будущее. В моем последнем научно-исследовательском проекте у меня была возможность изучить и использовать JavaScript (ES6) на платформе Node.js для объединения асинхронных сетевых запросов в рамках строгой структуры, которую я не мог переопределить (например, SDK). Обычно это не проблема, с которой я сталкиваюсь при работе со Swift и Objective-C, учитывая, что я могу спроектировать асинхронную работу таким образом, чтобы он был идиоматическим и имел концептуальный смысл в моем понимании. Однако работа в строгих рамках SDK на серверной архитектуре, которую я никогда раньше не использовал (AWS Lambda) на иностранном языке, оказалась проблемой, которая заставила меня опустить голову и изучить совершенно новую концепцию: _7 _ / _ 8_.

Изучив встроенную поддержку JavaScript для _9 _ / _ 10_ (и Promises!), Я понял, что в прошлом я делал нечто подобное в Swift, используя DispatchGroup Grand Central Dispatch. Однако ключевым отличием было то, что Swift не имеет поддержки на уровне языка для await в _13 _ / _ 14_. (await предотвращает продолжение выполнения кода после ключевого слова await до тех пор, пока async не будет разрешено.) Это позволяет включить осмысленный порядок асинхронных операций, а также избежать потенциального ада обратного вызова, который может возникнуть даже в лучшем из Swift кодовые базы.

Давайте посмотрим на пример:

Вот один (довольно неоптимальный) способ в Swift выполнить аналогичную операцию только с Foundation:

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

«Миры, в которых живут разные общества, - это разные миры, а не просто одни и те же миры с разными ярлыками». - Эдвард Сэпир

Если бы я не рискнул выйти за рамки моей обычной рутины свободного от зависимостей Swift для изучения ES6 JavaScript, я не только пропустил бы эту конкретную парадигму программирования, но я также пропустил бы ментальную / концептуальную модель _21 _ / _ 22_. Теперь, когда я знаком с этим типом потока управления, объединяющим асинхронный и синхронный код вместе, у меня есть еще один инструмент в моем наборе инструментов, который я могу использовать в любой момент для решения проблем. И хотя я не могу изначально использовать await непосредственно в Swift, я могу позаимствовать концепции из _24 _ / _ 25_ для реализации новых идиоматических решений.

.Finally()

Если вы говорите себе: но я уже знал об async & await!, это здорово! И вы правы: _27 _ / _ 28_ - идея не новая. Он существует в C # со времен Visual Studio 11 и еще с 2007 на F #, но в том-то и дело! За последние шесть месяцев я многому научился, изучая Ruby, Python и JavaScript среди других языков. Я могу с уверенностью сказать, что есть некоторый шаблон, архитектура или даже функция на уровне языка, о которых вы, вероятно, не знаете, и я надеюсь, что вы продолжите изучать другие языки и функции, которые сделают вас лучшим разработчиком.

Кихун любит find.out().then(obliterate(his.ignorance)) в Livefront.

Сноски

¹ https://www.ncbi.nlm.nih.gov/pmc/articles/PMC3583091/

² http://www.eneuro.org/content/early/2019/03/18/ENEURO.0483-18.2019

³ https://www.sciencedaily.com/releases/2012/10/121023124000.htm

https://www.psychologytoday.com/us/blog/the-biolinguistic-turn/201702/how-the-language-we-speak-affects-the-way-we-think

⁵ Если вы читаете это, и вы человек, который экспериментировал только с одним языком (Swift или любым другим), я настоятельно рекомендую вам проверить другие языки, такие как C ++, Rust, Go, Java, R, C # и Kotlin.