Connect with us

Программирование

Использование NSURLProtocol в Swift

NSURLProtocol – это как волшебный ключ к URL. Он позволяет предопределить, как работает система загрузки URL у Apple, определяя схемы пользовательских URL, и повторно переопределяя поведение существующих схем URL.

SwiftBook

Опубликовано

/

     
     

NSURLProtocol – это как волшебный ключ к URL. Он позволяет предопределить, как работает система загрузки URL у Apple, определяя схемы пользовательских URL и повторно переопределяя поведение существующих схем URL.

Звучит как волшебство? Так и должно быть, потому что URL словно любовь, которая везде вокруг нас. Что используют UIWebView и WKWebView? Конечно же URL. Что используется для потокового видео в MPMoviePlayer? И опять URL. Как вы отправляете кого-то на iTunes за вашим приложением, входите в FaceTime или Skype, загружаете приложение в систему, или даже вставляете изображение в HTML файл? И снова с URL. Взгляните на NSFileManager и обратите внимание, как много из его методов, работающих с файлами, требуют и возвращают URL!

В этом туториале по NSURLProtocol вы узнаете, как определить обработчика протокола, который меняет схемы URL. При этом он добавляет грубый и готовый прозрачный слой кеширования, сохраняя извлеченные данные в Core Data. При его включении обычный UIWebView может взять на себя роль браузера путем кеширования загруженных страниц для возможности просмотра их в оффлайне позднее.

Прежде чем углубиться с головой в тему, вам понадобится базовое понимание сетевых концепций и знакомство с тем, как работает NSURLConnection.

Итак, вы готовы начать изучение возможностей NSURLProtocol? Хорошо, устраивайтесь поудобнее с чашечкой чая и начнем расширяющее сознание обсуждение и пошаговые упражнения.

Начало

Для проекта этого туторила, вы создадите элементарный мобильный веб-браузер, такой, который вы могли бы добавить к вашему следующему приложению. Он будет иметь базовый интерфейс пользователя, который позволит ему войти и перейти к URL. Но ваш браузер сможет успешно кешировать полученные результаты. Поэтому пользователь сможет загружать страницы, которые он посетил ранее, в мгновение ока, ведь страница не будет загружаться из сетевого запроса, а только из локального кеша приложения.

Вы уже знаете, что быстрая загрузка страницы == счастливые пользователи, так что это хороший пример того, как можно улучшить NSURLProtocol для успешной работы вашего приложения.

Шаги, через которые вы пройдете:

  1. использование UIWebView для отображения веб-сайтов;
  2. использование Core Data для кеширования результатов.

Если вы не знакомы с Core Data, то можете заглянуть в учебник. Однако, кода в этом уроке должно быть достаточно для того, чтобы понять возможности NSURLProtocol. Использование Core Data является простым способом реализации локального кеша, так что на этом этапе вам этого будет достаточно.

Обзор исходного проекта

Вы можете скачать исходный проект здесь (архив). Как только загрузка будет завершена, распакуйте файл и откройте проект.

Когда вы откроете проект, то увидите два основных файла. Первый файл – Main.storyboard. Он имеет стандартный UIViewController, как раз такой, какой вам нужен для реализации. Обратите внимание на UITextField (для ввода URL), UIButton (для вызова веб-запросов) и UIWebView.

Откройте BrowserViewController.swift. Здесь вы увидите основное поведение, установленное для UI компонентов. UIViewController реализует протокол UITextFieldDelegate так, что вы можете отправлять запрос, когда пользователь нажимает клавишу возврата. IBAction для кнопки предварительно установлен на такое же поведение, как и клавиши возврата. Метод sendRequest() берет текст из текстового поля, создает объект NSURLRequest и вызывает метод loadRequest(_:)из UIWebView для загрузки.

После того, как вы ознакомитесь с приложением, запустите его! Когда оно откроется, введите “http://swiftbook.ru” и нажмите кнопку “Go”. UIWebView загрузит ответ и отобразит результат в приложении – довольно просто для начала, правда? Пришло время размять мышцы на пальцах, приступаем к коду!

Перехват сетевых запросов

Набор классов, известных как URL Loading System (система загрузки URL), обрабатывает запросы URL на iOS. В центре системы загрузки URL находится NSURL класс. Для сетевых запросов этот класс говорит, какой именно хост (host) пытается достичь вашего приложения и указывает путь к ресурсу на этом хосте. Кроме того, объект NSURLRequest добавляет такую информацию, как: HTTP заголовки, тело вашего сообщения и т.д.. Система загрузки обеспечивает несколько различных классов, которые вы можете использовать, чтобы обработать запрос, наиболее распространенными из которых являются NSURLConnection и NSURLSession.

Теперь пришло время, чтобы начать перехват всех NSURLRequest, отправленных с приложения. Для этого вам нужно создать свою собственную реализацию NSURLProtocol.

Нажмите File\New\File…. Выберете iOS\Source\Cocoa Touch Class и затем нажмите кнопку Next. В поле Class введитеMyURLProtocol, а в поле Subclass of введите NSURLProtocol. Убедитесь, что выбранный язык -Swift. Затем, нажмите Next и Create, когда появится диалоговое окно.

Откройте MyURLProtocol.swift и замените его содержимое на следующее:

import UIKit
 
var requestCount = 0

class MyURLProtocol: NSURLProtocol {
  override class func canInitWithRequest(request: NSURLRequest) -> Bool {
    print("Request #\(requestCount++): URL = \(request.URL!.absoluteString)")
    return false
  } 
}

Каждый раз, когда система загрузки URL получает запрос, что нужно загрузить URL, она ищет зарегистрированного обработчика протокола для обработки запроса. Каждый обработчик сообщает системе, может ли он справиться с данным запросом посредством canInitWithRequest(_:).

Параметром этого метода является запрос, а сам он звучит, как вопрос протоколу: сможет ли тот обработать передаваемый запрос? Если метод возвращает true, то загрузка системы будет опираться на этот подкласс NSURLProtocol для обработки запроса и игнорировать всех других обработчиков.

Если ни один из пользовательских зарегистрированных обработчиков не может обработать запрос, то система загрузки URL будет обрабатывать его сама, используя поведение системы по умолчанию.

Если вы хотите реализовать новый протокол, такой как foo: //, то это то место, которое нужно проверить, чтобы увидеть, является ли запрошенная схема URL foo. Но в приведенном выше примере вы просто возвращаете false, что говорит вам о том, что ваше приложение не может обработать запрос. Просто подождите минуту и вы начнете их обрабатывать в ближайшее время!

Откройте AppDelegate.swift и замените application(_:didFinishLaunchingWithOptions:) следующим:

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
    NSURLProtocol.registerClass(MyURLProtocol)
    return true
}

Теперь, когда ваше приложение запущено, оно будет регистрировать протокол с системой загрузки URL. Это означает, что он будет иметь возможность обрабатывать каждый запрос, доставленный системе загрузки URL. Сюда мы включаем код, который вызывает систему загрузки напрямую, а также многие компоненты системы, которые полагаются на загрузочные фреймворки URL, такие как UIWebView.

Запустите проект. Вставьте http://swiftbook.ru как веб-сайт, нажмите на Go и проверьте консоль Xcode. Теперь на каждый запрос приложения, который необходимо выполнить, система загрузки URL запрашивает класс, если она может обработать его. В консоли вы должны увидеть что-то вроде этого:

В настоящее время ваш класс только записывает строковое отображение URL запроса и возвращает false. Это означает, что ваш пользовательский класс не может обработать запрос. Но если вы посмотрите в логах, то увидите все запросы из UIWebView. Сюда включены и главный сайт (.html), и все эссеты (наборы), такие как изображения в формате JPEG и CSS файлы. Каждый раз, когда UIWebView нужно отправить запрос, он отображается в консоли, прежде чем сработать. Запросов будет целая куча – более пятисот – из-за разных наборов (эссетов) на веб-странице.

Итак, ваш пользовательский класс объявляется для каждого запроса URL, а в последующем вы сможете уже сделать что-то в каждом запросе!

Пользовательская загрузка URL

“Я люблю, когда страницы загружаются вечно” – никто так не скажет! Никогда! Теперь вы должны убедиться, что ваше приложение действительно может обрабатывать запросы. Как только true возвращается в canInitWithRequest(_:), на ваш класс переходит ответственность касательно обработки запроса. Это означает, что вы должны получить запрошенные данные и предоставить их обратно в систему загрузки URL.

Как вы получаете данные?

Если вы реализуете новый сетевой протокол приложения с нуля (например, добавление foo: // протокола), то вы познаете суровые радости реализации сетевого протокола приложения. Но так как наша цель просто вставить пользовательский слой кеширования, то вы можете просто получить данные с помощью NSURLConnection.

Фактически вы только собираетесь перехватить запрос и затем передать его обратно стандартной системе загрузки URL через использование NSURLConnection.

Ваш пользовательский подкласс NSURLProtocol возвращает данные через объект, который реализует протокол NSURLProtocolClient. Название немного сбивает с толку: NSURLProtocol – это класс, а NSURLProtocolClient – протокол!

Через клиента вы общаетесь с системой загрузки URL для обратной передачи основных изменений, ответов и данных.

Откройте MyURLProtocol.swift и добавьте следующее свойство в верхней части определения класса MyURLProtocol:

var connection: NSURLConnection!

Затем найдите canInitWithRequest(_:). Измените строчку возврата на true:

return true

Добавьте еще четыре метода:

override class func canonicalRequestForRequest(request: NSURLRequest) -> NSURLRequest {
    return request
}
 
override class func requestIsCacheEquivalent(aRequest: NSURLRequest,
                                   toRequest bRequest: NSURLRequest) -> Bool {
    return super.requestIsCacheEquivalent(aRequest, toRequest:bRequest)
}
 
override func startLoading() {
    self.connection = NSURLConnection(request: self.request, delegate: self)
}
 
override func stopLoading() {
    if self.connection != nil {
        self.connection.cancel()
    }
    self.connection = nil
}

Вашему предстоит определять, что значит «канонический запрос» (взятый за образец) и, как минимум, он должен вернуть такой же канонический запрос для таких же входящих запросов. Таким образом, если в этом методе вводятся семантически равные (т.е. не обязательно ===) запросы, то выходные запросы должны быть тоже семантически равны. Например, если ваша пользовательская схема URL чувствительна к регистру, то вы можете решить, что все канонические URL будут написаны в строчном регистре.

Для достижения абсолютного минимума просто возвратите сам запрос. Как правило, это является надежным путем решения, потому что вы, как правило, не хотите менять запрос. В конце концов, вы ведь доверяете разработчику, правильно?! Примером вашей работы здесь, будет замена запроса с добавлением заголовка и возврата нового запроса.

requestIsCacheEquivalent(_:toRequest:) – место, где вы можете определить, когда два отдельных запроса пользовательской схемы URL (т.е. foo: //) равны, с точки зрения способности возможности кеширования. Если два запроса равны, то они должны использовать одни и те же данные кеша. Это касается и самой системы загрузки URL и встроенной системы кеширования, которую мы не рассматриваем в этом туториале. Таким образом, для данного упражнения вы просто полагаетесь на реализацию по умолчанию суперкласса.

Система загрузки использует startLoading() и stopLoading() для того, чтобы сказать NSURLProtocol, и начать или остановить обработку запроса. Ваша начальная реализация настраивает NSURLConnection для загрузки данных. Существует метод остановки, так что URL загрузка может быть отменена. В приведенном выше примере как раз происходит такая обработка, отменяя текущее соединение и избавляясь от него.

Ю-ху! Вы реализовали интерфейс, необходимый для действующего экземпляра NSURLProtocol.

Но ваш код еще не готов! Вы все еще должны поработать с обработкой запроса, что вы и сделаете, обрабатывая обратную связь от делегата NSURLConnection, созданного вами.

Откройте MyURLProtocol.swift и добавьте следующие методы:

func connection(connection: NSURLConnection!, didReceiveResponse response: NSURLResponse!) {
    self.client!.URLProtocol(self, didReceiveResponse: response, cacheStoragePolicy: .NotAllowed)
}
 
func connection(connection: NSURLConnection!, didReceiveData data: NSData!) {
    self.client!.URLProtocol(self, didLoadData: data)
}
 
func connectionDidFinishLoading(connection: NSURLConnection!) {
    self.client!.URLProtocolDidFinishLoading(self)
}
 
func connection(connection: NSURLConnection!, didFailWithError error: NSError!) {
    self.client!.URLProtocol(self, didFailWithError: error)
}

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

Таким образом, обработчик MyURLProtocol создает свое собственное подключение NSURLConnection и запрашивает его продолжить запрос. В ответных методах делегата NSURLConnection, описанных выше, обработчик протокола ретранслирует сообщения от соединения обратно, к системе загрузки URL. Эти сообщения говорят о прогрессе загрузки, о завершении операции и об ошибках.

Посмотрите и вы увидите сходство в сигнатурах сообщений NSURLConnectionDelegate и NSURLProtocolClient — оба они используют API для асинхронной загрузки данных. Также обратите внимание, как MyURLProtocol использует свойство client для отправки сообщений обратно в систему загрузки URL.

Запустите проект. Когда приложение откроется, введите тот же URL и нажмите «Go».

Ой-ой! Ваш браузер больше ничего не загружает!

Если вы посмотрите в панель дебаггера, то увидите, как растет число запросов одного и того же URL. Что же не так?

2 (1)

Сначала вернитесь в Xcode и остановите симулятор, пока у вас не начались более серьезные проблемы.

Разрыв бесконечного цикла запросов

Подумайте снова о системе загрузки URL и регистрации протокола, может быть у вас появится догадки, почему так происходит. Когда UIWebView хочет загрузить URL, система загрузки URL спрашивает MyURLProtocol сможет ли он обработать этот запрос, и ваш класс отвечает true – да, он может его обработать.

Таким образом система загрузки URL создает экземпляр вашего протокола и вызывает startLoading. Затем ваша реализация создает и запускает свой NSURLConnection. Но помимо этого она также вызывает систему загрузки URL. Так как ваш метод canInitWithRequest(_:) возвращает true, то он создает новый экземпляр MyURLProtocol.

Очевидно, что вы не можете всегда возвращать true в методе canInitWithRequest(_:). Вам нужен своего рода контроль для того, чтобы вы могли сказать системе загрузки URL, чтобы она обрабатывала запрос единожды. Решение кроется в интерфейсе NSURLProtocol. Поищите метод класса setProperty(_:forKey:inRequest:), который позволяет добавлять дополнительные свойства в указанный URL. В этом случае вы сможете установить «ярлык», прикрепив к запросу это свойство, таким образом браузер поймет, встречал ли он этот запрос раньше или нет.

Вот пример того, как вы можете вытащить ваш браузер из бесконечного цикла безумия: откройте NSURLProtocol.swift, измените методы startLoading() и canInitWithRequest(_:), вот так:

override class func canInitWithRequest(request: NSURLRequest) -> Bool {
    print("Request #\(requestCount++): URL = \(request.URL!.absoluteString)")
 
    if NSURLProtocol.propertyForKey("MyURLProtocolHandledKey", inRequest: request) != nil {
      return false
    }
 
    return true
}

override func startLoading() { 
    var newRequest = self.request.mutableCopy() as NSMutableURLRequest
    NSURLProtocol.setProperty(true, forKey: "MyURLProtocolHandledKey", inRequest: newRequest)
 
    self.connection = NSURLConnection(request: newRequest, delegate: self)
 }

Теперь startLoading() выставляет свойство связанное с ключом «MyURLProtocolHandledKey» на true для текущего запроса. Это означает, что в следующий раз, когда он вызывает метод canInitWithRequest(_:) для данного экземпляра NSURLProtocol, протокол может спросить, выставлено ли это свойство.

Если его значение выставлено на true, то это означает, что вам не нужно обрабатывать этот запрос еще раз, и система загрузки URL получит данные из сети. Так как экземпляр MyURLProtocol является делегатом для этого запроса, то он получит ответ от NSURLConnectionDelegate.

Запустите ваше приложение. Когда вы сделаете это, сразу убедитесь в том, что оно благополучно отображает все данные в вашем UIWebView. Сладкая победа! Теперь консоль выглядит примерно вот так:

Request #0: URL = http://swiftbook.ru/
Request #1: URL = http://swiftbook.ru/
Request #2: URL = http://swiftbook.ru/
Request #3: URL = http://swiftbook.ru/
Request #4: URL = http://swiftbook.ru/
Request #5: URL = http://swiftbook.ru/
Request #6: URL = http://swiftbook.ru/
Request #7: URL = http://swiftbook.ru/
Request #8: URL = http://swiftbook.ru/
Request #9: URL = http://swiftbook.ru/
Request #10: URL = http://swiftbook.ru/
Request #11: URL = http://swiftbook.ru/
Request #12: URL = http://swiftbook.ru/
Request #13: URL = http://swiftbook.ru/
Request #14: URL = http://swiftbook.ru/
Request #15: URL = http://swiftbook.ru/sites/default/files/css/css_lQaZfjVpwP_oGNqdtWCSpJT1EMqXdMiU84ekLLxQnc4.css
Request #16: URL = http://swiftbook.ru/sites/default/files/css/css_lQaZfjVpwP_oGNqdtWCSpJT1EMqXdMiU84ekLLxQnc4.css 
Request #17: URL = http://swiftbook.ru/sites/default/files/css/css_lQaZfjVpwP_oGNqdtWCSpJT1EMqXdMiU84ekLLxQnc4.css 
Request #18: URL = http://swiftbook.ru/sites/default/files/css/css_lQaZfjVpwP_oGNqdtWCSpJT1EMqXdMiU84ekLLxQnc4.css 
Request #19: URL = http://swiftbook.ru/sites/default/files/css/css_0rdNKyAx9df4tRKovKjnVDsGvZwVuYAKO-m17AAJ1Dk.css ..

Вам наверное интересно, почему пришлось столько всего сделать и все для того, чтобы ваше приложение работало точно так же, как оно работало в начале туториала? А это для того, чтобы подготовить вас к самому интересному! Теперь у вас есть полный контроль над данными URL вашего приложения и вы можете делать с ними все, что захотите. Теперь самое время начать кешировать данные URL вашего приложения.

Реализация локального кеша

Первым требованием к приложению было то, что для каждого запроса, оно должно было загружать данные из интернета только один раз, и кешировать их. Если запрос повторяется в дальнейшем, то ваш протокол предоставляет кешированный ответ без перезагрузки данных из сети.

Заметка:

 

Исходный проект уже включает в себя базовую модель Core Data и стек. Вам не нужно знать детали Core Data, думайте о нем, как о хранилище данных.

Теперь самое время сохранить ответы, которые получает приложение из сети, чтобы была возможность получить их, когда мы получаем запрос сходный с кешированными данными. Откройте MyURLProtocol.swift и добавьте следующий import вверх файла.

import CoreData

Затем добавьте следующие свойства в реализацию класса:

var mutableData: NSMutableData!
var response: NSURLResponse!

Свойство response будет держать ссылку на метаданные, которые вам понадобятся для хранения ответа от сервера. Свойство mutableData будет использовано для хранения данных, которые получает соединение в методе делегата connection(_:didRecieveData).

Добавьте следующий метод в класс:

func saveCachedResponse () {
    print("Saving cached response")
 
    // 1
    let delegate = UIApplication.sharedApplication().delegate as! AppDelegate
    let context = delegate.managedObjectContext
 
    // 2
    let cachedResponse = NSEntityDescription.insertNewObjectForEntityForName("CachedURLResponse", inManagedObjectContext: context) as NSManagedObject
 
    cachedResponse.setValue(self.mutableData, forKey: "data")
    cachedResponse.setValue(self.request.URL!.absoluteString, forKey: "url")
    cachedResponse.setValue(NSDate(), forKey: "timestamp")
    cachedResponse.setValue(self.response.MIMEType, forKey: "mimeType")
    cachedResponse.setValue(self.response.textEncodingName, forKey: "encoding")
 
    // 3
    if context.hasChanges {
      do {
        try context.save()
      } catch let error as NSError {
        NSLog("произошла ошибка \(error), \(error.userInfo)")
        abort()
      }
    }

Вот что делает этот метод:

  1. Получает NSManagedObjectContext из Core Data экземпляра AppDelegate. Этот контекст является вашим интерфейсом взаимодействия с Core Data.
  2. Создаем экземпляр NSManagedObject для соответствия модели, которую вы видели в фйле .xcdatamodeld. Устанавливаем значения, основываясь на ссылках на NSURLResponse и NSMutableData, которые у вас есть.
  3. Сохраняем контекст управляемого объекта Core Data, если в нем произошли изменения.

Теперь у вас есть возможность сохранения данных, осталось только вызвать этот метод. Продолжаем работать в MyURLProtocol.swift. Измените методы делегата NSURLConnection на следующие:

func connection(connection: NSURLConnection!, didReceiveResponse response: NSURLResponse!) {
    self.client!.URLProtocol(self, didReceiveResponse: response, cacheStoragePolicy: .NotAllowed)
 
    self.response = response
    self.mutableData = NSMutableData()
}
 
func connection(connection: NSURLConnection!, didReceiveData data: NSData!) {
    self.client!.URLProtocol(self, didLoadData: data)
    self.mutableData.appendData(data)
}
 
func connectionDidFinishLoading(connection: NSURLConnection!) {
    self.client!.URLProtocolDidFinishLoading(self)
    self.saveCachedResponse()
}

Вместо прямой передачи запроса и данных клиенту, они сохраняются при помощи вашего протокольного класса.

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

Получение закешированного ответа

Наконец настало время получить ранее закешированные запросы и отправить их клиенту NSURLProtocol. Откройте MyURLProtocol.swift и добавьте следующий метод:

func cachedResponseForCurrentRequest() -> NSManagedObject? {
    // 1
    let delegate = UIApplication.sharedApplication().delegate as! AppDelegate
    let context = delegate.managedObjectContext
 
    // 2
    let fetchRequest = NSFetchRequest()
    let entity = NSEntityDescription.entityForName("CachedURLResponse", inManagedObjectContext: context)
    fetchRequest.entity = entity
 
    // 3
    let predicate = NSPredicate(format:"url == %@", self.request.URL!.absoluteString)
    fetchRequest.predicate = predicate
 
    // 4
    do {
      let possibleResult = try context.executeFetchRequest(fetchRequest)
      
      if !possibleResult.isEmpty {
        return possibleResult.first as? NSManagedObject
      }
      
    } catch let error as NSError {
      print("Fetch failed: \(error.localizedDescription)")
    }
    
    return nil
}

Вот что он делает:

  1. Берет контекст управляемого объекта Core Data, точно так же, как и в saveCachedResponse().
  2. Создает NSFetchRequest, говоря о том, что вы хотите найти все сущности с именем CachedURLResponse. Это и есть та сущность в модели управляемого объекта, которую вы хотите получить.
  3. Предикат для вашего запроса (fetch request) должен получить объект CachedURLResponse, который имеет отношение к URL и который вы пытаетесь загрузить. Как раз этот блок это и делает.
  4. Исполняет запрос и проверяет на наличие результатов. Если массив не пуст, то возвращается первый из них.

Теперь нам нужно вернуться и посмотреть на реализацию startLoading(). Вместо того, чтобы все подряд загружать из сети, нужно сделать так, чтобы он сначала проверял наличие закешированного ответа по URL. Найдите соответствующую реализацию и замените ее на следующую:

override func startLoading() {
    // 1
    let possibleCachedResponse = self.cachedResponseForCurrentRequest()
    if let cachedResponse = possibleCachedResponse {
        print("Serving response from cache")
 
        // 2
        let data = cachedResponse.valueForKey("data") as! NSData!
        let mimeType = cachedResponse.valueForKey("mimeType") as! String!
        let encoding = cachedResponse.valueForKey("encoding") as! String!
 
        // 3
        let response = NSURLResponse(URL: self.request.URL!, MIMEType: mimeType, expectedContentLength: data.length, textEncodingName: encoding)
 
        // 4
        self.client!.URLProtocol(self, didReceiveResponse: response, cacheStoragePolicy: .NotAllowed)
        self.client!.URLProtocol(self, didLoadData: data)
        self.client!.URLProtocolDidFinishLoading(self)
    } else {

        // 5
        print("Serving response from NSURLConnection")
 
        let newRequest = self.request.mutableCopy() as! NSMutableURLRequest
        NSURLProtocol.setProperty(true, forKey: "MyURLProtocolHandledKey", inRequest: newRequest)
        self.connection = NSURLConnection(request: newRequest, delegate: self)
    }
}

Вот, что здесь происходит:

  1. Сначала вам нужно выяснить, есть ли закешированный ответ на текущий запрос.
  2. Если есть, то мы получаем соответствующие данные из кеша.
  3. Создаем объект NSURLResponse из сохраненных данных.
  4. Говорим о данных в ответе клиенту. Устанавливаем политику конфиденциальности на .NotAllowed, так как мы не хотим, чтобы клиент кешировал что-либо с тех самых пор, как это стало вашей обязанностью. Затем вызываете URLProtocolDidFinishLoading для того, чтобы подать сигнал о завершении загрузки. Никаких сетевых запросов, так то!
  5. Если ничего в кеше по текущему запросу нет, то мы просто загружаем данные, как обычно.

Запустите ваш проект снова. Зайдите на парочку сайтов и выйдите из приложения. Установите режим работы вашего устройства на «в самолете» (или если вы работаете на симуляторе, то вам нужно выключить wi-fi вашего компьютера или просто выдерните кабель Ethernet) и снова запустите проект. Попробуйте вновь зайти на те же сайты, которые вы только что посещали. Ваши странички должны подгрузиться из кeша!

В консоли вы увидите множество сущностей следующего типа:

Request #7: URL = http://swiftbook.ru/
Serving response from cache

Это лог того, что ваш ответ поступает из кeша.

Ну вот и все! Ваше приложение благополучно кеширует данные и со скоростью света выдает их оттуда при повторном запросе! Ваши пользователи будут просто счастливы пользоваться вашим приложением у себя на устройстве!

Когда нужно использовать NSURLProtocol?

Как вы можете использовать NSURLProtocol, чтобы сделать ваше приложение лучше, быстрее, сильнее и зубодробительно классным? Вот вам несколько примеров:

Обеспечение индивидуальных ответов для сетевых запросов:

Неважно, делаете ли вы запрос с использованием UIWebView, NSURLConnection или используете стороннюю библиотеку (типа AFTNetworking, MKNetworkKit…, так как все они надстроены на NSURLConnection). Вы можете создать индивидуальный ответ и для метаданных, и для данных. Вы можете использовать его заглушить ответ на запрос при тестировании, например.

Пропустить активность сети и предоставить локальные данные:

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

Перенаправление сетевых запросов:

Хотелось ли вам когда-нибудь перенаправить запрос на proxy сервер без того, чтобы доверить пользователю изменить какие-либо настройки iOS? Что ж, вы можете! NSURLProtocol предоставляет то, что вам нужно — контроль над запросами. Вы можете настроить свое приложение так, что оно будет перехватывать и перенаправлять запросы на другой прокси-сервер или туда, куда вам только захочется. Речь идет о контроле запроса!

Изменение user-agent вашего запроса:

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

Используйте свой собственный сетевой протокол:

Вы можете иметь свой собственный сетевой протокол (например, что-либо построенное на UDP). Вы можете реализовать это в вашем приложении, что так же не ограничивает ваши возможности в использовании любой сетевой библиотеки.

Помните, что NSURLProtocol является мощным инструментом в дополнение к библиотеке, которую вы уже используете. Если говорить коротко, то вы можете пользоваться преимуществами NSURLProtocol в то время, пока пользуетесь и своей собственной библиотекой.

swift

Комментарии
Если вы нашли опечатку - выделите ее и нажмите Ctrl + Enter! Для связи с нами вы можете использовать info@apptractor.ru.
Advertisement
Click to comment

You must be logged in to post a comment Login

Leave a Reply

Программирование

Правила, которые я выработал по результатам 1000 code review

Леонид Боголюбов

Опубликовано

/

Во время работы в LinkedIn большая часть моей работы состояла из проверки кода. Были определенные ситуации, которые постоянно возникали снова и снова, поэтому я решил составить список, которым и поделился с командой.

Вот мои 3 (+1 бонус) наиболее распространенных правки, которые я делал во время code review.

Правка 1: Генерирование исключения, когда что-то идет не так

Обычно я видел такое:

List<String> getSearchResults(...) {
  try {
    List<String> results = // make REST call to search service
    return results;
  } catch (RemoteInvocationException e) {
    return Collections.emptyList();
  }
}

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

Если бы вместо этого API выбросил исключение, то наша система мониторинга немедленно подобрала бы его, обработала и мы ошибку исправили.

Во многих случаях возникает соблазн просто вернуть пустой объект после того, как вы поймали исключение. Примерами пустых объектов в Java являются Optional.empty(), нулевой или пустой список. Хорошим примером того, где это все встречается постоянно, является парсинг URL. Вместо того, чтобы возвращать null, если URL-адрес не может быть получен из строки, спросите себя: «Почему URL-адрес неправильно сформирован? Является ли это проблемой данных, которую мы должны исправить где-то выше?».

Пустые объекты не являются подходящим инструментом для работы. Если случилось что-то исключительное, то вы должны выбросить исключение.

Правка 2: Использование наиболее конкретного типа

Это предложение в основном противоречит строгому типизированному программированию.

Слишком часто я видел код, подобный этому примеру:

void doOperation(String opType, Data data); 
// where opType is "insert", "append", or "delete", this should have clearly been an enum

String fetchWebsite(String url);
// where url is "https://google.com", this should have been an URN

String parseId(Input input);
// the return type is String but ids are actually Longs like "6345789"

Использование наиболее конкретного типа позволяет избежать целого класса ошибок и, в основном, является основной причиной выбора строго типизированного языка, такого как Java.

Внимание, вопрос: как опытные программисты в конечном итоге пишут плохой типизированный код? Ответ: потому что внешний мир не сильно типизирован. Есть несколько разных мест, откуда берутся строки, например:

  • параметры запроса и пути в URL-адресах
  • JSON
  • Базы данных, которые не поддерживают enum
  • Плохо написанные библиотеки

В любом таком случае вы должны использовать следующую стратегию, чтобы избежать проблем – сохранить парсинг строки и сериализацию в вашей программе. Вот пример:

// Step 1: Take a query param representing a company name / member id pair and parse it
// example: context=Pair(linkedin,456)
Pair<String, Long> companyMember = parseQueryParam("context");
// this should throw an exception if malformed

// Step 2: Do all the stuff in your application
// MOST if not all of your code should live in this area

// Step 3: Convert the parameter back into a String at the very end if necessary
String redirectLink = serializeQueryParam("context");

Это дает ряд преимуществ. Неправильные данные немедленно обнаруживаются; в случае возникновении проблем приложение падает раньше. Кроме того, вам не нужно сохранять исключения для парсинга по всему приложению, так данные проверяются один раз. Кроме того, сильные типы сами по себе более полно описывают методы и вам не надо писать javadocs для каждого метода.

Правка 3: Использование Optionals вместо null

Одна из лучших функций Java 8 – это класс Optional, который представляет собой объект, который может существовать или не существовать.

Вопрос на миллион долларов: какое единственное исключение имеет собственную аббревиатуру? Ответ: NPE или Null Pointer Exception. Это, безусловно, самое распространенное исключение в  Java и, конечно, ошибка, которая стоит миллион долларов.

Optional позволяет вам полностью устранить NPE. Однако его следует использовать правильно. Вот некоторые советы по работе с Optional:

  • Не надо просто называть .get () в любое время, когда вам надо использовать Optional. Вместо этого внимательно подумайте о том случае, когда Optional не представлен, и придумайте разумное значение по умолчанию.
  • Если у вас еще нет разумного значения по умолчанию, тогда такие методы, как .map () и .flatMap (), позволяют отложить это решение.
  • Если внешняя библиотека возвращает значение NULL, чтобы указать на пустой случай, сразу же оберните значение с помощью параметра Optional.ofNullable (). Поверьте мне, вы поблагодарите себя позже. Нули имеют тенденцию «всплывать» внутри программ, поэтому лучше остановить их в первоисточнике.
  • Используйте Optional как возвращаемый тип в методах. Это здорово, потому что вам не нужно будет читать javadoc, чтобы выяснить, возможно ли, чтобы значение было пустым.

Бонус: Использование Unlift методов, когда это возможно

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

// AVOID:
CompletableFuture<T> method(CompletableFuture<S> param);
// PREFER: 
T method(S param);

// AVOID:
List<T> method(List<S> param);
// PREFER:
T method(S param);

// AVOID: 
T method(A param1, B param2, Optional<C> param3);
// PREFER:
T method(A param1, B param2, C param3);
T method(A param1, B param2);
// This method is clearly doing two things, it should be two methods
// The same is true for boolean parameters

Что общего у всех этих методов? Они используют контейнерные объекты, такие как Optional, List или Task как параметры методов. Еще хуже, когда  возвращаемый тип является тем же самым (т.е. метод принимает Optional и возвращает Optional).

Почему это плохо?

  1. Promise<A> method(Promise<B> param)
    менее гибко, чем просто
  2. A method(B param)

Если у вас есть Promise <B>, вы можете использовать 1, или вы можете использовать 2 путем «подъема» функции с помощью .map. (т.е. promise.map(method)).

Однако, если у вас есть только B, вы можете легко использовать 2, но вы не можете использовать 1, что делает 2 гораздо более гибким вариантом.

Мне нравится называть это «неподъемным», потому что это противоположность общепринятому функциональному методу «подъем». Применение этих знаний делает методы более гибкими и удобными для использования.

 

Комментарии
Продолжить чтение

Новости

Физтехи стали чемпионами России по программированию

2-3 декабря 2017 года команда МФТИ MIPT Cryptozoology в составе Александра Останина, Александра Голованова, Никиты Уварова завоевали абсолютное первое место в полуфинале чемпионата мира по программированию ACM ICPC.

AppTractor

Опубликовано

/

Автор:

В минувшие выходные на четырёх площадках России и СНГ состоялся полуфинал международного студенческого чемпионата мира по программированию ACM ICPC — Northern Eurasia Regional Contest. Более 300 команд собрались в университетах Санкт-Петербурга, Барнаула, Тбилиси и Алматы, чтобы побороться за победу на финале в Пекине.

Правила соревнования традиционны для всех этапов чемпионата по программированию ACM ICPC: у участников есть пять часов для решения 12 задач. При оценке результатов оценивается не только правильное решение задачи, но и время, затраченное на неё — победителем становится та команда, которая смогла выполнить наибольшее количество задач за наименьшее количество времени.

В Университет ИТМО приехали 128 команд. Рекордное количество команд представил Физтех — на полуфинал приехали целых семь!

В этом году абсолютным лидером полуфинала NEERC стала команда МФТИ Cryptozoology в составе Александра Останина, Александра Голованова, Никиты Уварова, тренер Михаил Тихомиров, руководитель Алексей Малеев. Первое место в полуфинале чемпионата студенты МФТИ занимают впервые. Ранее, в октябре, эта же команда заняла первое место в 1/4 чемпионата, завоевав титул чемпионов Москвы.

Ребята смогли решить 10 из 12 задач. Как отмечает Олег Христенко, комментатор онлайн-трансляции чемпионата, один из тренеров Центра развития ИТ-образования, команда шла «правильной дорогой», решая задачи в порядке сложности.

«Задачи были хорошие, некоторые было просто решить, некоторые не очень. Вообще надеемся на золотую медаль в этом году», — комментирует победу Александр Голованов.

«Очень приятно, что в этот раз победу одержали, от себя могу добавить, что они много тренировались, в частности, уже в этом учебном году отработали с полной отдачей на сборах в Петрозаводске, Барселоне и Долгопрудном. Это отличный результат, очередной шаг признания высокого уровня подготовки студентов МФТИ в области Computer Science», – говорит директор Центра развития ИТ-образования, Алексей Малеев.

По итогам соревнования в финал прошли 16 команд, 14 (88%) из которых принимали участие в тренировочных сборах Moscow Workshops ACM ICPC в этом учебном году. Все они поедут на финал, который состоится 20-25 апреля в Пекине.

Комментарии
Продолжить чтение

Программирование

Программирование это новый пузырь?

Тайлер Эллиот Беттилион рассуждает о том, исчезнет ли профессия программиста с ростом автоматизации и повсеместным распространением компьютерной грамотности.

Анна Гуляева

Опубликовано

/

Моя подруга недавно задала вопрос, который я слышал много раз в разных вариациях:

Не кажется ли вам, что некоторые низкоуровневые профессии программистов вымрут как птицы додо? Сейчас это похоже на большой пузырь, который рано или поздно лопнет. Мне кажется, что одна из причин “престижности” технологических и связанных с наукой (на низком уровне) профессий заключается в нелепом жаргоне индустрии и всеобщей компьютерной неграмотности, и оба этих фактора исчезнут в следующие десять лет […]

Это высказывание поднимает вопрос о будущем технологических профессий и показывает распространенные заблуждения об области разработки ПО. Хотя в индустрии действительно существует «нелепый жаргон», но для решения многих сложных проблем действительно требуется нужный набор навыков. Некоторые профессии исчезают, но программисты с нужным опытом и знаниями продолжат цениться и хорошо зарабатывать ещё многие годы, как показывает недавний рост зарплат ИИ-специалистов и нехватка специалистов с этим навыком.

Следовать за меняющимся технологическим ландшафтом может быть сложно. Мы должны уметь предсказывать, какие профессии исчезнут с рынка, потому что их заменят технологии. Также мы должны следить за ростом количества людей, которые учатся программировать, чтобы предугадать, как изменятся зарплаты и спрос на определенные навыки. Как сказала Ханна, «всеобщая компьютерная неграмотность» влияет на размер зарплат программистов, но люди узнают больше о технологиях с каждым годом.

Движение к коммодификации

Страх того, что алгоритмы заменят людей на работе, — не нов и не беспричинен. В любой области, а особенно в технологии, силы рынка подталкивают корпорации к автоматизации и коммодификации. Один из способов изображения этого явления — циклы хайпа Gartner.

С течением времени специфичные идеи и технологии доходят до «плато продуктивности», где их автоматизируют. Взглянув в прошлое, можно подумать, что автоматизация может разрушать определенные рынки труда. В разных индустриях, от сбора урожая до сборки автомобиля, технологические открытия заменили и дополнили человеческий труд, чтобы сократить затраты. Один профессор во время курса по компиляторам однажды сказал: «Посмотрите на текстильную и металлургическую промышленности: вы хотите строить машины и инструменты или вы хотите ими управлять?».

Коммодификация (от англ. commodity — товар) – процесс, в ходе которого все большее число различных видов человеческой деятельности обретает денежную стоимость и фактически становится товарами, покупаемыми и продаваемыми на рынке.

В этой метафоре «машиной» является язык программирования. Этот профессор спрашивал: вы хотите делать сайты на JavaScript или вы хотите создавать движок V8 для JavaScript?

Создание веб-сайтов уже автоматизировано при помощи WordPress и других сервисов. С другой стороны, у V8 появляются конкуренты, некоторые из которых решают открытые вопросы. Языки приходят и уходят (сколько сейчас открыто вакансий для Fortran?), но всегда будут люди, создающие следующий язык. К счастью для нас, все реализации пишутся на языках программирования. Путь «оператора машины» в программировании делает вас «создателем машины» в том смысле, который оказался неверным для работников сталелитейных заводом в прошлом.

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

Коммодификация распространяется на всё, не только на программирование. Человеческий труд постоянно заменялся автоматизированным или дополнялся таким образом, что требовал меньше людей. Беспилотные автомобили и грузовики являются последним примером этой великой традиции. Если цикл создания и автоматизации является частью жизни, то естественно будет спросить: какие работы и индустрии находятся в зоне риска, а какие нет?

Кто автоматизирует кого?

AWS, Heroku и другие аналогичные хостинговые платформы навсегда изменили роль системного администратора и DevOps-инженера. Раньше интернет-бизнесу был необходим свой “мастер серверов”. Кто-то, кто был подкован в Linux, мог настроить сервер Apache или NGINX, подключить все физические компоненты и сделать все необходимое для того, чтобы сервер стал доступным в публичном вебе. Хотя некоторые люди по-прежнему применяют этот навык в работе, AWS делают некоторые из этих навыков устаревшими, особенно на уровне небольшого опыта и размещения оборудования. В Amazon, Netflix и Google существуют хорошо оплачиваемые вакансии для людей с глубокими знаниями в инфраструктуре сетей, но спрос в малом и среднем бизнесе на таких людей значительно упал.

Инструменты бизнес-аналитики, такие как SalesForce, Tableau и SpotFire также начали занимать пространство, которое исторически занимали инженеры. Эти системы сократили потребность в штатных администраторах баз данных, но они увеличили спрос на понимание SQL. Они сократили потребность во внутренней технологии отчетности, но увеличили спрос на «инженеров интеграции», которые автоматизируют поток данных к сторонним платформам. Ранее этим полем правили Excel и таблицы, а теперь оно перешло к языкам вроде Python и R, а также SQL для управления данными. Некоторые профессии исчезли, но в целом спрос на разработчиков программ вырос.

Data Science — это ещё один интересный пример коммодификации, более близкой к программированию. Scikit.learn, Tensorflow и PyTorch — это библиотеки, которые упрощают людям задачу создания приложений с машинным обучением, устраняя необходимость создания алгоритмов с нуля. На самом деле, теперь возможно провести набор данных через многие алгоритмы машинного обучения с разными параметрами, практически не понимая работу этих алгоритмом (это неправильно, но возможно). Компании бизнес-аналитики, вероятно, будут пытаться интегрировать эти алгоритмы в свои инструменты в следующие несколько лет.

Во многом Data Science сейчас похожа на веб-разработку 5–8 лет назад. Это популярная область, в которую вы можете попасть с небольшим количеством знаний из-за «разрыва в навыках». Программы по веб-разработке закрываются, а программы по data science появляются на их месте. Kaplan, которая купила первый лагерь по веб-рзработке Dev Bootcamp и основала лагерь по data science Metis, решила закрыть Dev BootCamp и поддерживать Metis.

Системы управления контентом являются наиболее заметными инструментами, автоматизирующими работу разработчика. SquareSpace и WordPress являются одними из самых популярных таких систем. Эти платформы значительно снижают ценность людей с навыками фронтенд-разработки. Барьер для создания и запуска сайта снизился настолько, что люди с нулевым опытом программирования успешно запускают сайты каждый день. Они не создают сайты с глубоким взаимодействие для миллиардов людей, но они создают сайта для своих компаний и клиентов. Хороший лендинг с контактами и адресом более чем достаточен для местного ресторана, бара или магазина.

Если ваш бизнес не связан с интернетом в своей деятельности напрямую, то вам проще простого завести работающий веб-сайт. В результате, однажды процветающая область веб-разработчиков для быстрого создания простых сайтов становится все менее прибыльной.

В этом контексте нельзя проигнорировать и физический аспект. Как сказал Майк Актон: «Программное обеспечение — это не платформа, аппаратное — платформа». Разработчикам стоит немного изучить компьютерную архитектуру и электротехнику. Большой переворот случится при появлении потребительского квантового компьютера, он изменит многое в профессиональном программировании.

Квантовые компьютеры пока далеки от нас, но растущий интерес к графическим процессорам и движение к параллелизации — это неминуемый сдвиг. Скорости работы процессоров остаются неизменными уже несколько лет, а за это время возникла потребность в машинном обучении. Желание работать с OpenMP, OpenCL, Go, CUDA и другими языками и фреймворками параллельной обработки данных никуда не денется и будет только нарастать. В ближайшем будущем параллелизация станет всеобщим требованием и выйдет за пределы ниш операционных систем, инфраструктуры и видеоигр.

Все учатся кодить

Веб-сайты повсеместны. Опрос Stack Overflow 2017 года показывает, что около 15% профессиональных разработчиков работают в компаниях, связанных с интернетом или веб-сервисами. Бюро статистики труда ожидает ускорение роста в веб-разработке (24% между 2014 и 2024). Благодаря видимости отрасли, многие сосредоточены на «сокращении разрыва в навыках». Лагери программирования обучают практически только веб-разработке, а онлайн-курсы по этой теме заполнили Udemy, Udacity, Coursera и другие платформы.

Комбинация роста автоматизации в веб-разработке и приток новых программистов привели к тому, что некоторые предсказывают появление рынка «синих воротничков» для разработчиков. Другие даже предполагают, что это движение к рынку “рабочих” специальностей является стратегией больших технологических компаний. Остальные, конечно, считают, что мы движемся к очередному пузырю.

Изменение спроса на определенные технологии — это не новость. Языки и фреймворки всегда то набирают силу, то теряют популярность. Веб-разработка в своей текущей инкарнации (JS — король) рано или поздно пройдет путь веб-разработки в начале 2000-х (помните Flash?). Новым является то, что многие люди изучают исключительно современные фреймворки веб-разработки. Прежде чем вы назовете себя React-разработчиком, вспомните, что были люди, которые идентифицировали себя как Flash-разработчиков. Полагаться на определенный язык, фреймворк или технологию в своей карьере рискованно. Конечно, сложно предсказать, какие технологии останутся релевантными, но если вы собираетесь пойти ва-банк, я рекомендую положиться на эффект Линди и выбрать что-то вроде C, который уже перенес испытание временем.

У следующего поколения будет такой уровень врожденной технологической грамотности, которого нет у поколения X и миллениалов. Одним результатом этого станет то, что CMS будут использоваться по умолчанию. Сами инструменты станут лучше, и молодые сотрудники будут лучше ими пользоваться. Эта комбинация определенно снизит ценность низкоуровневых навыков IT и веб-разработки, когда молодые специалисты войдут на рынок труда. Школы следуют за этим трендом, предлагая курсы программирования и информатики, и образованные ученики смогут сразу после окончания стать стажерами-программистами.

Другая большая группа потенциальных программистов включает выпускников MBA и аналитиков данных. В предложениях о работе, в которых прежде доминировал Excel, начинает использоваться SQL. Веб-метрики заменят таблицы в роли главного инструмента создания отчетов. Если это продолжится, все больше аналитиков данных будут сразу учить SQL, потому что он позволит проще экспортирования данные в таблицы.

Люди, желающие опередить своих сверстников в этих ролях, проходят онлайн-курсы для изучения баз данных и статистических языков программирования. С этими новыми навыками они смогут позиционировать себя как data scientists с навыками машинного обучения и статистических библиотек. Примером этого пути может быть программа обучения Metis.

Число людей с образованием в информатике и программировании продолжает расти. Университет Пердью сообщает, что количество заявлений на направление информатики удвоилось за пять лет. Корнелл сообщает об аналогичном росте числа выпускников по этому направлению. Этот тренд неудивителен в свете распространения ПО. Молодые люди не представляют будущего без компьютеров, поэтому хотят изучать то, что даст им уверенность в трудоустройстве.

Редкость и ожидание

В индустрии сейчас распространена идея о том, образование по направлению информатики в большинстве случаев является ненужным. Противоположная точка зрения также популярна, а некоторые даже говорят, что «все программисты должны получить степень магистра».

Как и Эрик Эллиотт, я считаю, что существует много хороших вариантов попасть в программирование, и степень бакалавра для некоторых может быть не лучшим вариантом. В то же время я согласен с Уильямом Бейном о том, что базовые навыки критически важны для долговременной карьеры, и эту информацию пока сложно найти вне университета. Ранее я писал о том, какие навыки я считаю фундаментальными для будущих инженеров, и поэтому я присоединился к школе Bradfield.

Школ программирования становится больше – и это не просто так. Вы можете многое узнать о программировании без знаний о большом «О», неясных структурах данных и деталей об алгоритмах. Иногда выпускники Стэнфорда соперничают с выпускниками Hack Reactor, но это верно только для одной или двух областей. Выпускники курсов программирования пока не работают в области встроенных систем, криптографии, безопасности, робототехники, инфраструктуры сетей или в разработке и исследовании искусственного интеллекта. Хотя эти области быстро растут.

Некоторые навыки уже превращаются из редких навыков в базовое ожидание. Понимание механизмов, вроде AWS, становится довольно распространенным. Но большие компании, развивающие технологии, обычно не ищут людей с «базовым пониманием JavaScript». AWS обслуживают миллиарды пользователей каждый день. Чтобы поддерживать такую инфраструктуру инженер должен понимать протоколы сетей, компьютерную архитектуру и иметь несколько лет аналогичного опыта работы. Как и в любой области, здесь есть любители и мастера.

Эти престижные фирмы исследуют проблемы и создают системы, которые действительно двигают границы возможного. Но они по-прежнему испытывают дефицит кадров, несмотря на то, что базовые навыки программирования достаточно распространены. Люди, которые могут писать алгоритмы для прогнозирования изменений в генах, которые дадут желаемый результат, будут очень ценными в будущем. Люди, которые могут программировать спутники и космические аппараты и автоматизировать машины, будут по-прежнему высоко цениться. Это не те области, для работы в которых достаточно «трехмесячной интенсивной программы», как в веб-разработке.

Предполагается, что молодые люди будут обладать врожденным пониманием компьютеров к 2025 году. К несчастью, распространенность компьютеров не привела к новому поколению людей, которые так же бы понимали математику, информатику, структуру сетей, электротехнику и так далее. Компьютерная грамотность не означает знание вычислений. Несмотря на то, что математика существует очень давно, по-прежнему только немногие люди обладают хорошим знанием статистики. Информатика почти так же стара, Эвклид изобрел несколько алгоритмов, один из которых используется при отправке HTTPS-запросов, но тот факт, что мы используем HTTPS каждый раз при входе на сайт, не означает, что все понимают работу этих протоколов.

Бимодальные распределения заработной платы

Во многих областях действует бимодальное распределение заработной платы: небольшое количество сотрудников зарабатывают большие деньги, а остальные получают неплохую зарплату, но не входят в верхний процент. NALP визуализирует этот феномен абсолютно понятно. Многие юристы зарабатывают между 45 и 65 тысячами долларов. Это хорошая зарплата, но мы не можем ассоциировать её с «топовыми профессионалами».

Мы думаем, что все новоиспеченные юристы стремятся месту партнера в фирме, хотя в реальности существует множество путей: помощник юриста, чиновник, общественный защитник, судья, юрист для бизнеса и т.д. У выпускников направления информатики существует столько же вариантов для профессиональной деятельности: от веб-разработки до встроенных систем.

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

Зарплаты мобильных разработчиков 2017: деньги, платформы, стаж и регионы

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

Комментарии
Продолжить чтение

Новости

Самые популярные языки программирования 2017

TIOBE это мгновенный срез того, что используют, а PYPL это то, что намереваются использовать разработчики.

Леонид Боголюбов

Опубликовано

/

TIOBE (The Importance of Being Earnest), один из самых популярных рейтингов языков программирования, опубликовал данные за ноябрь 2017 года и, соответственно, весь год целиком. По данным компании, Java остается самым популярным языком программирования, а за ней следуют С и C++.

С другой стороны, PYPL (PopularitY of Programming Language), еще один рейтинг, так же определи Java как лидера, но на вторые места поставил Python и PHP.

Различие между ними в том, что TIOBE  подсчитывает рейтинг на основе поисковых запросов, а PYPL подсчитывает популярность на основе Google Trends, в которой больше учитываются запросы на руководства и обучение. То есть можно предположить, что TIOBE это мгновенный срез того, что используют, а PYPL это то, что намереваются использовать разработчики.

Вот весь рейтинг за 2017 год:

Комментарии
Продолжить чтение

Наша рассылка

Каждому подписавшемуся - "1 час на UI аудит": бесплатный ускоренный курс для разработчиков веб и мобильных приложений!

Нажимая на кнопку "Подписаться" вы даете согласие на обработку персональных данных.

Популярное

X

Спасибо!

Теперь редакторы в курсе.