Результаты поиска
ITVDN: курсы программирования
Видеокурсы по
программированию
Подписка

300+ курсов по популярным IT-направлениям

Выбери свою IT специальность

Подписка
Подписка

300+ курсов по популярным IT-направлениям

Результаты поиска по запросу: начальный курс c
Асинхронное программирование и сопрограммы в Python

Автор: Алексей Орленко

Введение  В этом цикле статей будет рассмотрено асинхронное программирование при помощи сопрограмм в языке Python. В данной мы рассмотрим основные понятия и термины, которыми будем оперировать в дальнейшем, вкратце познакомимся с историей асинхронного программирования и состоянием дел в этой области на сегодняшний день. Также Вы узнаете о том, что такое сопрограммы и чем они могут быть полезны при написании кода в асинхронном стиле. Во второй статье будет рассмотрена реализация сопрограмм при помощи расширенных возможностей генераторов в Python (PEP 342), в третьей мы рассмотрим модуль asyncio (PEP 3156), который стал частью стандартной библиотеки в Python 3.4 и доступен в виде отдельного пакета для Python 3.3, а четвёртая статья цикла будет посвящена асинхронным функциям и сопрограммам в Python 3.5 с использованием нового синтаксиса async/await (PEP 0492). Понятие асинхронного программирования и сопрограмм Наверное, сегодня все уже слышали о Node.js и знают причины возрастания его популярности: один язык для фронтенда и бекенда (что в рамках данной статьи нас не интересует) и то, что он является платформой для построения асинхронных неблокирующих веб-серверов. Другой известной технологией, основанной на данной модели, является веб-сервер nginx, который часто используется на высоконагруженных проектах, занимая первое место по частоте использования среди 10000 самых посещаемых сайтов в мире (согласно данным W3Techs). Так что же такое асинхронное программирование и почему оно становится таким популярным, особенно в highload-проектах? На самом деле, асинхронное программирование существовало ещё на заре вычислительной техники, так как было важно максимально использовать аппаратные ресурсы машины. Но не так давно оно стало чуть ли не стандартной парадигмой программирования, настолько, что можно сказать, что большинство написанных в наши дни приложений являются асинхронными объектно-ориентированными программами. Давайте для наглядности рассмотрим это на примере графических интерфейсов пользователя. Что происходит, когда пользователь не производит никаких действий? Ничего. Программа должна ждать, пока пользователь укажет ей, что делать. Это ожидание можно реализовать в виде постоянных проверок: «а не нажал ли пользователь на кнопку?», «а не поставил ли пользователь курсор в поле ввода?». Таким образом, вычислительные ресурсы тратятся просто на то, чтобы проверить, не случилось ли что-нибудь. К счастью, практически все UI-фреймворки построены иначе. Они реализуют систему обработки событий. Любое действие пользователя – это событие, и разработчик может привязать к нему код – обработчик события. Это настолько привычный паттерн, что многие разработчики даже не задумываются, как он работает, хотя следовало бы. Например, представьте, что на экране есть три кнопки и пользователь каким-то образом нажимает на них практически одновременно. Запустятся ли три разных обработчика событий? Как правило, ответ – нет. Наиболее распространённая архитектура системы обработки событий – однопоточная, лишь с одним потоком исполнения. Однопоточные системы обработки событий практически всегда реализуются при помощи очереди событий или сообщений. Идея состоит в том, что, когда программа ничего не делает, её поток смотрит на наличие новых событий в очереди. Когда происходит событие, оно добавляется в очередь и, если поток исполнения в это время не делает ничего другого, он забирает следующее событие из очереди и выполняет соответствующий обработчик. Таким образом, события добавляются в очередь и UI-фреймворк предоставляет диспетчер, который выполняется в том же потоке, что и обработчики, вызывая их по мере надобности. В любой момент времени поток находится либо в каком-то обработчике события, либо в диспетчере, ожидая следующего события. Возникает логичный вопрос: каким же образом событие попадает в очередь, если поток исполнения занят обработкой другого события? Дело в том, что у операционной системы много потоков и тот код, который действительно взаимодействует с пользователем, выполняется отдельно от нашей программы и лишь посылает ей сообщения. Это пример асинхронной системы, так как мы не знаем, в каком порядке будет выполнятся код. Обработчики событий, с точки зрения программы, могут выполняться произвольно. Но в данной модели обработчики событий являются неделимыми действиями. И тут возникает проблема: если обработчик событий выполняется слишком долго, интерфейс как бы «подвисает». Причина в том, что пока обработчик события не вернул управление в диспетчер, следующий обработчик не будет выполнен. Решением является минимизировать количество работы, которое выполняет обработчик события. Но что если ему требуется совершить какие-то вычисления или загрузить данные с сервера? Очевидный ответ – выполнять обработчик этого события в отдельном потоке. Однако в JavaScript есть лишь один поток исполнения, а в Python, как известно, проблемой многопоточных приложений, которая значительно их замедляет, является Global Interpreter Lock (GIL). Тут мы подходим к тому, что существует два вида многозадачности: вытесняющая и кооперативная. Потоки и процессы используют вытесняющую многозадачность. Это значит, что операционная система производит квантование времени и постоянно переключается между разными потоками, сохраняя и восстанавливая их контекст выполнения. При использовании кооперативной многозадачности ветви кода, которые исполняются параллельно, сами отдают управление в определённые моменты времени. Кооперативная многозадачность как способ одновременного выполнения отдельных программ устарела и не используется в современных операционных системах, однако, идеи, заложенные в неё, оказываются очень полезными для организации выполнения асинхронного кода и позволяют при грамотном использовании максимально использовать вычислительные ресурсы в рамках одного потока (а при комбинировании этого подхода с традиционной многопоточностью, как в async/await в C#, можно строить крайне эффективные приложения). Можно построить обработчик события из множества асинхронных функций обратного вызова (callback-функций), которые управляются общим циклом событий, как это делается в Node.js, однако такой код сложно отлаживать и поддерживать. Значительно упрощают его паттерны Promise и Future, однако Python и некоторые другие языки программирования поддерживают механизм, который позволяет в данном случае обойтись без callback-функций – сопрограммы. Сопрограмма (coroutine) – это компонент программы, обобщающий понятие подпрограммы, который дополнительно поддерживает множество входных точек (а не одну, как подпрограмма) и остановку и продолжение выполнения с сохранением определённого положения. Сопрограммы в данном случае удобны тем, что позволяют писать асинхронный код в синхронном стиле. В последующих статьях мы рассмотрим механизмы их реализации в Python.
Сокрытие метода в С#

Автор: Редакция ITVDN

Введение В данной статье Вы узнаете, как скрывать метод и как вызывать скрытые элементы базового класса. Рассмотрим это на конкретных примерах. Создадим в Visual Studio консольное дополнение с классом Student. У класса Student два поля: FirstName и LastName, и метод, который выводит FirstName и LastName на экране консоли. using System; namespace methodHidingInCSharp {        class Student {              public string FirstName;              public string LastName;              public void PrintName() {                     Console.WriteLine(FirstName + " " + LastName);              }        }        class Program {              static void Main(string[] args) {              }        } } Создадим класс DiplomaStudent и GraduateStudent, которые унаследуют класс Student. using System; namespace methodHidingInCSharp {        class Student {              public string FirstName;              public string LastName;              public void PrintName() {                     Console.WriteLine(FirstName + " " + LastName);              }        }        class DiplomaStudent : Student {        }        class GraduateStudent : Student {        }        class Program {              static void Main(string[] args) {              }        } } Если нужно создать объект класса DiplomaStudent и GraduateStudent, это можно сделать главным методом, например:  class Program {        static void Main(string[] args) {              DiplomaStudent ds = new DiplomaStudent();              ds.FirstName = "Sam";              ds.LastName = "Fisher";              ds.PrintName();              GraduateStudent gs = new GraduateStudent();              gs.FirstName = "Aiden";              gs.LastName = "Pearce";              gs.PrintName();        } } Так как классы DiplomaStudent и GraduateStudent наследуют класс Student, можно вызывать всех участников, кроме частных (приватных). При запуске проекта получим следующий результат: Результат вышел таким, как и предполагалось. Но есть небольшая проблема. Невозможно установить, какой из этих двух результатов DiplomaStudent, а какой – GraduateStudent. Для этого создадим дополнение к имени (studentType)  с указанием Diploma или Graduate. Таким образом, просто смотря на имена, можно определить, какой из них DiplomaStudent, а какой – GraduateStudent. Вернемся к проекту. Теперь стоит создать метод PrintName, который будет одинаковым для обоих производных классов, и добавить DiplomaStudent и GraduateStudent, чтоб сделать их более читабельными и понятными. class DiplomaStudent : Student {        public void PrintName() {              Console.WriteLine(FirstName + " " + LastName + " - Diploma Student");        } } class GraduateStudent : Student {        public void PrintName() {              Console.WriteLine(FirstName + " " + LastName + " - Graduate Student");        } } Как известно, тот же метод используется в базовом классе. class Student {        public string FirstName;        public string LastName;        public void PrintName() {              Console.WriteLine(FirstName + " " + LastName);        } } В результате дочерний класс скрывает реализацию базового класса. При построении кода появляется зеленая волнистая линия. Если навести курсор мыши на линию, можно увидеть объяснение: если нужно специально скрыть унаследованный член, используйте новое ключевое слово. Чтобы скрыть унаследованный от производного класса член, используйте новое ключевое слово, например: class DiplomaStudent : Student {        public new void PrintName() {              Console.WriteLine(FirstName + " " + LastName + " - Diploma Student");        } } class GraduateStudent : Student {        public new void PrintName() {              Console.WriteLine(FirstName + " " + LastName + " - Graduate Student");        } } Запустите программу: Результат оправдал ожидания. Рассмотрим, как вызвать метод назад после скрытия. Существует несколько способов. Первый – использование основных ключевых слов. class DiplomaStudent : Student {        public new void PrintName() {              base.PrintName();        } } class GraduateStudent : Student {        public new void PrintName() {              Console.WriteLine(FirstName + " " + LastName + " - Graduate Student");        } Базовый класс реализуется, когда мы выполним программу. Второй способ – превратить тип переменной дочернего класса в базовый класс. using System; namespace methodHidingInCSharp {        class DiplomaStudent : Student {              public new void PrintName() {                     Console.WriteLine(FirstName + " " + LastName + " - Diploma Student");              }        }        class GraduateStudent : Student {              public new void PrintName() {                     Console.WriteLine(FirstName + " " + LastName + " - Graduate Student");              }        } В двух предыдущих случаях реализовывается метод дочернего класса и используется новое ключевое слово, чтобы скрыть реализацию базового метода. То есть, когда Вы запускаете приложение, оно печатает реализацию дочернего класса.  class Program {        static void Main(string[] args) {              DiplomaStudent ds = new DiplomaStudent();              ds.FirstName = "Sam";              ds.LastName = "Fisher";              re I have type - casted the child class reference variable into a base class                     ((Student)ds).PrintName();              GraduateStudent gs = new GraduateStudent();              gs.FirstName = "Aiden";              gs.LastName = "Pearce";              ((Student)gs).PrintName();        } } Запустите программу.  В предыдущем результате Вы получили базовую реализацию. Третий способ состоит в создании переменной базового класса, которая указывает на дочерний класс. class Program {        static void Main(string[] args) {              DiplomaStudent ds = new DiplomaStudent();              ds.FirstName = "Sam";              ds.LastName = "Fisher";              re I have type - casted the child class reference variable into a base class                     ((Student)ds).PrintName();              GraduateStudent gs = new GraduateStudent();              gs.FirstName = "Aiden";              gs.LastName = "Pearce";              ((Student)gs).PrintName();        } } Результат тот же. Источник: http://www.c-sharpcorner.com/UploadFile/219d4d/method-hiding-in-C-Sharp/
Создание Web API в MVC6

Автор: Редакция ITVDN

Введение ASP.Net Web API – это основа создания HTTP услуг широкого спектра клиентов, таких как браузеры, мобильные телефоны, планшеты и так далее. API должна быть совместима с современными браузерами, чтобы использовать эти услуги в простой форме. Мы можем быстро и просто сбрасывать служебные данные в браузер, а также приложения. Необходимость в Web API Если Вы нуждаетесь в Web Service и Вам не нужно SOAP, то API ASP.Net –лучший выбор. Он строит простые HTTP сервисы, основанные на базе существующей WCF. ASP.Net Web API на основе HTTP легко определяются. У них открытый исходный код. Легкая архитектура подходит для устройств с ограниченной шириной полосы, например, смартфонов. Создание простой Web API в ASP. NET MVC 6 Запустите Visual Studio 2015 Preview. В меню Файл выберите New > Project. В диалоговом окне New Project нажмите Tempates > Visual C# > Web и выберите ASP. NET шаблон проекта Web-приложений. Назовите проект "WebApplication1" и нажмите OK. В диалоговом окне New ASP.NET Project выберите "ASP.NET 5.0 Empty” шаблон. Проект включает в себя следующие файлы:   Global.json содержит настройки решения. В project.json находятся настройки проекта. Project_Readme.html – read me файл. Startup.cs содержит встроенный код конфигурации. Откройте файл Project.json. Добавьте библиотеки классов (class libraries) в разделе зависимостей (dependencies). ​ "dependencies": {           "Microsoft.AspNet.Server.IIS": "1.0.0-beta1",           " "Microfost.AspNet.Diagnostics": "1.0.0-beta1" } Затем откройте Startup.cs с кодом, показанным ниже.  public class Startup    {         public void Configure(IApplicationBuilder app)         {             // For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=398940              app.UseWelcomePage();             // app.UseMvc();          }     }  После отладки Visual Studio перейдите на http://localhost:port/ в браузере. Создание Web API Мы создадим Web API, чтобы упорядочить список клиентских продуктов. Сначала нужно добавить ASP.Net MVC6 в приложение. Добавьте пакет MVC6 в список зависимостей в Project.json. Используйте код ниже. "dependencies": {         "Microsoft.AspNet.Server.IIS": "1.0.0-beta1",         "Microsoft.AspNet.Diagnostics": "1.0.0-beta1",         "Microsoft.AspNet.Mvc": "6.0.0-beta1"       } Затем добавьте MVC в request pipeline в Startup.cs. Добавьте Using для Microsoft.Framework.DependencyInjection.   Добавьте следующий метод в Startup класс. using System; using Microsoft.AspNet.Builder; using Microsoft.AspNet.Http; using Microsoft.Framework.DependencyInjection;//add new  namespace WebApplication1 {     public class Startup     {         public void Configure(IApplicationBuilder app)         {                      app.UseWelcomePage();              app.UseMvc();         }         public void ConfigureServices(IServiceCollection services)         {             services.AddMvc();         }     } } Добавьте модель using System; using System.ComponentModel.DataAnnotations; namespace WebApplication1.Model {     public class Customer     {         public int CustomerId { get; set; }         [Required]         public string Name { get; set; }     } } Добавьте контроллер  using Microsoft.AspNet.Mvc; using System.Collections.Generic; using System.Linq; using WebApplication1.Model; namespace WebApplication1.Controllers {     public class HomeController : Controller     {                 static readonly new List<Customer> _items = new List<Customer>()             {                 new Customer  { CustomerId = 1, Name = "Henry" },                 new Customer { CustomerId = 2, Name = "John" },             };         public IEnumerable<Customer> Get()         {             return _items;         }         public IActionResult GetById(int id)         {             var its = _items.FirstOrDefault(x => x.CustomerId == id);             if (its == null)             {                 return HttpNotFound();             }             return new ObjectResult(its);         }         public void CreateCustomer([FromBody] Customer item)         {             if (!ModelState.IsValid)             {                 Context.Response.StatusCode = 400;             }             else             {                 item.CustomerId = 1 + _items.Max(x => (int?)x.CustomerId) ?? 0;                 _items.Add(item);                 string url = Url.RouteUrl("GetByIdRoute", new { id = item.CustomerId },                     Request.Scheme, Request.Host.ToUriComponent());                 Context.Response.StatusCode = 201;                 Context.Response.Headers["Location"] = url;             }         }         public IActionResult DeleteItem(int id)         {             var item = _items.FirstOrDefault(x => x.CustomerId == id);             if (item == null)             {                 return HttpNotFound();             }             _items.Remove(item);             return new HttpStatusCodeResult(204);         }     } } Выше описывается класс HomeController. Маршрутизация Атрибут маршрутизации определяет URL шаблоны контроллера. [Route("api/[controller]")] Методы HTTP [HttpGet], [HttpPost] и [HttpDelete] – атрибуты, определяющие методы HTTP для контроллера. public IEnumerable<Сustomer> Get() { }  //[HttpGet]  public IActionResult GetById(int id) { } //[HttpGetbyid}  public void СreateСustomer([FromBody] Сustomer item) { } // [HttpPost]  public IActionResult DeleteItem(int id) { } //[HttpDelete] {Customerid: int} int ограничивает переменную до соответствия целому числу, чтобы URL-адреса совпадали. http://localhost/api/home/1 http://localhost/api/home/42 Из этой статьи Вы узнали, как создавать Web API в MVC 6, используя модели, контроллер и HTTP методы. Источник: http://www.c-sharpcorner.com/UploadFile/85ed7a/create-web-api-in-mvc-6/
Читабельность программного кода

Автор: Редакция ITVDN

Введение Вам приходилось возвращаться к фрагменту кода, написанному год или месяц назад? Каково это было?  Это было просто, или приходилось вникать в код исходя из заметок? Если у Вас не получается быстро разобраться в коде и Вы задаете себе вопрос: «Что же я тогда имел ввиду?» – Вы определенно делаете что-то не так. Скорее всего, Ваш код работает правильно. И Вы знали его вдоль и поперек, когда над ним работали. Почему же Вы не можете его вспомнить сейчас? Быть может, он не был написан достаточно доступно и не соответствовал стандартам машинного кода? В этой статье Вы найдете полезную информацию о том, как научиться писать доступный не только для себя, но и для остальных разработчиков код. Пример использования стандарта оформления кода Рассмотрим это на следующем примере метода в C#: public string Transform(List<DateTime> s)         {             string d = null;             foreach (DateTime kc in s)             {                 if (kc > DateTime.Now)                 {                     d = d + kc + "\n";                 }                 else                 {                     d = d + "Delayed\n";                 }             }             return d;         } Скорее всего, Вы не можете понять, какую функцию он выполняет и как его можно использовать. Но после короткой реконструкции кода мы получим:  public string GetText(List<DateTime> arrivalTimes)         {             var stringBuilder = new StringBuilder();             foreach (DateTime arrivalTime in arrivalTimes)             {                 if (arrivalTime > DateTime.Now)                 {                     stringBuilder.AppendLine(arrivalTime.ToString());                 }                 else                 {                     stringBuilder.AppendLine("Delayed");                 }             }             return stringBuilder.ToString();         } Или если мы обратимся к оператору “?:”, мы получим:  public string GetText(List<DateTime> arrivalTimes)         {             var stringBuilder = new StringBuilder();             foreach (DateTime arrivalTime in arrivalTimes)             {                 string message = arrivalTime > DateTime.Now ? arrivalTime.ToString() : "Delayed";                 stringBuilder.AppendLine(message);             }             return stringBuilder.ToString();         } Что произошло с кодом? Некоторые изменения сделали наш код более читабельным: 1. Имя метода получило более понятное название. 2. Мы изменили названия переменных: 1. “kc” изменена на arrivalTime, 2. “s” изменена на arrivalTimes, 3. “d” изменена на stringBuilder, Это облегчит понимание того, за что отвечает каждая переменная и как она используется. 3. Скобки были стандартизированы. 4. Добавлены вкладки для читаемости, размещения и разметки в скобках. 5. Оператор “?:” был введен для того, чтобы сократить наш код до четырех строчек. 6. Добавлен класс StringBuilder, чтобы избежать конкатенации (“string” + “string”). Кто-то может возразить, что создание экземпляра StringBuilder будет замедлять метод из-за его распределения памяти. Но стоит помнить, что конкатенация струн создает много мусора в памяти, который вынужден чистить Garbage Collector. Считается, что ~ 5 непрерывных строк равны созданию реализации StringBuilder, так что если список состоит из пяти или более элементов, то производительность этого метода будет увеличена. А для больших коллекций этот метод будет работать в несколько раз быстрее. Правильный способ составления кода Давайте перейдем к другому примеру. Рассмотрим класс пользователя: public class User         {             public bool HasConfirmedEmail { get; set; }             public bool HasActiveAccount { get; set; }             public bool IsLoggedIn { get; set; }             public bool HasPremiumAccount { get; set; }             public bool StatusAutoGenerated { get; set; }             public DateTime LastStatusChange { get; set; }             public bool SetStatus(string status)             {                 // write to Data Base                 return true;             }         }  Метод, отвечающий за обновление статуса пользователя, который должен проверить, все ли свойства в правильном состоянии: public string UpdateStatus(string status, User user)         {             if (user.HasActiveAccount)             {                 if (user.HasConfirmedEmail)                 {                     if (user.IsLoggedIn)                     {                         if (user.HasPremiumAccount)                         {                             if (!user.StatusAutoGenerated)                             {                                 if (user.LastStatusChange < DateTime.Now.AddDays(-1))                                 {                                     if (user.SetStatus(status))                                     {                                         return "Updated";                                     }                                 }                             }                         }                     }                 }             }             return "Fail";         } Хотя этот код более понятный, чем первый, представленный в этой статье, он все еще не соответствует стандартам программного кода. Вот пример того, как этот код можно сделать немного лучше: const string OK = "Updated";         const string FAIL = "Fail";         public string UpdateStatus(string status, User user)         {             if (!CanUpdateStatus(user)) return FAIL;             if (!user.SetStatus(status)) return FAIL;             return OK;         }         public static bool CanUpdateStatus(User user)         {             if (!user.IsLoggedIn) return false;             if (!user.HasActiveAccount) return false;             if (!user.HasConfirmedEmail) return false;             if (!user.HasPremiumAccount) return false;             if (user.StatusAutoGenerated) return false;             if (!(user.LastStatusChange < DateTime.Now.AddDays(-1))) return false;             return true;         } Основные изменения, внесенные в этот код, чтобы улучшить его читабельность: Static method был создан, чтобы проверить возможность обновления статуса пользователя. Это делает метод UpdateStatus более понятным с первого взгляда. Кроме того, логика метода CanUpdateStatus может быть повторно использована в других частях системы, если они являются public и static. Все " if " были заменены, чтобы уменьшить вложения. Количество скобок значительно уменьшилось, и код гораздо легче читать и компилировать. Еще одним преимуществом данного условия является его масштабируемость. Представьте себе, что класс User имеет теперь еще три свойства, которые должны быть проверены перед обновлением статуса – будут необходимы еще три "if" выписки. Теперь Вы можете добавить только три (не более) линии в методе CanUpdatedStatus. Строки, которые представляют сообщения, были удалены из тела методов и были введены в постоянные переменные. Это помогает поддерживать код, потому что независимо от числа использований кода есть только одно место, где Вы должны изменить содержание сообщения, если это необходимо. Но, на самом деле, все тексты должны быть помещены в проект внешних ресурсов. Источник: http://blog.goyello.com/2014/12/11/clean-code/ 
Flappy Bird за 30 минут

Автор: Олег Загородний

Введение Не так давно была популярной такая мобильная игра, как Flappy Bird.  Причем по разным причинам из магазинов она пропала также неожиданно, как и появилась. Однако, учитывая ее популярность, сразу образовалось множество клонов. Не столь качественных, конечно. Но почему их было много? Все из-за того, что сама игра делается довольно просто и быстро. И в этой небольшой статье мы, разумеется, рассмотрим, как же сделать такую игрушку, как Flappy Bird. Все ресурсы (спрайты, шрифты) принадлежат непосредственно их авторам. Ресурсы Все, что нам понадобится из ресурсов игры – это несколько спрайтов и шрифт, как в оригинале. Спрайты найдены на просторах интернета. Шрифт был скачан по ссылке: http://www.dafont.com/04b-19.font?text=Flappy+Number Подготовка игровых объектов Сначала сделаем префаб игрока, то есть птичку. Для этого создаем на сцене пустой объект с именем Bird. Внутрь него помещаем объект-спрайт с именем Body и в свойство Sprite компонента Sprite Renderer помещаем спрайт нашей птички (из папки Sprites). Теперь на саму птичку (объект Bird) прикрепляем компонент Circle Collider 2D и задаем его радиусу значение 0.45. Также необходимо прикрепить компонент Rigidbody 2D. Здесь, пожалуйста, не перепутайте. Нам необходим именно 2D компонент, а не обычный Rigidbody. Ему задаем значение гравитации (Gravity Scale) равным 2.45 и запрещаем передвижение по оси X, чтобы наша птичка неожиданно не улетела куда-то в сторону. Теперь создаем C# скрипт c именем BirdHelper и тоже прикрепляем его к птичке (объект Bird). После всего этого перетягиваем объект Bird из окна Hierarchy в окошко Project, создав таким путем префаб птички. То есть в итоге на префабе Bird должно быть четыре компонента: Transform, Circle Collider 2D, Rigidbody 2D и скрипт Bird Helper. С главным героем пока что покончили. Приступим теперь к единственным препятствиям в игре – трубам. Мы с Вами поступим очень хитро. Так как в процессе игры каждая преграда – это пара труб (одна сверху, другая – снизу), их длину можно было бы регулировать и кодом в момент создания. Ведь если нижняя труба короткая, то верхняя – длинная. Но мы пойдем более простым путем. Наша преграда будет сразу состоять из двух длинных труб, и мы просто-напросто будем их ставить выше или ниже. Как на картинке ниже, где светлая рамка – границы дисплея. Что ж, дабы заделать префаб преграды, создаем на сцене пустой объект с именем Pipes и помещаем внутрь него два объекта-спрайта с именами TopPipe и BottomPipe. В Каждому из них в свойство Sprite компонента Sprite Renderer перетаскиваем спрайт Pipe (из папки Sprites). Объекту BottomPipe ставим положение по оси Y -4.5 (отрицательное). С объектом TopPipe проделываем аналогичные манипуляции, но позиция по оси Y будет 4.5, и еще необходимо повернуть его на 180 градусов вокруг оси Z. Почти готово. Осталось только настроить коллайдеры и прикрепить скрипт. Начнем с коллайдеров. Прикрепим  на объект Pipes компонент Box Collider 2D. А лучше сразу три. Первый настроим таким образом, как на картинке. Просто немного подкорректируем размер и зададим позиции по оси X значение -4.5. Как вы, думаю, уже догадались - это будет коллайдер для нижней трубы. Следующий Box Collider 2D настроим аналогично предыдущему, только позиция по оси X будет 4.5. Теперь последний коллайдер. Он, на самом деле, будет триггером, и с помощью него  мы сможем отследить, когда же игрок преодолел текущее препятствие. Вот такие настройки должны быть у этого коллайдера (уже триггера). И под конец создаем скрипт с именем PipesHelper и прикрепляем его на объект Pipes. Теперь перетягиваем объект Pipes из окна Hierarchy в окно Project, создав таким путем префаб для препятствий. Остался только фон. Создаем пустой объект с именем Background. Помещаем в него два объекта-спрайта с именами Part1 и Part2 и в свойство Sprite компонента Sprite Renderer помещаем спрайт Background. Объекту Part1 задаем размеры X: 2.6, Y: 2.6. С объектом Part2 выполняем такие же действия, но еще сдвигаем его вправо на 7.2 юнитов по оси X. После этого в объект Background помещаем еще два объекта-спрайта с именами Ground1 и Ground2. Им назначаем спрайты Ground из папки Sprites. Вот так должны выглядеть настройки объектов Ground1 и Ground2. Напоследок необходимо добавить коллайдер для земли и создать анимацию движения фона. Прикрепляем компонент Box Collider 2D на объект Background. Для того, чтобы создать анимацию, выделяем Background в окне Hierarchy и в окошке Animation нажимаем кнопку Create. Назовем ее BackgroundFloating. Вся задача данной анимации – передвижение фона влево, чтобы создать эффект, как будто игрок на самом деле летит вправо. После того, как анимация будет создана, на объект Background автоматически прикрепится компонент Animator и будет создан Animator Controller. Нам осталось только перейти в окно Animator и установить значение скорости анимации 0.2. Под конец создаем скрипт GameHelper и цепляем его на игровую камеру. На этом, пожалуй, все игровые приготовления завершены. Непосредственно сам процесс разработки Начнем, я так думаю, из скрипта главного персонажа. То есть BirdHelper’a. Реализация полета птички, как в оригинале, довольно проста. Под действием силы гравитации она будет постоянно падать, а при нажатии клавиши, допустим, Space, мы применим к ней силу по направлению вверх, используя метод AddForce на компоненте Rigidbody2D. using UnityEngine; public class BirdHelper : MonoBehaviour {     public float force;     private new Rigidbody2D rigidbody;     void Awake()     {         rigidbody = GetComponent<Rigidbody2D>();     }     void Update()     {         if (Input.GetKeyDown(KeyCode.Space))             rigidbody.AddForce(Vector2.up * (force - rigidbody.velocity.y), ForceMode2D.Impulse);         rigidbody.MoveRotation(rigidbody.velocity.y * 2.0F);     } } С помощью метода MoveRotation мы совершаем поворот птицы в зависимости он величины и знака значения текущего ее ускорения. Поле force у нас открытое и, разумеется, отобразится в окне Inspector. Напишем там 8. Это будет сила “прыжка”. Со скриптом главного героя почти всё. Вернемся к нему немножко позже. Перейдем к трубам. Их задача - двигаться на игрока, ведь сам по себе он лишь летает по вертикальной оси в процессе игры и так и не сдвинется по горизонтальной. Движение препятствий можно реализовать статическим методом MoveTowards структуры Vector3. using UnityEngine; public class PipesHelper : MonoBehaviour {     [SerializeField]     private float speed;            void Start()     {         Vector2 position = transform.position;         position.y = Random.Range(-1.5F, 2.5F);         transform.position = position;         Destroy(gameObject, 6.0F);     }        void Update()        {         transform.position = Vector2.MoveTowards(transform.position, transform.position - transform.right, speed * Time.deltaTime);        } } При появлении препятствие будет выбирать случайную позицию по оси Y, но такую, чтобы не было видно конца верхней или нижней трубы. Затем каждый кадр будет двигаться влево. Для этого, задавая конечную точку движения, мы вычитаем из текущей позиции препятствия вектор, направленный вправо от него. Также через 6 секунд объект Pipes будет уничтожен, чтобы не нагружать устройство, так как он свою задачу уже выполнил. К полю speed, представляющему скорость движения препятствия, мы применили атрибут SerializeField, чтобы оно было отображено в Inspector’e, ведь мы его закрыли. Перед тем, как перейти к скрипту GameHelper, добавим на игровую сцену объект-текст с именем ScoreText и настраиваем, как на рисунке ниже. Это будет текст для отображения количества очков игрока. Еще давайте добавим объект-кнопку с именем RestartButton. Она будет появляться, когда игрок проиграет, то есть при столкновении с каким-либо препятствием. В свойство SourceImage компонента Image нашей кнопки перетащите спрайт Button из папки Sprites. Вот настройки кнопки. А вот настройки текста внутри кнопки RestartButton. Непосредственно объект кнопки нужно деактивировать. Иерархия объектов на сцене будет выглядеть следующим образом. Какая же задача скрипта GameHelper? Он будет отвечать за генерацию новых препятствий, подсчет очков и их отображение. А еще за перезапуск уровня. Давайте глянем код. using System.Collections; using UnityEngine; using UnityEngine.UI; public class GameHelper : MonoBehaviour {     [SerializeField]     private Text scoreText;     private GameObject pipes;     public Button restartButton;     [HideInInspector]     public int score;     void Awake()     {         pipes = Resources.Load<GameObject>("Pipes");     }     void Start()     {         StartCoroutine(GeneratePipes());     }     void Update()     {         scoreText.text = "Score: " + score;     }     IEnumerator GeneratePipes()     {         Vector2 position;         while(true)         {             position = transform.position;             position.x += 6.0F;             Instantiate(pipes, position, Quaternion.identity);             yield return new WaitForSeconds(2.0F);         }              }     public void Restart()     { # if UNITY_5_2         Application.LoadLevel(Application.loadedLevel); #endif         Time.timeScale = 1.0F;     } } В первую очередь не забудьте подключить пространства имен UnityEngine.UI для работы с элементами пользовательского интерфейса и System.Collections, ведь там находится необходимый нам интерфейс IEnumerator, который мы будем использовать для карутины. Метод Reset отвечает за перезапуск уровня при нажатии соответствующей кнопки. Значит, настройки компонента Button объекта ResetButton необходимо немножко подправить. Так как сцена у нас не тяжелая, то мы можем позволить себе просто перезагружать ее полностью. Но, так как свойство timeScale статическое, его значение стоит снова установить в 1.0, чтобы при перезагрузке сцены время шло своим чередом. Метод GeneratePipes является карутиной и его задача – бесконечным циклом создавать препятствия с задержкой между каждыми в 2.0 секунды. Запускается карутина методом StartCaroutine при старте игры. А в методе Awake подгружается из папки Resources модель препятствия. В поля scoreText и restartButton, которые будут отображены в окне Inspector, необходимо перетащить соответствующие объекты текста очков и кнопки рестарта игры. Каждый кадр в свойство text объекта scoreText будет передавать текущее количество очков, которое хранится в поле score. Почти закончили. Осталось немного дополнить скрипт BirdHelper. using UnityEngine; public class BirdHelper : MonoBehaviour {     public float force;     private new Rigidbody2D rigidbody;     private GameHelper;     void Awake()     {         rigidbody = GetComponent<Rigidbody2D>();         gameHelper = Camera.main.GetComponent<GameHelper>();     }     void Update()     {         if (Input.GetKeyDown(KeyCode.Space))             rigidbody.AddForce(Vector2.up * (force - rigidbody.velocity.y), ForceMode2D.Impulse);         rigidbody.MoveRotation(rigidbody.velocity.y * 2.0F);     }     void OnCollisionEnter2D (Collision2D collision)     {         gameHelper.restartButton.gameObject.SetActive(true);         Time.timeScale = 0.0F;     }     void OnTriggerExit2D (Collider2D other)     {         gameHelper.score++;     } } Метод OnTriggerExit2D сработает в момент выхода игрока из триггера, который находится внутри препятствия и добавит нам одно очко. OnCollisionEnter2D будет вызван при столкновении с любым коллайдером, а это значит, что игрок проиграл. Время остановится и активируется кнопка перезапуска игры. На этом, пожалуй, всё. Скачивайте проект, изучайте, дополняйте, переделывайте либо просто удаляйте. Спасибо большое всем за внимание. Удачи в начинаниях и творческих успехов!
Что такое адаптивная верстка и зачем она нужна

Автор: Редакция ITVDN

Что такое адаптивная верстка? Преимущества мобильного адаптивного дизайна Почему адаптивный дизайн важен для бизнеса Как создать адаптивный дизайн Плавающая Сетка (Fluid Grid) Гибкий текст и изображения Медиа-запросы Пользовательское тестирование адаптивных сайтов Браузерное и устройство-зависимое тестирование на адаптивный дизайн Вдохновение от других адаптивных сайтов Будущее адаптивного дизайна для мобильных устройств Является ли ваш сайт Mobile-Friendly? Подводя итоги От редакции ITVDN Еще в 2015 году Google внедрил изменения в алгоритмы своей поисковой системы, которые теперь учитывают адаптированность сайта под мобильные устройства как важный пункт при ранжировании сайта. Дата была удачно названа Мобилгеддон (Mobilegeddon), как сравнение с Армагеддоном. Одно только такое введение требований от поисковиков к наличию мобильной версии сайта может оправдать важность адаптивного дизайна. Проще говоря, веб-сайт должен быть удобным для просмотра на смартфоне. Требования к адаптивной верстке включают в себя такие элементы дизайна, как: читаемый текст без необходимости его увеличения; достаточное количество места для целей касания (tap targets); отсутствие горизонтальной прокрутки. На сегодня уже почти 4 миллиарда пользователей используют смартфоны для серфинга в Интернете. Веб-сайты, не оптимизированные для всех небольших экранов смартфонов, имеют рейтинг в поисковых системах ниже тех, что выполнены адаптивно. Более 50% поисковых запросов в Интернете теперь происходит с мобильного устройства. Чтобы ваш веб-сайт мог работать с карманными устройствами (не создавая отдельное приложение), вам для начала стоит признать – адаптивная вёрстка важна для пользователей смартфонов. Давайте рассмотрим более детально, почему и как это происходит. Прежде всего ... а что такое адаптивная верстка и мобильный дизайн, и почему вы вообще должны о них заботиться?   Что такое адаптивная верстка? Адаптивный веб-дизайн (RWD - Responsive web design) создает систему, позволяющую одному сайту (с одним URL-адресом и одним источником контента) реагировать и адаптироваться к размерам устройства пользователя. Адаптивный веб-сайт создан с использованием верстки с гибким макетом, который подстраивается под размеры экрана устройства. По-сути, благодаря адаптивной верстке, ваш веб-сайт будет отлично выглядеть и хорошо работать как на настольном компьютере (или ноутбуке), так и на планшете, и в браузере мобильного телефона. В прошлом разработчики создавали более одного сайта, для соответствия страниц экранам разных размеров. С учетом того, что на рынке сегодня представлено много типов устройств, это кажется совершенно неэффективным… верно? Сам термин «адаптивная верстка» был фактически придуман в 2010 году веб-дизайнером Итаном Маркоттом. Сегодня адаптивная верстка в веб-дизайне уже не новая тенденция, а скорее проверенный временем способ мышления, стоящий за созданием сайтов. На сегодня наличие адаптивного веб-сайта больше не является еще одной возможностью для развития вашей инфраструктуры — это уже необходимость! Преимущества мобильного адаптивного дизайна Преимущество адаптивного макета номер один— это получение гарантии того, что любой пользователь на любом устройстве будет иметь наилучшие возможности взаимодействия с контентом на вашем сайте. Адаптивная верстка веб-сайта также является отличным способом улучшить контент на вашем сайте. Вы сможете убедиться, что те, кто использует мобильное устройство, видят всю важную информацию. Благодаря особенностям алгоритма Google, адаптивный веб-дизайн повышает видимость сайта в поисковых системах, поскольку он удобен для просмотра на мобильных устройствах. Сайт с качественным представлением контента на мобильном устройстве будет находиться в результатах поиска выше, чем сайт, хорошо отображающий контент только на десктопах.   Почему адаптивный дизайн важен для бизнеса Расширяется охват клиентов благодаря захвату пользователей небольших устройств (планшетов и смартфонов); Постоянный опыт работы с широкой аудиторией, который может увеличить количество потенциальных клиентов, продажи и конверсии; Аналитика, отслеживание и отчетность по версиям сайтов для десктопов и мобильных устройств могут быть в одном месте; Затраты времени и стоимость управления контентом снижается; Более 60 % запросов в Google на конец первого квартала 2019 делаются с мобильных устройств. Обратите внимание, что есть еще два способа, с помощью которых можно обеспечить взаимодействие пользователя с сайтом через мобильные приложения. Первый называется динамическим показом (Dynamic Serving), в котором используется один и тот же URL-адрес, но разные коды HTML и CSS. Страницы распознают устройство, на котором они просматриваются, и предоставляют соответствующий код. Второй способ — это вообще отдельный мобильный сайт. Когда пользователи посещают сайт с мобильного устройства, они отправляются на другой - мобильный URL-адрес. Вам следует выяснить, какой вариант лучше всего подходит для вашего присутствия в Интернете, прежде чем остановиться на одном. Учтите, что на Google ежедневно приходится более 5,6 миллиардов поисковых запросов. Рекомендуемая Google конфигурация для сайтов, оптимизированных для смартфонов, - это сайты с адаптивным веб-дизайном. Google даже предлагает тест на адаптивность сайта под мобильные устройства, чтобы вы могли увидеть, насколько легко посетитель может использовать вашу страницу на мобильном устройстве. Вы просто вводите URL страницы и получаете оценку. Как создать адаптивный дизайн Как сделать адаптивную верстку? Есть несколько моментов, о которых стоит подумать при создании адаптивного макета. Это процесс, который требует определенной системы проектирования и иерархии контента среди различных устройств. Три основных компонента адаптивного веб-дизайна включают в себя: Гибкая (плавающая) сетка - fluid grid; Гибкий текст и изображения; Медиа-запросы. Рассмотрим каждый из этих элементов детальнее.   Плавающая Сетка (Fluid Grid) Сетка является ключевым элементом для создания адаптивного макета. На сегодня сетки уже не являются чем-то новым. Веб-дизайнеры использовали сетки для создания веб-сайтов с самого начала. Однако в прошлом эти сетки имели фиксированную ширину и не позволяли поддерживать плавную компоновку. Гибкая сетка, используемая для адаптивных веб-сайтов, обеспечит вам гибкость и масштабируемость дизайна. Элементы будут иметь постоянный интервал, пропорции и смогут настраиваться на определенную ширину экрана в процентах. Гибкий текст и изображения Способ отображения текста зависит от того, на каком устройстве пользователь просматривает ваш сайт. Однако текст должен оставаться читаемым, несмотря ни на что. На адаптивных веб-сайтах есть возможность увеличить размер шрифта и высоту строки (расстояние между каждой строкой текста) для удобочитаемости. Гибкий текст и изображения настраиваются в пределах ширины макета, в соответствии с иерархией содержимого, заданной с помощью CSS (таблицы стилей). Текст на сайте с адаптивной версткой теперь может быть разборчивым независимо от устройства конечного пользователя. Благодаря гибкому контейнеру (внутри сетки) текст может переноситься с увеличением размера шрифта на небольших устройствах. Гибкие изображения могут оказаться более сложными из-за времени загрузки в небольших браузерах устройств. Но эти изображения могут масштабироваться, обрезаться или исчезать в зависимости от того, какой контент необходим для мобильных устройств. Медиа-запросы Медиа-запросы - это код, который обеспечивает гибкость макета на адаптивных веб-сайтах. Медиа-запросы определяют код CSS, который будет применен соответственно, в зависимости от размеров и ориентации устройства (например, книжная ориентация iPhone или альбомная ориентация iPad и т. д.). Медиа-запросы допускают существование несколько макетов дизайна, которые будут использовать одну и ту же HTML-кодированную веб-страницу. Все три указанных элемента являются основой адаптивной верстки. Однако есть и другие важные средства, которые могут помочь определить акценты и усовершенствовать адаптивный веб-дизайн ваших сайтов для мобильных устройств. Обратите внимание на: Пользовательское тестирование адаптивных сайтов Информация о том, как пользователи взаимодействуют с вашим сайтом, - бесценна и точно стоит того, чтобы заплатить за ее получение. Существует множество способов провести пользовательское тестирование, чтобы получить максимально полезную обратную связь. Такие сайты, как UserTesting.com, предоставляют пользователям тестирование за небольшую плату или бесплатно. Различные методы, такие как тестирование in-the-wild и карточная сортировка (Card Sorting), также могут помочь обнаружить неожиданные болевые точки и слабые места в использовании вашего продукта.   Браузерное и устройство-зависимое тестирование на адаптивный дизайн Убедитесь, что ваш адаптивный дизайн и верстка совместимы со всеми соответствующими браузерами и сохраняет целостность вашего пользовательского опыта и дизайна. Не полагайтесь только на изменение размеров окна браузера при тестировании адаптивного веб-дизайна для мобильных устройств. Попробуйте просмотреть сайт на как можно большем количестве физических устройств. Вы будете удивлены тем, что можно обнаружить при переходе от одной операционной системы к другой, от одного устройства – к другому.   Вдохновение от других адаптивных сайтов Точно также, как и выполняя любой другой дизайн-проект, обратитесь к опыту других людей. Найдите другие адаптивные веб-сайты, которые творчески обыгрывают концепцию адаптивного веб-дизайн. Задумайтесь над следующими вопросами: Какие веб-сайты или приложения вы часто используете на своем мобильном телефоне или других портативных устройствах? Почему вы предпочитаете один сайт другим, которые могут предоставлять аналогичные услуги? Предпочитаете ли вы использовать их на смартфоне или на настольном компьютере? Поиск ответов на эти вопросы может помочь вам найти слабые места, которые вы, возможно, никогда не замечали, во время ежедневного использования своего вебсайта. Будущее адаптивного дизайна для мобильных устройств Мы знаем, что Google требует следующих оптимизированных элементов для эффективного взаимодействия с пользователями мобильных интерфейсов, используя адаптивный веб-дизайн: Текст, с читаемым размером без необходимости его принудительного увеличения; Контент, который умещается на экране устройства, без необходимости горизонтальной прокрутки; Ссылки и кнопки, расположенные на достаточном расстоянии друг от друга, чтобы не было затруднений в работе с интерфейсом; Разумное время загрузки страниц; Не используйте Flash! Эти правила адаптивной верстки очень важно соблюдать. Рост числа мобильных устройств — это только начало перехода к более удобному использованию Интернета. Нужно быть уверенными, что пользователи могут просматривать ваш сайт в любом месте на любом устройстве, самые разнообразные мобильные носимые устройства становятся все более популярными. Важным моментом будет учитывать современные размеры гаджетов, чтобы понимать в вашей адаптивной верстке какие разрешения учитывать. К примеру, на 2019 год все еще лидирующим остается разрешение экранов - 360х640. Является ли ваш сайт Mobile-Friendly? Пройдите тест Google, чтобы узнать, насколько адаптирован ваш сайт для мобильных устройств. Ваш сайт получил зеленый свет? Отлично, значит вы прошли тест Google на адаптивность. Вы уже прочитали выше причины, почему адаптивный дизайн важен для пользователей вашего сайта. Вместо зеленого видите большие красные иксы? Значит вам следует начать предпринимать определенные шаги для оптимизации работы вашего сайта под пользователей мобильных устройств. Помните, что изменения в алгоритмах Google и требованиях к адаптивному дизайну в настоящее время мало учитывают планшеты, но, если вы сделаете ваш сайт полностью адаптивным - вы будете впереди тех конкурентов, которые этого еще не сделали!   Подводя итоги Согласно требованиям сегодняшнего времени, ваш веб-сайт должен отлично выглядеть и хорошо работать как на настольном компьютере, так и на планшете, и в браузере смартфона. Адаптивный веб-дизайн может помочь вам достичь этого. В этой статье мы ответили на общий вопрос «что такое адаптивный дизайн?». Есть три компонента адаптивного веб-дизайна: плавающая сетка, гибкий текст и изображения и медиазапросы. Помните о важности адаптивного веб-дизайна для вашего бизнеса.  Выполнение вашего сайта по всем правилам адаптивной верстки поможет вам: Увеличить охват потребителей на всех устройствах; Поддерживать постоянный качественный пользовательский опыт, который увеличивает удержание аудитории на сайте; Консолидировать данные аналитики, отслеживания и отчетности; Сократить время и стоимость управления контентом; Конкурировать в своей отрасли с другими брендами. Google привлекает к коммерческим сайтам более 85% трафика мобильного поиска и рекомендует применять на ваших сайтах адаптивный дизайн. Поскольку адаптивный веб-дизайн удобен для мобильных устройств, он помогает улучшить видимость в поисковых системах, что, в свою очередь, может увеличить количество посетителей вашего сайта. Увеличение трафика приводит к лучшей генерации потенциальных клиентов, дополнительным конверсиям и увеличению продаж - три основные причины, по которым вам нужен адаптивный веб-дизайн!   От редакции ITVDN Мы с вами рассмотрели необходимость адаптивной верстки для каждого современного сайта. Такой подход является конкурентным преимуществом для компании из любой сферы бизнеса. Если говорить о разработчике, то навыки создания адаптивных web-сайтов будут существенным конкурентным преимуществом при поиске работы. Специальные знания и навыки вы можете получить, обучаясь по видео курсам ITVDN. В первую очередь это курсы: HTML5&CSS3 Advanced Практический курс по верстке лендинга Создание адаптивного сайта с Bootstrap 3 Также вам могут быть интересны другие курсы и технологии, которые входят в программу обучения по специальностям Верстальщик сайтов и FrontEnd разработчик. По материалам статьи за авторством Сони Грегори.
Разработка под Android - советы начинающим

Автор: Армен Маилян

Овладейте языком Хорошие навыки работы со средой разработки и другими правильными инструментами разработки Знание компонентов приложения Понимание фрагментации, Android-приложений, потоков, загрузчиков и задач Правильный выбор необходимых инструментов разработки и последние советы Вывод Разработка приложений под различные мобильные платформы (Android,  iOs) – это то, на что ориентируются многие опытные и начинающие разработчики программного обеспечения. Ведь именно приложения делают телефоны «умными» смартфонами. Благодаря своим преимуществам приложения кардинально изменили возможности и функции вчерашних «звонилок». Выбирая разработку под Android как целевую платформу, у нас есть выбор между Java и Kotlin - основными языками программирования для этой платформы. Сейчас мы не будем вдаваться в детали их различий, и отвечать на вопрос «на чем писать приложения для Android?». Мы уже затрагивали этот вопрос недавно в соответствующей статье «Kotlin vs Java: что лучше для Android-разработки?». Сегодня мы остановимся на Java. Попробуем сформулировать основные советы в разработке приложений под андроид для начинающих.   Овладейте языком На сегодняшний день Java и XML являются двумя основными языками, используемыми при разработке приложений под Android. Поэтому знание и владение этими языками программирования и разметки является необходимым условием для разработки приложения под Android.  Задав себе вопрос «с чего начать программирование под андроид?», вы получите достаточно простой ответ – изучите основной язык разработки и основы ООП. Знания основ языка программирования Java должны включать в себя: • Понимание и применение пакетов (Packages) в Java; • Общее понимание ООП, понятия объектов и классов; • Понимание механизмов наследования, понимание и умение работать с интерфейсами; • Работа со строками и числовыми значениями, работа с дженериками; • Понимание функционирования коллекций и работы с ними; • Параллелизм. Правильное понимание Java и XML поможет вам создать/разработать более надежное и элегантное приложение для Android.   Хорошие навыки работы со средой разработки и другими правильными инструментами разработки Очень важно, чтобы, прежде чем приступить к полноценной разработке своего приложения, вы были хорошо знакомы с инструментами автоматизации сборки, а также с таким инструментом, как IDE - интегрированной средой разработки. В основном рекомендуется использовать Android App Studio IDE или Eclipse в качестве среды разработки. Применение их поможет вам изучить основы разработки и поможет вам улучшить качество вашего кода. Также советуем вам изучить такие механизмы как Apache Maven, Apache Ant и Gradle, поскольку они предоставляют собой мощный набор инструментов, помогающих управлять вашими сборками.   В процессе разработки важно, чтобы вы умели использовать инструменты и концепции контроля версий. Изучите git, а затем создайте репозиторий git-source (создав учетную запись в Bitbucket или GitHub). Чтобы получить представление об основных понятиях и условиях работы платформы, вы можете воспользоваться Git Pocket Guide.   Знание компонентов приложения Компоненты приложения — при разработке андроид-приложений выступают в роли основных строительных блоков. В свою очередь каждый из таких блоков представляет из себя отдельную точку, с помощью которой в ваше приложение может войти система. Хотя каждый из компонентов существует как отдельная сущность и играет свою отдельную роль, есть ряд компонентов, которые зависят друг от друга. При этом не все из них окажутся фактическими точками входа. Среди компонентов приложения выделяют пять разных типов, каждый из которых выполняет определенную роль и имеет свой собственный жизненный цикл, согласно которому он будет создаваться и уничтожаться. Они включают: Операции (Activity): это компонент андроид, представляющий один экран с пользовательским интерфейсом (к примеру, приложение для работы с электронной почтой может иметь одну Activity, отображающую список входящих писем, другую Activity - составляющую e-mail, и третью - читающую эти письма). Операции работают вместе, чтобы сформировать единый пользовательский опыт в андроид-приложении. Несмотря на это, каждая из Activity является независимой. Службы: компонент приложения в андроид, работающий в фоновом режиме и обеспечивающий выполнение длительных Activity и удаленных процессов. Этот компонент пользовательский интерфейс не предоставляет (например, пока пользователь обращается к интерфейсу другого приложения, он может проигрывать музыку в фоне). Поставщики содержимого или Content providers: компонент андроид-приложения, управляющий общим перечнем данных приложения. Используя этот компонент данные, хранимые в базе данных SQLite, в Интернете или файловой системе, могут быть запрошены или изменены (если допускает поставщик содержимого). Этот компонент также применим как для записи, так и чтения тех данных, что являются частными, а не общими для вашего приложения. Широковещательные приёмники или Broadcast receivers: компонент андроид-приложения, отвечающий на широковещательные сообщения, общие для системы. Большая часть таких сообщений происходят от системы. Broadcast receivers могут создавать в строке состояния уведомления, которые предупреждают пользователя, когда происходит широковещательное событие, хотя и не имеют пользовательского интерфейса. Как правило такой приёмник выполняет только минимальный объем работы, выступая для других андроид-компонентов в роли шлюза. Активация компонентов: асинхронное сообщение, также имеющее название - намерение (Intent). Активирует 3 из 4 компонентов (то есть сервисы, Broadcast receivers и Activity). Intents также связывают отдельные компоненты друг с другом во время выполнения, вне зависимости от того, принадлежит ли вашему приложению данный компонент или нет.   Понимание фрагментации, Android-приложений, потоков, загрузчиков и задач   Android — это фрагментированный рынок с множеством видов устройств и различных версий операционной системы. Обратите внимание, что, чем больше ваше устройство поддерживает различных устройств и/или версий, тем больше оно требует обслуживания и тестирования и, соответственно, больше будет сопутствующих расходов. Вам также потребуются соответствующие шрифты, ресурсы и макеты, которые помогут обеспечить наилучшее взаимодействие с различными характеристиками экрана. Вы придется держать во внимании всё множество поддерживаемых Android датчиков и средств пользовательского интерфейса.   Распределение версий Android по данным statista.com   Иногда, для выполнения фоновых задач, вам приходится использовать службы, которые должны выполняться непрерывно. Но, в ряде случаев, применение их может оказаться невозможным. Если вы хотите создать отличный и удобный пользовательский интерфейс, всегда следите за тем, чтобы поток никогда не блокировался. Поэтому длинные операции (вычисления, ввод-вывод, сеть и т. д.) должны выполняться асинхронно в фоновом режиме (в основном в другом потоке выполнения). Вот почему важно изучить средства параллелизма языка Java.   Правильный выбор необходимых инструментов разработки и последние советы Что нужно для создания приложения на андроид? Чтобы начать программировать под Android, вам подойдут весьма простые инструменты — это персональный компьютер с Mac или OS Windows, Linux. Сами же инструменты разработки ( IDE Eclipse, плагин ADT и Android SDK) – распространяются бесплатно. Android имеет некоторые уникальные параметры, которые вам следует учитывать при написании приложений под Android. Среди них: Производительность и скорость отклика: вы всегда должны реагировать на ввод пользователя в течение пяти секунд, в противном случае приложение выдаст ошибку ANR (ANR: application not responding - приложение не отвечает). Единственный доступный вариант - принудительно закрыть приложение. Пользователи заметят лаги более 100 мс: как уже упоминалось выше, поток пользовательского интерфейса никогда не должен блокироваться, потому что он только один. Ограниченные ресурсы: Wake-Lock (механизм, который заставляет устройство выполнять определенные действия, несмотря на рекомендацию менеджера батареи перевести устройство в спящий режим), следует использовать с осторожностью. Не обращайтесь лишний раз к элементам оборудования (например, GPS или акселерометру), потому что такие действия быстро разряжает аккумулятор.   Вывод Мы с вами рассмотрели ряд простых советов для тех, кто начинает программировать под андроид. Надеемся, что данные рекомендации помогут вам создавать новые высококачественные приложения. Если вы только раздумываете над направлением, в котором вам следует развиваться – рекомендуем посмотреть видео «Как стать Android разработчиком». В этом видео вы также сможете получить подходящие для вас ответы на вопрос «как начать программировать под Android?». Если вы уже определились с направлением развития и желаете получать знания в сфере разработки под Android - рекомендуем вам ознакомиться с нашим курсом подготовки Android Developer.  Если вы уже имеете определенные навыки в разработке и ищете дополнительных знаний по отдельным технологиям - вам наверняка будет полезен курс «Автоматизация сборки проектов с помощью Apache Maven». В свой очередь портал ITVDN.com желает вам успехов в обучении, интересных проектов и высокой зарплаты. По материалам статьи от Эшна Верна.
Введение в разработку приложений под iOS. Часть 3.

Автор: Volodymyr Bozhek

Здравствуйте, дорогие читатели. В этом уроке мы: создадим форму редактирования товара; рассмотрим понятие делегата и удобство его использования; добавим действия редактирования / удаления товара в списке товаров. Откройте проект Warehouse. В первую очередь, давайте изменим цвет View входа в систему с “Light Green” на “White”, я явно перестарался с выбором цвета в самом начале :). В будущих уроках, когда разберем, как пользоваться Assets, мы заменим фон на красивую картинку, подходящую по смыслу к этому приложению, а пока сделаем нейтральный цвет, не бросающийся в глаза. Для этого в панели навигатора откройте модуль “Main.storyboard”, выделите “View Controller”, затем в панели свойств откройте вкладку “Show the Attributes inspector”. Найдите свойство “Background” и установите значение “White”. Теперь найдите в библиотеке компонентов компонент “Table View Controller” и перетащите его в свободную область дизайнера рядом с “Supplies View Controller”, созданным в прошлом уроке. Выделите только что добавленный компонент. Найдите кнопку в дизайнере “Show Document Outline”, нажмите на нее, откроется панель документов. На этой панели разверните компонент “Table View Controller” и выделите компонент “Table View”. Затем в панели свойств откройте вкладку “Show the Attributes inspector”. Найдите свойство “Content”. По умолчанию у этого свойства установлено значение “Dynamic Prototypes”, установите значение “Static Cells”, в дизайнере вы увидите, что интерфейс контроллера изменился и отобразилось 3 строки. Разберем значения этого свойства. Значение “Dynamic Prototypes” используется, если вам необходимо иметь динамический набор данных, который будет постоянно изменяться. Установив это значение, обязательно необходимо переопределить методы протокола “UITableViewDataSource” для корректной работы контроллера. Значение “Static Cells” используется, если вам необходимо иметь статические данные, которые не будут меняться. Установив это значение, вам не нужно переопределять методы протоколы “UITableViewDataSource”. В данном примере мы устанавливаем это значение с целью удобства размещения элементов управления на нашей View. У нас будут ячейки с таким содержимым: ячейка под картинку, идентификатор товара, название товара, описание товара. Сейчас у нас 3 ячейки, надо чтобы было 4. В первой ячейке будет компонент “Image View”, в остальных 2 ячейках будут элементы управления “Label” и “Text Field”, в последней 4-й ячейке будут элементы управления “Label” и “Text View”. На панели документов для “Table View Controller”  выделите компонент “Table View Section”. В панели свойств откройте вкладку “Show the Attributes inspector”. Найдите свойство “Rows”. Сейчас у этого свойство установлено значение “3”. Измените значение на “4”, у вас появится 4 ячейка. В панели документов раскройте компонент “Table View Sections”, вы увидите список ячеек типа “Table View Cell”. Выделите первую ячейку. В панели свойств откройте вкладку “Show the Size inspector”. На этой вкладке можно управлять размерами компонента. Найдите свойство “Custom” и отметьте его галочкой. Затем найдите свойство “Row Height”. Установите значение этого свойства “144”, высота ячейки изменится. Перетащите на эту ячейку из библиотеки компонентов  компонент “Image View” и растяните его на всю область ячейки. Выделите компонент “Image View” и нажмите кнопку “Pin”. В открывшемся диалоговом окне снимите галочку с поля “Constrain to margin” и отметьте позиционирование относительно всех стенок ячейки. Нажмите кнопку “Add 4 Constraints”. В панели документов выделите вторую ячейку. Перетащите из библиотеки компонентов компонент “Label” на эту ячейку. Поместите его с левого края ячейки и растяните по высоте ячейки. В панели свойств откройте вкладку “Show the Size inspector”, установите свойство “Width” в значение “120”. Откройте вкладку “Show the Attributes inspector”, установите безымянное свойство с текстом “Label” на текст “Идентификатор”. Найдите свойство “Font”, нажмите на кнопку со значком “T”, откроется диалоговое окно задания свойств шрифта. Установите свойство “Style” в значение “Bold”, свойство “Size” в значение “12”. Нажмите кнопку “Done”. Представление должно выглядеть так: Из библиотеки компонентов перетащите компонент “Text Field” и расположите рядом с компонентом “Label”. Растяните компонент “Text Field” на оставшуюся ширину ячейки. Выделите элемент управления “Label”, нажмите кнопку “Pin”. Снимите галочку с поля “Constrain to margin”, отметьте позиционирование относительно верхней и левой стенок ячейки. Отметьте галочкой поле “Height”. Нажмите кнопку “Add 3 Constraints”. Выделите элемент управления “Text Field”, нажмите кнопку “Pin”. В диалоговом окне снимите галочку с поля “Constrain to margin”, установите позиционирование относительно левой, верхней, правой стенок ячейки, отметьте галочкой поле “Height”. Нажмите кнопку “Add 4 Constraints”. В панели документов выделите 3 ячейку. Повторите для нее все операции, которые были применены ко второй ячейке. Измените текст элемента управления “Label” на “Название”. Должно получиться вот так: В панели документов выделите последнюю ячейку, на вкладе “Show the Size inspectors”  установите в поле “Row Height” значение “144”, предварительно отметив поле “Custom” галочкой. Перенесите на ячейку два компонента “Label” и “Text View”. В          Установите ограничения для элемента управления “Label”, как мы устанавливали для предыдущих элементов управления “Label”, а для элемента управления “Text View” такие же ограничения, как для “Text Field”. Для элемента управления “Label” установите текст “Описание”, для элемента управления “Text View” уберите текст по умолчанию. Должно получиться вот так: В панели навигатора, добавьте новый модуль “Swift File” с именем “ProductViewController.swift”. Измените код, как показано ниже: Перейдите снова в дизайнер , выделите “Table View Controller”, с которым проводили изменения, в панели свойств, откройте вкладку “Show the Identity inspector”. Установите свойство “Class” значением “ProductViewController”, свойство “Storyboard ID” значением “ProductViewController”. В панели инструментов нажмите кнопку “Show the Assistant editor”. Для элемента управления “Image View” создайте переменную с именем “imageView”.       Во второй ячейке, для элемента управления “Text Field”, создайте переменную с именем “idTxt”. В третьей ячейке, для элемента управления “Text Field”, создайте переменную с именем “nameTxt”. В четвертой ячейке, для элемента управления “Text View”, создайте переменную с именем “descriptionTxt”. Должно получиться вот так: В панели навигатора, добавьте новый модуль “Swift File” с именем “ProductModel.swift”. Добавьте в него следующий код: Разберем добавленный код построчно. На 9 строке мы подключили пространство имен “Foundation” для класса “NSObject”. На 11 строке мы объявили класс с именем “ProductModel”, который наследуется от класса “NSObject” для того, чтобы считаться типом данных. На 12 строке мы объявили переменную с именем “productId” типа “Int” и инициализировали ее значение по умолчанию “-1”. На 13 строке мы объявили поле с именем “productImage” типа “String” и инициализировали ее значение по умолчанию “”. На 14 строке мы объявили поле с именем “productName” типа “String” и инициализировали ее значение по умолчанию “”. На 15 строке мы объявили поле с именем “productDescription” типа “String” и инициализировали ее значение по умолчанию “”. На 17 строке мы объявили параметризированный инициализатор класса “ProductModel” (это тоже самое, что и конструктор в языке программирования C#). Инициализатор - это метод, который вызывается при создании нового экземпляра класса. Данный инициализатор принимает аргументы с такими же именами, как имена полей в классе. Для того, чтобы инициализировать внутренние поля класса значениями полей аргументов. Мы левым операндом обращаемся к самому себе, через ключевое слово “self” и обращаемся к нужному нам полю, а правым операндом задаем значение аргумента. Мы плавно подходим к созданию делегата. В панели навигатора добавьте новый модуль “Swift File” с именем “ProductProtocol.swift”. Добавьте в него следующий код: Разберем добавленный код. На 11 строке мы объявили протокол с именем “ProductProtocol”. Протокол - это тоже самое, что и интерфейс в языке программирования C#. Экземпляр протокола через инициализатор создать нельзя, поскольку это только прототип, который не содержит реализации и используется в качестве описания и задания соглашений, которые разработчик должен реализовать сам в будущем. На 12 строке мы объявили метод прототип с именем “changeProduct”,  который принимает аргумент типа “ProductModel” с именем “model”. Откройте модуль “ProductViewController.swift”, добавьте поле с именем “delegate” типа “ProductProtocol?” и поле с именем “id” типа “Int” со значением по умолчанию “-1”. Должно получиться вот так: Добавьте после метода “viewDidLoad”, новые методы с именами “initNavigationButtons”, “backToParent”, “saveData”, которые ничего не принимают и ничего не возвращают. Код: Разберем построчно добавленный код. На 21 строке мы вызываем метод “initNavigationButtons”, когда View находится в процессе загрузки, чтобы инициализировать кнопки навигации. На 24 строке мы объявили метод с именем “initNavigationButtons”. На 25 строке мы переопределяем левую кнопку навигации, задаем ей текст “Отмена” и обработчик события на нажатие, метод “backToParent”. На 26 строке мы создаем кнопку с именем “saveButton” и текстом “Сохранить”, добавляем для нее обработчик событие на нажатие, метод “saveData”. На 27 строке мы обращаемся к экземпляру панели навигации контроллера “navigationItem” и вызываем от него метод “setRightBarButton”, который принимает два аргумента. Первый аргумент - это экземпляр добавляемой на панель навигации кнопки, второй аргумент - это стиль добавления кнопки, добавить с анимацией или без. Сам метод, как видно из названия, добавляет кнопку справа на панель навигации. Это вариант, как добавить правую кнопку из кода. На 30 строке мы объявили метод с именем “saveData”. На 31 строке мы обращаемся к нашему делегату с именем “delegate” и проверяем, если он инициализирован, тогда вызываем у него метод “changeData” и передаем туда модель данных, заполненную данными собранными с элементов управления. На 32 строке мы создаем экземпляр типа “ProductModel” с именем “model”. На 33 строке мы вызываем у делегата метод “changeData” и передаем туда экземпляр “model”. Данный метод будет реализован в классе “SuppliesViewController”. На 35 строке мы возвращаемся на предыдущую View (SuppliesViewController) в стеке иерархий вызовов View. На 38 строке мы объявляем метод с именем “backToParent”. Данный метод делает переход на предыдущую View (SuppliesViewController) в стеке иерархий вызовов View. Теперь откройте модуль “SuppliesViewController.swift”. Нам необходимо обновить его реализацию: Разберем обновленный код построчно. На 12 строке в классе SuppliesViewController мы наследуемся от протокола “ProductProtocol”. На 13 строке мы заменили тип данных для поля “supplies”. Тип данных был “[String]”, стал “[ProductModel]”. И сделали это поле статическим для того, чтобы была возможность доступа к нему из контроллера “ProductViewController”. На 29 строке мы реализовываем метод “changeProduct” протокола “ProductProtocol”. Именно этот метод будет вызываться при нажатии кнопки “Сохранить” в контроллере “ProductViewController”. На 30 строке мы проверяем идентификатор продукта, если “-1” - это означает, что это новый продукт. Иначе существующий продукт, и мы его обновляем. На 32 строке мы правым операндом генерируем идентификатор продукта путем вызова метода “makeNewProductId”. Данный метод возвращает значение типа “Int”, которое мы присваем левому операнду. Левый операнд - это поле “productId” экземпляра “ProductModel”. На 33 строке мы добавляем новый продукт в коллекцию продуктов. На 36 строке мы объявляем переменную с именем “changedIndex” типа “Int” со значением по умолчанию “-1”. В эту переменную мы запишем найденную ниже в цикле позицию продукта в коллекции “supplies”. На 37 строке мы в цикле проходимся по элементам коллекции “supplies” и ищем продукт, который нужно обновить. На 38 строке описано условие поиска продукта. На 39 строке, когда продукт был найден, мы сохраняем его позицию в переменную “changedIndex”. На 40 строке выходим из цикла. На 43 строке проверяем, если продукт был найден , тогда обновляем этот продукт. С 44 по 46 строку мы обновляем свойства продукта , значениями свойств модели, переданной аргументом метода “changeProduct”. На 49 строке мы запускаем переинициализацию “DataSource” для табличного представления, чтобы данные в ячейках обновились и добавились/удались обновленные данные. На 52 строке мы объявили метод с именем “makeNewProductId”, который ничего не принимает и возвращает значение типа “Int”. На 53 строке левым операндом мы объявили переменную с именем “sortProducts” типа “[ProductModel]”. Правым операндом мы на экземпляре коллекции “supplies” вызываем метод “sorted”, который принимает лямбда метод сортировки коллекции объектов и возвращает отсортированную коллекцию. У лямбда метода есть два аргумента, в них находятся экземпляры сравниваемых объектов из коллекции “suppliers”. Данный метод возвращает значение типа “Bool”. На 54 строке мы возвращаем условие сортировки по возрастанию. Сортировка производится по свойству “productId” класса “ProductModel”. На 56 строке мы обращаемся к последнему элементу отсортированной коллекции, тем самым получаем максимальный идентификатор продукта в коллекции и увеличиваем его на единицу. Теперь надо обновить реализацию метода “cellForRowAt indexPath”: Разберем код построчно. На 69 строке мы изменили вид обращения к коллекции “supplies”. На 73 строке мы изменили для экземпляра ячейки тип стиля. Был “.plain”, стал “subtitle”. На 74 строке мы левым операндом объявили константу с именем “model” типа “ProductModel”. Правым операндом мы инициализируем константу значением из коллекции “supplies”. На 75 строке мы записываем в свойство “tag” идентификатор продукта для этой ячейки. На 76 строке в элемент управления “Label”, который находится в верхней области ячейки, мы записываем название продукта. На 77 строке в элемент управления “Label”, который находится в нижней области ячейки, мы записываем описание продукта. На 78 строке мы активируем в ячейке информационную кнопку справа. При нажатии на эту кнопку мы будем редактировать продукт. Теперь нам надо подвязаться на событие нажатия на информационную кнопку в ячейке. Для этого необходимо переопределить метод протокола “UITableViewDelegate” ,реализованного в классе “UITableViewController” с именем “accessoryButtonTappedForRowWith”. Разберем код построчно. На 83 строке мы получаем экземпляр типа “ProductModel”, привязанный к ячейке, и сохраняем его в константу с именем “model”. На 84 строке мы производим поиск контроллера с именем “ProductViewController” в модуле “Main.storyboard”. На 85 строке на найденном экземпляре контроллера обращаемся к свойству “delegate” типа “ProductProtocol” и инициализируем его ссылкой на самого себя, тем самым говоря, что в этом классе уже реализован метод этого протокола с именем “changeProduct” и вызывать метод надо именно из этого класса. На 86 строке мы на найденном экземпляре контроллера обращаемся к свойству “id” и инициализируем его идентификатором продукта, привязанного к текущей ячейке. На 87 строке мы открываем контроллер “ProductViewController”. Редактирование мы почти сделали, осталось добавить инициализацию редактируемых данных в контроллере “ProductViewController”. Давайте реализуем еще в этом контроллере удаление данных. Для этого надо переопределить два метода объявленных в протоколе “UITableViewDelegate” и реализованных в классе “UITableViewController”. Эти методы называются “canEditRowAt IndexPath” и “commit editingStyle”. Обновите свой код в соответствии с представленным ниже: Разберем код построчно. На 90 строке мы переопределили метод “canEditRowAt IndexPath”, данный метод возвращает значение , которое говорит о том, активировать удаление строк или нет. На 91 строке возвращаем значение активировать. На 94 строке мы переопределили метод “commit editingStyle”, данный метод вызывается, когда мы нажали кнопку удалить на ячейке. На 95 строке мы удаляем продукт из коллекции “supplies”. На 96 строке обновляем содержимое таблицы. Теперь добавим кнопку добавления нового товара. Для этого обновим код метода “initNavigationButtons”.   Разберем код построчно. На 100 строке мы создали экземпляр кнопки с текстом “Новый продукт” и обработчиком события на нажатие - метод “newProduct”. На 101 строке мы добавили выше созданную кнопку в панель навигации контроллера в область справа. На 104 строке мы объявили метод “newProduct”, которые ничего не принимает и ничего не возвращает. На 105 строке мы производим поиск контроллера “ProductViewController” в модуле “Main.storyboard”. На 106 строке мы на найденном экземпляре контроллера обращаемся к свойству “delegate” и инициализируем его ссылкой на самого себя. На 107 строке мы  на найденном экземпляре контроллера обращаемся к свойству “id” и говорим, устанавливая значение “-1”, что мы создаем новый продукт. Теперь откройте модуль “Main.storyboard”, в нем на контроллере “ProductViewController” выделите элемент управления с идентификатором “idTxt”. В панели свойств на вкладке “Show the Attributes inspector” найдите свойство “User Interaction Enabled” и снимите галочку. Тем мы самым мы запретили редактирование значения этого поля. Теперь перейдите в модуль “ProductViewController.swift”. Обновите в нем код, как это показано ниже: Разберем добавленный код построчно. На 19 строке мы добавили метод с именем “initData”, который ничего не возвращает и принимает аргумент с именем “id” типа “Int”. На 20 строке мы проверяем идентификатор продукта, если он больше значения “-1”, значит продукт уже существует и содержит внутри себя данные, которые можно отобразить на текущей View. На 22 строке мы ищем продукт по идентификатору продукта, переданному аргументом в методе в коллекции продуктов “supplies”. С 23 по 25 строку мы заполняем элементы управления на пользовательском интерфейсе данными найденного продукта. На 33 строке в методе “viewDidLoad” мы добавили вызов метода “initData” и передали ему аргумент поле “id”, которое мы задаем в контроллере “SuppliesViewController”. Запустите приложение. На анимации выше видно, что мы вошли в систему, открыли товар на редактирование, откредактировали товар и изменения сохранились. Затем удалили товар. Теперь давайте проверим добавление нового товара: Проверили, добавление нового товара работает хорошо. Но все равно есть один нюанс, наше приложение на русском языке. А когда выполняли на ячейки жест справа на- лево, то показывалась кнопка удалить “Delete” на английском, давайте исправим это, чтобы показывалось русское название “Удалить”. Откройте модуль “SuppliesViewController.swift”, нам необходимо переопределить метод, объявленный в делегате “UITableViewDelegate” c именем “titleForDeleteConfirmationButtonForRowAt” и реализованный в классе “UITableViewController”. Добавьте следующий код, после метода “backToParent”: Я думаю, этот метод не стоит разбирать построчно, тут и так все понятно. Запустите приложение. На этом завершим наш урок. В следующем уроке мы разберем технологию 3D Touch и применим ее к нашему приложению для предварительного просмотра товаров. Добавим поле поиска в заголовок контроллера со списком товаров, реализуем поиск товаров. Реализуем протокол “UITextFieldDelegate”, чтобы скрывать клавиатуру при нажати кнопки “Ввод” на клавиатуре мобильного устройства. Разберем, как добавить собственную панель интрументов с кнопками.
Framework в С# для проверки отпечатков пальцев

Автор: Редакция ITVDN

Введение В наше время распознавание отпечатков пальцев является активным направлением исследований. Важным компонентом в системе распознавания отпечатков является алгоритм. В связи с проблемой данной сферы алгоритмы распознавания отпечатков пальцев делятся на две категории: алгоритмы проверки и идентификации. Цель алгоритмов проверки отпечатков пальцев является – определить, какой из двух отпечатков сделан одним пальцем, а какой нет. С другой стороны, алгоритмы идентификации делают поиск запроса отпечатка пальца в базе данных, ища отпечаток, сделанный одним и тем же пальцем. Насколько мы знаем, существуют сотни документов, касающихся проверки отпечатков пальцев, но нет ни одного фреймворка, позволяющего проверять отпечатки в сети. Поэтому вы должны осуществлять ваши личные настройки, тестировать выполнения алгоритмов распознавания ваших отпечатков. Более того, вы должны потратить много времени, выполняя алгоритмы других авторов, для сравнения с собственными. FVC-onGoing – наиболее связанный с работой нашего фреймворка в веб-системе. Данная система имеет такие ограничения: У вас нет доступа к другим алгоритмам, кроме своих. Это не фреймворк, поэтому вы не можете использовать другие компоненты программного обеспечения. Система не может быть использована с целью обучения, так как ученик не может посмотреть, как работают алгоритмы. После выполнения опыта используется база данных (стандартная или жесткая), вам необходимо ждать 30 дней для, того чтобы сделать следующий эксперимент, используя ту же базу данных. Вы не можете управлять базой данных. Таким образом, вы не можете использовать собственную базу данных либо редактировать существующую. Отсутствует доступ к тем отпечаткам, для которых ваш алгоритм не выполнился. Следовательно, вы не сможете проанализировать, почему ваш алгоритм не выполнился для того, чтобы исправить код. Вы не сможете создать эксперимент с помощью обычного протокола, для оценки выполнения Если в любом из указанных выше ограничениях для вас возникли проблемы, тогда используйте наш фреймворк. Наш фреймворк реализован на С# с использованием .Net Framework по двум главным причинам. Во-первых, С# стал одним из самых популярных языков программирования. Вторая причина в том, что инструменты, библиотеки и классы, доступные в .Net Framework, экономят много времени написания кода. Наш фреймворк позволяет экспериментировать в базах данных типа B от FVC2000, FVC2002 и FVC2004, и в базах данных типа А от FVC2002 и FVC2004. В этих экспериментах мы выполняем индикаторы the Fingerprint Verification Competitions (EER(%), FMR100(%), FMR1000(%), ZeroFMR(%), Time(ms) и ROC curves).  Кроме того, вы можете делать опыты даже с обычным протоколом и разными базами данных. Мы реализовали алгоритмы распознавания отпечатков пальцев, предложенный Tico и Kuosmanen, Jiang и Yau, Medina-Pérez и Qi. Важно обратить внимание на то, что вопреки алгоритму Qi - это набор шаблонов отпечатков пальцев, основывающийся на алгоритмах, мы реализовали только алгоритмы, сопоставимые протоколами ввода отпечатка пальца. Мы также сделали алгоритмы выделения признаков, предложенный Ratha, и ориентацию на получение изображения предложенную Sherlock. Данный фреймворк позволяет вам добавлять, как новые алгоритмы распознавания отпечатков, так и новые алгоритмы выделения признаков с минимальными усилиями и без перекомпиляции фреймворка. Одна из целей, которую мы преследовали, когда разрабатывали данный фреймворк, была сделать классы интерфейсов простыми и доступными. Таким образом, процесс добавления новых алгоритмов очень прост. В этой статье мы вкратце объясняем, как: экспериментировать над распознаванием отпечатков пальцев; увидеть шаблон отпечатка пальца после выполнения алгоритма; высчитать и вывести на дисплей отпечаток пальца; интегрировать ваши алгоритмы в фреймворк. Расширения данного фреймворка с целью исследований появились в https://sites.google.com/site/miguelmedinaperez/software/fprframework В данной статьей мы вкладываем следующие файлы: FingerprintRecognition_v2.2.zip: исходные файлы нашего фреймворка. Help.zip: Исходный код документации. Запуск исследования для распознавания отпечатков пальцев Извлеките файл “FingerprintRecognition.zip” и постройте решение. Далее вы можете отлаживать проект “FR.FVCExperimenter” или можете запустить “FR.FVCExperimenter.exe” в директорию, которая содержит сгенерированный узел. Данное окно откроет: В строке “Resources” записан путь к базе данных, которую вы собираетесь использовать, к примеру: “D:\PR Databases\Fingerprints\FVC2004\DB1_B”. Выберите подходящий вам тип опыта в всплывающем меню с названием “Experiment”. Используйте меню с названиями “Minutia Extractor”, “Orientation Image Extractor” и “Skeleton Image Extractor“ для выбора алгоритма, который будет использоваться для нахождения основных особенностей (отпечаток, ориентированное изображение и его образ). Используйте поле “Matcher” для выбора алгоритма распознавания отпечатков пальцев и поле “Feature Provider” для выбора алгоритма, который будет хранить и извлекать черты выбранных совпадений. Несмотря на то, что мы реализовали только одну черту распознавания для каждого совпадения, существуют сценарии, где вы используете несколько признаков для одного совпадения. Поле с названием “Properties” позволяет изменять параметры выбранного алгоритма. Кликните на кнопку “Execute Experiment” для запуска исследования. Данный опыт использует протокол оценки от the Fingerprint Verification Competitions. В этом опыте мы высчитали такие индикаторы: EER(%), FMR100(%), FMR1000(%), ZeroFMR(%), Время(мс) и  ROC-кривая. Эти индикаторы сохранены в файле с именем, сформированным в зависимости от выбранного вами алгоритма и окончанием ".Summary.csv". Этот файл сохраняется в папке с названием "Results" в той же папке, где хранятся отпечатки пальцев. Также сохранены еще два файла, один хранит в себе ложные соответствия отпечатков пальцев, другой – ложные несоответствия отпечатков. Если вы хотите сравнить 2 отпечатка и проверить их совпадение, кликните на кнопку “Visual Match”, после которой откроется форма “Visual Fingerprint Matching”. Загрузите отпечатки, которые вы хотите сравнить и нажмите кнопку “Match”. Экстрактор признаков и выбранный в “FVC Experimenter” режим также здесь используются для того, чтобы выполнить сравнение отпечатков пальцев. Ниже пример сравнения двух отпечатков. Визуализация очертаний отпечатка пальца Если вы хотите вывести картинку очертания отпечатка, тогда вам нужно использовать проект “FR.FeatureDisplay”. В поле “Fingerprint Feature Display” вы можете изменять экстрактор признаков и их изображение. В фреймворке мы используем классы для визуализации отпечатка, ориентированное изображение и скелет картинки. В следующем примере вы можете увидеть визуализацию приблизительного изображения отпечатка: Соответствие отпечатков вне фреймворка В данном разделе представлен пример использования фреймворка для сравнения двух изображений отпечатков в обычном пользовательском приложении. Он складывается из 3 шагов для сравнения 2 изображений отпечатков: загрузить картинку, извлечение признаков и их сравнение. В этом случае пользователям нужно добавить ссылки из их приложения к сборке FR.Core и FR.Medina2012. Сборки SHullDelaunayTriangulation и ImageProcessingTools должны быть добавлены в папку вывода, где появится бинарный файл. // Loading fingerprints var fingerprintImg1 = ImageLoader.LoadImage(fileName1); var fingerprintImg2 = ImageLoader.LoadImage(fileName2); // Building feature extractor and extracting features var featExtractor = new MTripletsExtractor() { MtiaExtractor = new Ratha1995MinutiaeExtractor() }; var features1 = featExtractor.ExtractFeatures(fingerprintImg1); var features2 = featExtractor.ExtractFeatures(fingerprintImg2); // Building matcher and matching var matcher = new M3gl(); double similarity = matcher.Match(features1, features2); Пример использования M3gl  показывает, как легко использовать фреймворк, и как хорошо сложен и не требует пояснений код. Правила хорошего дизайна применены в фреймворке и дают возможность пользователю легко заменить или изменить любой компонент. Добавление новых алгоритмов в фреймворк Первое, что вы должны знать - это то, что вам не нужно модифицировать приложение фреймворка для распознавания собственных алгоритмов, потому что мы используем Рефлекцию, для того чтобы загрузить все динамические алгоритмы во время выполнения. Вы можете создать столько приложений, сколько хотите в директории, которая содержит фреймворк. Для каждого нового приложения зайдите в настройки и укажите путь вывода со значением “..\bin\Release\”. Для добавления новой функции определения вам нужно наследовать с базового класса FeatureExtractor и реализовать метод ExtractFeatures(Bitmap image). Например, предположим, что вы хотите создать функцию определения типа MyFeature, дальше вы можете реализовать класс по примеру:  public class MyFeatureExtractor : FeatureExtractor {     public override MyFeature ExtractFeatures(Bitmap image)     {         // Place here your code to extract features     } } В случае, если новая функция была построена на некоторых существующих, вы можете поступить следующим образом: public class MyFeatureExtractor : FeatureExtractor {     public FeatureExtractor<List> MtiaExtractor { set; get; }     public FeatureExtractor OrImgExtractor { set; get; }     public override MyFeature ExtractFeatures(Bitmap image)     {         try         {             var mtiae = MtiaExtractor.ExtractFeatures(image);             var orImg = OrImgExtractor.ExtractFeatures(image);             return ExtractFeatures(mtiae, orImg);         }         catch (Exception e)         {             if (MtiaExtractor == null)                 throw new InvalidOperationException("Cannot extract MyFeature: Unassigned minutia list extractor!", e);             if (OrImgExtractor == null)                 throw new InvalidOperationException("Cannot extract MyFeature: Unassigned orientation image extractor!", e);             throw;         }     }     public MyFeature ExtractFeatures(List mtiae, OrientationImage orImg)     {         // Place here your code to extract features     } } Для каждой функции определения вы должны создать поставщик ресурса. Поставщик ресурса позволяет сохранять (полученный) в (выходной) файл ресурс, связанный с отпечатком. Фреймворк включает в себя поставщик ресурса для извлекания отпечатков (MinutiaListProvider), ориентированное изображение (OrientationImageProvider) и скелет картинки (SkeletonImageProvider). В следующем примере поставщика ресурсов для функции извлекания определены ниже. public class MyFeatureProvider : ResourceProvider {     public MinutiaListProvider MtiaListProvider { get; set; }     public OrientationImageProvider OrImgProvider { get; set; }     public override string GetSignature()     {         return "myf";     }     public override bool IsResourcePersistent()     {         return true;     }     protected override MyFeature Extract(string fingerprint, ResourceRepository repository)     {         try         {             var mtiae = MtiaListProvider.GetResource(fingerprint, repository);             var orImg = OrImgProvider.GetResource(fingerprint, repository);             return featureExtractor.ExtractFeatures(mtiae, orImg);         }         catch (Exception e)         {             if (MtiaListProvider == null)                 throw new InvalidOperationException("Unable to extract MyFeature: Unassigned minutia list provider!", e);             if (OrImgProvider == null)                 throw new InvalidOperationException("Unable to extract MyFeature: Unassigned orientation image provider!", e);             throw;         }     }     private MyFeatureExtractor featureExtractor = new MyFeatureExtractor(); } Пришло время создать новый алгоритм совпадения отпечатков пальцев. Предположим, вы хотите сравнить функции типа MyFeature, для этого вам необходимо создать «сравнитель» такой как: public class MyMatcher : Matcher {     public override double Match(MyFeature query, MyFeature template)     {         // Place here your code to match fingerprints     } } В случае, если вы реализовали алгоритм сравнения отпечатков, дальше вам необходимо изменить в коде ниже следующее: public class MyMatcher : Matcher, IMinutiaMatcher {     public override double Match(MyFeature query, MyFeature template)     {         List matchingMtiae;         return Match(query, template, out matchingMtiae);     }     public double Match(object query, object template, out List matchingMtiae)     {         // Place here your code to match fingerprints     } } Интегрированные встроенные алгоритмы в фреймворке Пользователям не нужно изменять фреймворк для интеграции обычных алгоритмов, так как Рефлекция загружает динамически, во время выполнения программы. В этом случае пользователи должны добавить новые алгоритмы к их собственным обычным сборкам. Для того, чтобы использовать существующие алгоритмы сравнения в фреймворке, первое, что необходимо сделать, создать поставщик ресурсов. Поставщик ресурсов позволяет сохранять (полученный) в (выходной) файл ресурсы, связанные с отпечатками пальцев. К примеру, предположим, что пользователи хотят интегрировать SourceAFIS SDK (http://www.sourceafis.org/) в фреймворк, следующая функция обеспечения может использоваться как: public class SourceAFISFeatureProvider : ResourceProvider {     protected override Person Extract(string fingerprint, ResourceRepository repository)     {         Fingerprint fp = new Fingerprint();         fp.AsBitmap = imageProvider.GetResource(fingerprint, repository);         Person person = new Person();         person.Fingerprints.Add(fp);         Afis.Extract(person);         return person;     }     public override string GetSignature()     {         return string.Format("sAFIS");     }     public override bool IsResourcePersistent()     {         return true;     }     private static AfisEngine Afis = new AfisEngine(); } А сейчас алгоритм сравнения отпечатков может быть записан в следующие классы: public class SourceAFISMatcher : Matcher {     public override double Match(Person query, Person template)     {         return Afis.Verify(query, template);     }     private static AfisEngine Afis = new AfisEngine(); } Результаты эксперимента Мы выполнили обширный эксперимент с алгоритмами сравнения отпечатков пальцев, пользуясь фреймворком. Выводы В данной статье продемонстрировали фреймворк в C# для распознавания отпечатков пальцев. Мы коротко объяснили, как выполнить опыты по распознаванию отпечатков и как интегрировать собственные алгоритмы в фреймворк. Мы предоставили несколько алгоритмов сравнения отпечатков пальцев и алгоритмов извлечения признаков, с помощью которых вы можете не только делать эксперименты, но и создать собственные приложения. Мы показали исходные коды всех алгоритмов, поэтому пользователь может использовать любую часть кода так же, как и любой компонент программного обеспечения. Источник: http://www.codeproject.com/Articles/97590/A-Framework-in-C-for-Fingerprint-Verification
Как правильно составить ТЗ на английском

Автор: Виктор Осадчий

Составляем ТЗ на английском О важности правильно составленного и правильно понятого технического задания в работе любой IT-команды говорить не стоит. Вопрос в том, как правильно написать его на английском. А если вы работаете в международной команде, это потребуется обязательно. Без паники! EnglishDom расскажет, как написать ТЗ на английском и не наделать ошибок. Итак, обо всех важных моментах - по порядку. SRS structure. Структура ТЗ В техзадании обязательно присутствуют следующие разделы: introduction - вступление, overall description - общее описание, specific requirements - специфические требования, а также возможны и appendices - приложения. Поговорим о каждом разделе отдельно. В introduction, помимо purpose - цели, может быть включен еще и scope - объем работ, definitions - термины, специфичные и принятые для этого ТЗ, и раздел overview, который дает общее представление о наполнении и структуре будущего проекта - identify the product, describe the content and the structure. Overall description - это раздел, который включает многое: product perspective - функционал будущего продукта, который описывает все внешние интерфейсы - describes all external interfaces, functions - главные функции продукта (summary of major functions), constraints, or anything that limits our options - возможные ограничения, use cases - сценарии использования. specific requirements - все, что можно назвать требованиями, идет в этот раздел. Собственно, это и есть его основной частью - body of the document. Итак, структура ТЗ в общем виде должна выглядеть так: Introduction: purpose / scope / definitions Overall description: product perspective / functions  / constraints / use cases  Specific requirements: all the possible requirements = body of the document Useful phrases: identify / limit options, content, structure, product, external interfaces Overview is a section that identifies the product and describes the content and the structure. - Общее представление - это раздел, который определяет проект и описывает наполнение и структуру. Anything that limits our options is described in the constraints. - Все, что как-либо лимитирует варианты действий, указано в разделе “ограничения”. All the possible requirements usually identify the body of the document. - Все возможные требования определяют главную часть документа. Характеристики  ТЗ Есть несколько ключевых характеристик ТЗ. Первое - оно должно быть correct - правильным, то есть up to the required standards for the quality, database integrity and so on - соответствовать требуемым стандартам по качеству, целостности базы данных и т.д. Второе - unambiguous and complete  - недвусмысленным и полным, чтобы четко описать проект и его функционал - describe what is the future project created for. Третье - consistent and detailed - последовательным и детальным, подробно описывающее, каким будет взаимодействие с людьми, оборудованием и другими внешними интерфейсами - how it interacts with people, hardware and other external interfaces. Четвертое - modifiable and traceable - поддающееся изменениям и их отслеживанию, то есть the one you can edit and control. Ряд фраз, которые вам пригодятся: imposed on an implementation - обязательный к внедрению, main considerations - ключевые факторы, operation environment - рабочая среда. Итак, ТЗ должно быть: Correct: up to the required standards for the quality / database integrity Unambiguous and complete: describe what is the future project created for Consistent and detailed: how it interacts with people, hardware and other external interfaces Modifiable and traceable: the one you can edit and control Полезные фразы: imposed on an implementation / main considerations / operation environment. SRS typical mistakes. Как не испортить ТЗ Столько деталей и нюансов, подпунктов, что сложно не ошибиться. Мы расскажем, чего стоит избегать. Первое: ambiguity - неясность. don’t give too much or too little information that may not be verified - не стоит давать чересчур много или мало информации, которую, к тому же, еще и проверить нельзя. Второе: requirements on users - требования к пользователям. Запомните, you can only assume what user will do - нельзя заставить пользователя, можно только предположить, что он будет делать. Третье: unnecessary or invented terms - термины, которые не нужны или выдуманы. Avoid any extra terms if you can say it simple - избегайте лишней терминологии, если все можно сказать проще. Бесполезные и ненужные в ТЗ вещи: forward reference - ссылка наперед, contradiction - противоречие, noise - лишняя информация, silence - недостаточное описание. В общем, придерживайтесь структуры, избегайте лишней информации, используйте ключевые фразы - и ваше ТЗ будет идеальным! Если же вы сомневаетесь в своем знании английского - в EnglishDom есть специальный курс “Английский для IT”, где вы сможете подтянуть все важные для it-шника темы. Научитесь писать резюме и CV, проходимть собеседования, обсуждать проекты и проводить переговоры, переписываться в чате, писать ТЗ и деловые письма, понимать носителей языка и читать зарубежные блоги.
Notification success