Языки программирования:
Как делать?
-
C/C++/C#;
-
Java;
-
JavaScript;
-
Python;
-
Swift/UIKit, а SwiftUI уже декларативный;
-
Ruby, Basic, Pascal;
Пример кода
private func fetchData(from url: URL, completion: @escaping ([User]) -> Void) {
let dataTask = URLSession.shared.dataTask(with: url) { data, _, error in
if let _ = error {
completion([])
}
guard let data = data else {
return completion([])
}
do {
let decoder = JSONDecoder()
let users = try decoder.decode([User].self, from: data)
DispatchQueue.main.async {
completion(users)
}
} catch {
completion([])
}
}
dataTask.resume()
}
C, Basic, Pascal
Последовательно выполняемые операторы можно собрать в подпрограммы, то есть более крупные целостные единицы кода, с помощью механизмов самого языка. Процедурное программирование является отражением архитектуры традиционных ЭВМ. Процедурный язык программирования предоставляет возможность программисту определять каждый шаг в процессе решения задачи. Особенность таких языков программирования состоит в том, что задачи разбиваются на шаги и решаются шаг за шагом. Используя процедурный язык, программист определяет языковые конструкции для выполнения последовательности алгоритмических шагов.
C#, C++, Java. Objective-C, Perl, Python, Scala, Ruby, Smaltalk, PHP
Язык, построенный на принципах объектно-ориентированного программирования. В основе концепции объектно-ориентированного программирования лежит понятие объекта — некой сущности, которая объединяет в себе поля (данные) и методы (выполняемые объектом действия).
Языки программирования:
Что делать?
-
HTML;
-
Lisp, Erlang, Haskell, Scala, Clojure;
-
SwiftUI, Combine
-
SQL
Самый популярный язык СУБД SQL так же является декларативным. На нём описывается конечный результат, а способ его получения генерируется сервером СУБД исходя из множества факторов.
Lisp, Erlang, Haskell, Scala, Clojure
На основе достаточно строгих абстрактных понятий и методов символьной обработки данных. Тексты программ на функциональных языках программирования описывают «как решить задачу», но не предписывают последовательность действий для решения.
Пример кода
private func fetchData(from url: URL) -> AnyPublisher<[User], Never> {
URLSession.shared.dataTaskPublisher(for: url)
.map { $0.data }
.decode(type: [User].self, decoder: JSONDecoder())
.receive(on: DispatchQueue.main)
.replaceError(with: [])
.eraseToAnyPublisher()
}
Отличия между реактивным (декларативный "Что делать?") и классическим подходом (императивным "Как делать?"):
- push вместо pull
Раскрыть
Разница в том, как именно мы работаем с данными. Вместо самостоятельного извлечения каких-либо данных (например, из массива или UserDefaults), мы пишем код таким образом, чтобы объект сам отправлял актуальные на текущий момент данные, а также все последующие изменения.
Другими словами, массив (или сервис) перестает быть статичным набором элементов и превращается в поток данных, который сам отправляет содержащиеся в нем элементы один за другим.
- auto update
Раскрыть
В императивном подходе нам надо самостоятельно следить за данными: проверять на актуальность и обновлять.
В реактивном подходе данные всегда будут в консистентном виде.
Например, в социальной сети для авторизованного пользователя могут быть доступны функции, недоступные анонимному пользователю. А также в зависимости от состояния может по-разному выглядеть интерфейс.
Смена статуса авторизации может произойти на одном табе, а перерисовать экраны мы должны во всем приложении. Пользователь может разлогиниться самостоятельно, а также его может выкинуть система, если, допустим, «протухнет» токен. Что делать?
В императивном подходе без использования паттерна наблюдателя у нас был бы сервис с таймером, время от времени проверяющий статус пользователя. Как только статус изменится, мы бы сохранили его и принудительно перерисовали интерфейс, начав заново опрашивать сервис о статусе. В этом случае мы похожи на ослика из Шрека: «А сейчас? Уже можно? Может, пора?».
В реактивном подходе мы бы просто подписались на изменения в сервисе на нужных экранах и перерисовывали интерфейс при необходимости.
Примером из мира iOS-разработки может послужить переход от MRC к ARC — когда было необходимо самостоятельно следить за количеством сильных ссылок на объект и вызывать методы retain / release.
В 70-е годы прошлого века возник новый подход к разработке алгоритмов и программ, который получил название структурного проектирования программ. К его достоинствам можно отнести: более высокую производительность; читаемость программ; простоту тестирования и эффективность программ.
Одна из концепций структурного программирования – нисходящее проектирование (декомпозиция).
Все операции в программе, построенной на основе структурного программирования, должны представлять собой либо исполняемые в линейном порядке выражения, либо одну из следующих управляющих конструкций: вызовы подпрограмм; вложенные на произвольную глубину операторы условия; циклические операторы.
2.2 Languages Folder | Back To iOSWiki Contents | 2.2.2 Programming Languages Paradigm Theme Folder