Русский
Русский
English
Статистика
Реклама

Разработка мобильных приложений

Перевод Десятикратное улучшение производительности React-приложения

14.06.2021 16:14:45 | Автор: admin

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


Около года назад в Techgoise я получил возможность поработать с большим React-приложением. Мы получили (унаследовали) готовую кодовую базу, внесли основные правки и начали добавлять в приложение новые интересные возможности.


Однако, мы часто получали жалобы от тестировщиков и конечных пользователей о том, что они видят эту злополучную ошибку. После проведенного анализа мы установили, что причина происходящего состоит в том, что приложение расходует целых 1,5 Гб памяти!


В данной статье я расскажу о том, как нам удалось добиться уменьшения этой цифры с 1,5 Гб до 150 Мб, что, как следствие, привело к улучшению производительности почти в 10 раз, и мы больше никогда не сталкивались с Ошибкой.


Поиск узких мест в производительности


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


1. Профилирование компонентов с помощью расширения для Google Chrome


Flamegraph (что условно можно перевести как граф в форме языков пламени), предоставляемый названным инструментом, является довольно информативным, но его анализ занимает много времени. Он помогает определить, сколько времени занимает рендеринг каждого компонента в приложении. Цветные полоски позволяют с первого взгляда понять, рендеринг какого компонента выполняется дольше всего. Точное время можно увидеть на самой полоске (если для этого хватает места) или при наведении на нее курсора. Ранжированная диаграмма позволяет расположить компоненты по времени рендеринга от большего к меньшему.


2. Снимки используемой памяти в Firefox


Данный инструмент предоставляет снимок "кучи", которая используется текущей вкладкой браузера. Древовидное представление снимка показывает следующие вещи:


  1. Объекты: объекты JavaScript и DOM, такие как функции, массивы или, собственно, объекты, а также типы DOM, такие как Window и HTMLDivElement.
  2. Скрипты: источники JavaScript-кода, загружаемые страницей.
  3. Строки.
  4. Другое: внутренние объекты, используемые SpiderMonkey.

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


3. Пакет why-did-you-render


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


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


Как же нам удалось решить эту задачу?


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


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


1. Удаление встроенных функций


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


import Child from 'components/Child'const Parent = () => ( <Child onClick={() => {   console.log('Случился клик!') }} />)export default Parent

В нашем коде имеется встроенная функция. С такими функциями сопряжено 2 главных проблемы:


  1. Они запускают повторный рендеринг компонента даже в случае, когда пропы остались прежними.
  2. Это, в свою очередь, увеличивает расход памяти.

В основном, это связано с тем, что в данном случае метод "передается по ссылке", поэтому на каждом цикле рендеринга создается новая функция и изменяется ссылка на нее. Это присходит даже при использовании PureComponent или React.memo().


Решение: выносим встроенные функции из рендеринга компонента.


import Child from 'components/Child'const Parent = () => { const handleClick = () => {   console.log('Случился клик!') } return (   <Child onClick={handleClick} /> )}

Это позволило снизить расход памяти с 1,5 Гб до 800 Мб.


2. Сохранение состояния при отсутствии изменений хранилища Redux


Как правило, для хранения состояния мы используем хранилище Redux. Предположим, что мы повторно обращаемся к API и получаем те же данные. Должны ли мы в этом случае обновлять хранилище? Короткий ответ нет. Если мы это сделаем, то компоненты, использующие такие данные будут повторно отрисованы, поскольку изменилась ссылка на данные.


В унаследованной кодовой базе для этого использовался такой хак: JSON.stringify(prevProps.data) !== JSON.stringify(this.props.data). Однако, на нескольких страницах он не давал желаемого эффекта.


Решение: перед обновлением состояния в хранилище Redux проводим эффективное сравнение данных. Мы обнаружили два хороших пакета, отлично подходящих для решения этой задачи: deep-equal и fast-deep-equal.


Это привело с уменьшению Цифры с 800 до 500 Мб.


3. Условный рендеринг компонентов


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


import { useState } from 'react'import { Modal, Button } from 'someCSSFramework'const Modal = ({ isOpen, title, body, onClose }) => { const [open, setOpen] = useState(isOpen || false) const handleClick =   typeof onClose === 'function'     ? onClose     : () => { setOpen(false) } return (   <Modal show={open}>     <Button onClick={handleClick}>x<Button>     <Modal.Header>{title}</Modal.Header>     <Modal.Body>{body}</Modal.Body>   </Modal> )}

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


Решение: рендеринг таких компонентов по условию (условный рендеринг). Также можно рассмотреть вариант с "ленивой" (отложенной) загрузкой кода таких компонентов.


Это привело к снижению расхода памяти с 500 до 150 Мб.


Перепишем приведеный выше пример:


import { useState } from 'react'import { Modal, Button } from 'someCSSFramework'const Modal = ({ isOpen, title, body, onClose }) => { const [open, setOpen] = useState(isOpen || false) const handleClick =   typeof onClose === 'function'     ? onClose     : () => { setOpen(false) } // условный рендеринг if (!open) return null return (   <Modal show={open}>     <Button onClick={handleClick}>x<Button>     <Modal.Header>{title}</Modal.Header>     <Modal.Body>{body}</Modal.Body>   </Modal> )}

4. Удаление ненужных await и использование Promise.all()


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


Обычно, для получения начальных данных мы обращаемся к API. Представьте, что для инициализации приложение требуется получить данные от 3-5 API, как в приведенном ниже примере. Методы get... в примере связанны с соответствующими запросами к API:


const userDetails = await getUserDetails()const userSubscription = await getUserSubscription()const userNotifications = await getUserNotifications()

Решение: для одновременного выполнения запросов к API следует использовать Promise.all(). Обратите внимание: это будет работать только в том случае, когда ваши данные не зависят друг от друга и порядок их получения не имеет значения.


В нашем случае это увеличило скорость начальной загрузки приложения на 30%.


const [ userSubscription, userDetails, userNotifications] = await Promise.all([ getUserSubscription(), getUserDetails(), getUserNotifications()])

Рассмотренные в данной статье приемы по оптимизации производительности React-приложения это лишь вершина айсберга. О более тонких приемах мы поговорим в одной из следующих статей.


Заключение


Итак, для повышения производительности React-приложения необходимо придерживаться следующих правил:


  1. Избегайте использования встроенных функций. В небольших приложениях это не имеет особого значения, но по мере роста приложения это негативно отразится на скорости работы приложения.
  2. Помните о том, что иммутабельность (неизменяемость) данных это ключ к предотвращению ненужного рендеринга.
  3. В отношении скрытых компонентов вроде модальных окон и раскрывающихся списков следует применять условный или отложенный рендеринг. Такие компоненты не используются до определенного момента, но их рендеринг влияет на производительность.
  4. По-возможности, отправляйте параллельные запросы к API. Их последовательное выполнение занимает гораздо больше времени.

Спустя 3 недели разработки (включая тестирование), мы, наконец, развернули продакшн-версию приложения. С тех пор мы ни разу не сталкивались в ошибкой "Aw! Snap".


Благодарю за внимание и хорошего дня!




Облачные серверы от Маклауд быстрые и безопасные.


Зарегистрируйтесь по ссылке выше или кликнув на баннер и получите 10% скидку на первый месяц аренды сервера любой конфигурации!


Подробнее..

C vs Kotlin

01.06.2021 08:12:59 | Автор: admin

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

Начнем с точки входа

В C# эту роль играет статический метод Main или top-level entry point, например

using static System.Console;WriteLine("Ok");

В Kotlin нужна функция main

fun main() = println("Ok")

По этим небольшим двум примерам в первую очередь заметно, что в Kotlin можно опускать точку с запятой. При более глубоком анализе видим, что в C#, несмотря на лаконичность показательного entry point, статические методы в остальных файлах по прежнему требуется оборачивать в класс и явно импортировать из него (using static System.Console), а Kotlin идет дальше и разрешает создавать полноценные функции.

Обьявление переменных

В C# тип пишется слева, а для создания экземпляра используется ключевое слово new. В наличии есть специальное слово var, которым можно заменить имя типа слева. При этом переменные внутри методов в C# остаются подвержены повторному присваиванию.

Point y = new Point(0, 0); var x = new Point(1, 2);x = y; // Нормально

В Kotlin типы пишутся справа, однако их можно опускать. Помимо var, доступен и val который не допускает повторного присваивания. При создании экземляров не нужно указывать new.

val y: Point = Point(0, 0)val x = Point(1, 2)x = y // Ошибка компиляции!

Работа с памятью

В C# нам доступны значимые (обычно размещаются на стеке) и ссылочные (обычно размещаются в куче) типы. Такая возможность позволяет применять низкоуровневые оптимизации и сокращать расход оперативной памяти. Для объектов структур и классов оператор '==' будет вести себя по разному, сравнивая значения или ссылки, впрочем это поведение можно изменить благодаря перегрузке. При этом на структуры накладываются некоторые ограничения связанные с наследованием.

struct ValueType {} // структура, экземпляры попадут на стекclass ReferenceType {} // ссылочный тип, экземпляры будут в куче

Что до Kotlin, то у него нет никакого разделения по работе с памятью. Сравнение '==' всегда происходит по значению, для сравнения по ссылке есть отдельный оператор '==='. Объекты практически всегда размещаются в куче, и только для некоторых базовых типов, например Int, Char, Double, компилятор может применить оптизмизации сделав их примитивами jvm и разместив на стеке, что никак не отражается на их семантике в синтаксисе. Складывается впечатление что рантайм и работа с памятью это более сильная сторона .NET в целом.

Null safety

В C# (начиная с 8ой версии) есть защита от null. Однако ее можно явно обойти с помощью оператора !

var legalValue = maybeNull!;// если legalValue теперь null, // то мы получим exception при первой попытке использования

В Kotlin для использования null нужно использовать два восклицания, но есть и другое отличие

val legalValue = maybeNull!! // если maybeNull == null, // то мы получим exception сразу же

Свойства классов

В C# доступна удобная абстракция вместо методов get/set, то есть всем известные свойства. При этом традиционные поля остаются доступны.

class Example{     // Вычислено заранее и сохранено в backing field  public string Name1 { get; set; } = "Pre-calculated expression";    // Вычисляется при каждом обращении  public string Name2 => "Calculated now";    // Традиционное поле  private const string Name3 = "Field"; }

В Kotlin полей нет вообще, по умолчанию доступны только свойства. При этом в отличие от C# public это область видимости по умолчанию, поэтому это ключевое слово рекомендукется опускать. Для разницы между свойствами, допускающими set и без него, используются все те же ключевые var/val

class Example {    // Вычислено заранее и сохранено в backing field  val name1 = "Pre-calculated expression"    // Вычисляется при каждом обращении  val name2 get() = "Calculated now"}

Классы данных

В C# достаточно слова record чтобы создать класс для хранения данных, он будет обладать семантикой значимых типов в сравнении, однако по прежнему остается ссылочным (будет размещаться в куче):

class JustClass{  public string FirstName { init; get; }  public string LastName { init; get; }}record Person(string FirstName, string LastName);...   Person person1 = new("Nancy", "Davolio");Person person2 = person1 with { FirstName = "John" };

В Kotlin нужно дописать ключевое слово data к слову class

class JustClass(val firstName: String, val lastName: String)data class Person(val firstName: String, val lastName: String)...val person1 = Person("Nancy", "Davolio")val person2 = person1.copy(firstName = "John")

Расширения типов

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

static class StringExt{  public static Println(this string s) => System.Console.WriteLine(s)      public static Double(this string s) => s + s}

В Kotlin расширямый тип должен находиться слева от метода, который можно разместить в любом месте. При этом расширить тип можно не только методом, но и свойством

fun String.println() = println(this)fun String.double get() = this * 2

Лямбда выражения

В C# для них есть специальный оператор =>

numbers.Any(e => e % 2 == 0);numbers.Any(e =>   {    // объемная логика ...    return calculatedResult;  })

В Kotlin лямбды органично вписываются в Си-подобный синтаксис, кроме того во многих случаях компилятор заинлайнит их вызовы прямо в используемый метод. Это позволяет создавать эффективные и красивые DSL (Gradle + Kotlin например).

numbers.any { it % 2 == 0 }numbers.any {  // объемная логика ...  return calculatedResult}

Условия и шаблоны

У C# есть очень мощный pattern matching c условиями (пример из документации)

static Point Transform(Point point) => point switch{  { X: 0, Y: 0 }                    => new Point(0, 0),  { X: var x, Y: var y } when x < y => new Point(x + y, y),  { X: var x, Y: var y } when x > y => new Point(x - y, y),  { X: var x, Y: var y }            => new Point(2 * x, 2 * y),};

У Kotlin есть аналогичное switch выражение when, которое, несмотря на наличие возможности сопоставления с образцом, не может одновременно содержать деконструкции и охранных условий, но благодаря лаконичному синтаксису можно выкрутиться:

fun transform(p: Point) = when(p) {  Point(0, 0) -> Point(0, 0)  else -> when {    x > y     -> Point(...)    x < y     -> Point(...)    else      -> Point(...)  }}// или такfun transform(p: Point) = when {  p == Point(0, 0) -> Point(0, 0)  p.x < y          -> Point(p.x + y, p.y)  p.x > y          -> Point(p.x - p.y, p.y)  else             -> Point(2 * p.x, 2 * p.y)}

Подводя итоги

Уложить в одной статье все отличия обоих языков практически нереально. Однако кое какие выводы сделать уже можем. Заметно что Kotlin-way скорее в том чтобы минимизировать количество ключевых слов, реализуя весь сахар поверх базового синтаксиса, а C# стремится стать более удобным увеличивая количество доступных выражений на уровне самого языка. У Kotlin преимущество в том что его создатели могли оглядываться на удачные фичи C# и лаконизировать их, а C# выигрывает за счет мощной поддержки в лице Microsoft и лучшего рантайма.

Подробнее..

4 бесплатных мероприятия по созданию бизнес- приложений в июне

03.06.2021 10:20:31 | Автор: admin

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

1. Технический марафон Microsoft Dynamics 365

10 июня, на русском10 июня, на русском

Приглашаем Вас принять участие в онлайн мероприятии Технический Mарафон Microsoft Dynamics 365, где Вы и Ваши коллеги познакомитесь с ключевыми сценариями использования платформы, а также с новыми предложениями, направленными на успешное внедрение и использование Dynamics 365.

Программа

10.00 - 10.20

Открытие технического марафона

Павел Чужмаров, руководитель отдела по технологическому развитию партнеров, Microsoft

Трек Dynamics 365 Finance and Operations (ERP)

10.20-10.50

Новости Finance and Operations

Владимир Ручкин, эксперт по бизнес-решениям, Microsoft

Вадим Корепин, ведущий функциональный архитектор, Microsoft

Александр Яковлев, эксперт по бизнес-решениям, Microsoft

10.50 -11.00

Использование хранилища Azure Synapse для построения высоконагруженных отчётов в D365 for Finance and Supply Chain

Илья Карякин, руководитель департамента корпоративных приложений, Awara IT

11.00 -11.10

Использование Electronic Reporting в интеграции с EDI и в печатных формах

Елена Терехова, функциональный архитектор департамента MS ERP, ГК Корус Консалтинг

11.10-11.20

Развертывание Dynamics 365 FO on premise: плюсы и минусы:

Денис Туров, заместитель руководителя департамента разработки, GMCS

11.20-11.30

Секреты успешного внедрения и поддержки Microsoft Dynamics 365 Finance на примере проекта в Финансовой группе БКС

Роман Приходченко, Dynamics 365&Power Platform Lead, Navicon; Андрей Жучков, Ведущий архитектор по ERP-решениям, Navicon

Перерыв, 5 минут

Трек Dynamics 365 Customer Engagement (CRM)

11.35-11.55

Новости Customer Engagement

Дмитрий Лобода, архитектор по работе с партнерами, Microsoft CEE Никита Усачев, эксперт по бизнес-решениям, Microsoft

11.55-12.05

Dynamics 365 Customer Insights и чем он отличается от for Sales/Marketing

Илья Карякин, руководитель департамента корпоративных приложений, Awara IT

12.05-12.15

Опыт внедрения Microsoft Dynamics Marketing в современном бизнесе.

Анатолий Инчеревский, эксперт по технологиям Microsoft, Ёлва

12.15-12.25

Эффективное управление сотрудниками в полях с помощью Dynamics 365 Field Service

Дарья Кагарлицкая, ведущий архитектор, Navicon

Перерыв 5 минут

Трек Power Platform

12.30-12.50

Новости Power Platform

Андрей Голубев, Power Platform Lead, Microsoft Никита Усачев, эксперт по бизнес-решениям, Microsoft

12.50-13.00

Построение low-code Центра компетенций и администрирование Power Platform

Михаил Головастиков, low-code / no-code евангелист , Руководитель GGroupp

13.00-13.10

Опыт реализации процесса найма сотрудников и разработки личного кабинета нового сотрудника и руководителя.

Андрей Браун, архитектор Low-Code решений, I-SyS

Подробности и регистрация.

2. Построение устойчивых цепей поставок

16 июня, на английском с субтитрами на русском16 июня, на английском с субтитрами на русском

Будьте впереди в сегодняшнем цифровом ландшафте с инструментами и обучением, чтобы быстро адаптироваться к сбоям и обеспечить непрерывность бизнеса. Виртуальный учебный день Microsoft Dynamics 365: создание устойчивой цепочки поставок знакомит вас с Dynamics 365 Supply Chain Management, упреждающим управлением активами, Dynamics 365 Commerce и многим другим. Это мероприятие разработано, чтобы помочь вам поддерживать непрерывную видимость и подготовить вашу организацию к тому, что будет дальше.

Во время этого учебного мероприятия:

  • Оптимизируйте свои процессы с помощью интеллектуальных цепочек поставок и упреждающего управления активами.

  • Улучшите свои розничные операции с Dynamics 365 Commerce.

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

Подробности и регистрация.

3. Microsoft Developers Meetup

16 июня, на русском16 июня, на русском

Приглашаем Вас принять участие в онлайн мероприятии Microsoft Developers Meetup, посвященное технологиям в области процессов разработки и сопровождения ПО.

На мероприятии вы узнаете от лучших экспертов в области разработки о том, какие технологии предлагает GitHub и Microsoft для разработчиков и DevOpsa. Специалисты и архитекторы Microsoft покажут, как размещать в Azure приложения с использованием контейнеров, а также какие возможности имеет предлагает GitHub для обеспечения безопасной и эффективной работы команд.

Партнёры Microsoft поделятся своим опытом и практикой реализации проектов трансформации процессов разработки и улучшения качества кода. Мероприятие ориентировано на разработчиков и руководителей разработки, а также ИТ-специалистов, специалистов по безопасности и ИТ-менеджеров, которые участвуют в процессе разработки программного обеспечения, а также занимаются выведением программных продуктов на рынок.

Программа

10:00 - 10:10

Opening

10:10 - 10:30

Microsoft Dev platform roadmap and Build news Microsoft

10:30 - 11:00

AppDev on Azure + Industry case DataArt

11:00 - 11:30

GitHub news and roadmap Microsoft

11:30 - 12:00

DevOps with GitHub Actions + Industry case Softline

12:00 - 12:30

Secure DevOps and Supply chain + build updates Microsoft

12:30 - 13:00

Secure Development on Azure + Industry case AwaraIT

Подробности и регистрация: регистрация приостановлена.

4. Microsoft Power Platform: App Maker

26 июня, на английском с субтитрами на русском26 июня, на английском с субтитрами на русском

Развивайте свой технический опыт и расширяйте свои методы работы с низким кодом на Виртуальном учебном дне Microsoft Power Platform: Конструктор приложений. Это бесплатное обучение поможет вам лучше разрабатывать, создавать, внедрять и управлять более разумными бизнес-решениями. Присоединяйтесь к нам, чтобы изучить инновационные стратегии для улучшения ваших базовых методов моделирования данных, дизайна взаимодействия с пользователем, а также анализа процессов и требований. Получите возможность максимально эффективно использовать Power Platform - и сразу же научитесь упрощать, автоматизировать и преобразовывать свои бизнес-процессы.

Во время этого учебного мероприятия:

  • Создайте приложение на основе модели в PowerApps.

  • Автоматизируйте рабочие процессы с помощью Power Automate.

  • Используйте AI Builder в Power Automate для улучшения ваших процессов.

Подробности и регистрация.

Подробнее..

Перевод Flutter 2.2 что нового

09.06.2021 12:21:23 | Автор: admin

Представляем свежий релиз Flutter 2.2, анонсированный на Google I/O. Да, оригинальная статья вышла ещё в мае, но мы считаем, что лучше поздно, чем никогда. Публикуем перевод статьи с комментариями Евгения Сатурова ex-Flutter TeamLead Surf, а ныне DevRel Surf.

Flutter 2.2 лучшая версия Flutter. С последними обновлениями разработчикам станет ещё проще монетизировать приложения через покупки, платежи и рекламу, а также подключить облачные сервисы и API, чтобы расширить функциональность приложений. Благодаря новым инструментам и языковым фичам разработчики смогут избежать целого класса ошибок, повысить производительность приложений и сделать их компактнее.

Основа Flutter 2

За основу Flutter 2.2 взят Flutter 2, который работает не только с мобильными устройствами, но и с вебом, ПК и встраиваемые системами. Он создан специально для мира, где нас окружают компьютеры: множество разных устройств и форм-факторов создают потребность в единообразии интерфейсов.

С помощью Flutter 2.2 все корпорации, стартапы, предприниматели смогут создавать решения высокого качества, способные по-максимуму раскрыть потенциал целевого рынка. Единственным ограничением станет креативность а не целевая платформа.

Flutter стал самым популярным фреймворком для кроссплатформенной разработки.

Рост Flutter отметили в недавнем исследовании мобильной разработки. Компания SlashData провела анализ и выпустила статью Mobile Developer Population Forecast 2021, согласно которой Flutter стал самым популярным фреймворком в кроссплатформенной разработке: его выбирают 45% разработчиков. Рост между Q1 2020 и Q1 2021 составил 47%. Интерес к Flutter продолжает расти: за последние30 дней одно из восьми приложений, загруженных в Play Store, написано на Flutter.

Комментарий Жени Сатурова

Это не удивляет нас в Surf. Нашей Flutter-компетенции уже больше двух лет. За это время мы стали свидетелями того, как мобильная индустрия в России и за её пределами совершила кульбит.

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

Сегодня клиенты приходят за Flutter целенаправленно и часто даже не рассматривают нативный подход. В наших кейсах можно найти несколько хороших примеров.

На I/O мы рассказали вам, что только в Play Store загружено более 200 тысяч приложений, написанных на Flutter. Эти приложения пишут очень серьёзные компании. Например:

  • Tencent их мессенджером WeChat пользуется более 1,2 миллиарда пользователей iOS и Android.

  • ByteDance создатели TikTok, которые уже написали 70 разных приложений на Flutter.

  • Другие компании, в том числе BMW, SHEIN, Grab и DiDi.

Конечно, Flutter используют не только крупные корпорации. Некоторые новаторские приложения делают компании, названия которых вы, возможно, и не слышали раньше. Например:

  • Wombo вирусное приложение с поющими селфи.

  • Fastly приложение для интервального голодания.

  • Kite красивое приложение для инвестиций и трейдинга.

Flutter 2.2

Основная цель релиза Flutter 2.2 улучшить процесс разработки, чтобы вы могли писать более надёжные и производительные приложения для клиентов.

Sound null safety теперь по умолчанию работает для новых проектов. Null safety защищает от ошибок типа null reference exception, так как даёт разработчикам возможность указать non-nullable типы в своём коде. А раз Dart абсолютно непротиворечив (sound), компилятор может не проверять на null во время выполнения. В результате производительность приложения повышается. Наша экосистема отреагировала быстро: около 5 000 пакетов уже обновлены и поддерживают null safety.

Комментарий Жени Сатурова

Жить в эпоху перемен всегда непросто, но весело. То же самое я могу сказать про переезд на Flutter 2. Для некоторых особенно масштабных наших проектов это стало настоящим испытанием. Процесс переезда продолжается до сих пор.

Хорошая новость заключается в том, что столь масштабных изменений во фреймворке и языке Dart в ближайшие годы не предвидится. Шутка ли к внедрению null safety в прод шли больше двух лет. Чтобы облегчить переезд коллегам из других компаний, мы оперативно обновили все наши пакеты, входящие в состав репозитория SurfGear.

Кроме того, в этом релизе есть множество возможностей повысить производительность:

  • Для веб-приложений фоновое кэширование с помощью сервисных работников.

  • Для приложений на Android поддержка отсроченного запуска загружаемых компонентов.

  • Для iOS мы разработали инструменты предварительной компиляции шейдеров.

Благодаря им удастся устранить или сократить лаги при первом запуске.

Комментарий Жени Сатурова

Многие ждали, что возможность прекомпиляции шейдеров для Metal поступит в stable уже в этом релизе, но увы. В утешение могу посоветовать попробовать собрать проект из dev-канала. Обещаю, вы непременно заметите разницу в FPS на iOS в анимациях и переходах.

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

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

Мы не только совершенствуем сам Flutter. Вместе с другими командами Google мы работаем над интеграцией Flutter в более масштабный стек технологий компании. В частности мы продолжаем разработку надёжных сервисов, с помощью которых разработчики смогут с умом монетизировать приложения. В этом релизе мы дополнили новый ads SDK: добавили в него null safety и поддержку адаптивных баннеров. Ещё мы добавили новый плагин для оплаты, который написали в сотрудничестве с командой Google Pay. С его помощью можно провести оплату за материальный товар как на iOS, так и на Android. Также мы обновили свой плагин для оплаты из приложения и соответствующую статью на codelab.

Комментарий Жени Сатурова

Радует, что экосистема вокруг Flutter развивается в правильном направлении. Не так много осталось незакрытых официальными плагинами вопросов. Возможность процессинга платежей через Google Pay существовала уже давно, но официальная реализация это гарантия качества решения. В нашем последнем релизе The Hole мы внедрили in_app_purchase ещё до выхода пакета в стабильный релиз. Надеемся, что теперь работать с ним станет ещё приятнее.

Так как Dart секретный ингредиент в составе Flutter, в этом релизе мы обновили и его. В Dart 2.13 мы расширили возможность интеграции нативного кода, добавив в FFI поддержку массивов и упакованных структур. В том числе появилась поддержка псевдонимов типов, с которыми код станет читабельнее, а некоторые сценарии рефакторинга получится осуществить менее болезненно. Мы продолжаем добавлять новые возможности интеграции с более широкой экосистемой через GitHub Action для Dart и Docker Official Image. Последний проходит тщательную проверку и оптимально подходит для внедрения бизнес-логики в облачную среду.

Не просто проект Google

Несмотря на то, что Google остаётся основным контрибьютором в проекты Flutter, нас радует, что экосистема Flutter развивается и за пределами компании.

За последние месяцы больше всего роста было связано с тем, что всё больше платформ и операционных систем стали доступны для Flutter. На Flutter Engage мы объявили, что Toyota собирается использовать Flutter в следующем поколении информационно-развлекательных систем своих автомобилей. А месяц назад Canonical отправили в свободное плаванье первый релиз Ubuntu с поддержкой Flutter, в том числе интеграцией со Snap и поддержкой Wayland.

Рост экосистемы отлично демонстрируют два наших новых партнёра. Samsung портирует Flutter на Tizen и оставляет репозиторий опенсорсным, чтобы остальные тоже могли в него контрибьютить. А Sony руководит разработкой решения для Linux на встраиваемых системах.

Дизайнеры тоже выигрывают от того, что проект опенсорсный: так, Adobe анонсировали, что обновили плагин XD to Flutter. Adobe XD даёт дизайнерам отличную возможность экспериментировать и копировать свои предыдущие работы. С улучшенной поддержкой Flutter дизайнеры и разработчики могут вместе работать над материалами а значит, ещё быстрее выводить классные идеи в продакшн.

И наконец, с нами продолжает сотрудничать Microsoft. Команда Surface разрабатывает с помощью Flutter решения для складных устройств. А на этой неделе в альфа канале появится поддержка Flutter для приложений на UWP, разработанных для Windows 10. Мы очень рады, что всё больше мобильных, десктопных, веб- и других приложений используют способность Flutter подстраиваться под разные платформы.

Комментарий Жени Сатурова

Дух open-source разработки захватывает кроссконтинентальные корпорации. Очень радует тенденция открытости и поддержки, даже когда речь идёт о взаимодействиях таких монстров, как Samsung, Google и Microsoft. Пока разработки ведутся в независимых репозиториях и никакого официального отношения к Flutter не имеют, но существует надежда, что скоро список поддерживаемых платформ расширится в полтора раза.

Создаём отличный пользовательский опыт

Мы в первую очередь стремимся помочь разработчикам создать отличный пользовательский опыт. Нам придаёт сил мысль, что разработка приложений может стать лучше: что мы можем расширить возможности, убрав традиционные препятствия между вами и аудиторией.

Нам нравится смотреть, какое применение вы находите для Flutter. Один из примеров проект от US Veterans Administration. В видео о том, как приложение на Flutter помогаетсолдатам с реабилитацией от посттравматического стрессового расстройства.

Мы проведём множество разных воркшопов, презентаций, посвящённых Flutter и ответим на возникшие у вас вопросы на Google I/O. А пока не забудьте попробовать нашу веб-фотобудку, написанную во Flutter: в ней можно сделать селфи с нашим талисманом Dash и её друзьями!

Подробнее..

Анонс эфира live-coding на SwiftUI

11.06.2021 12:20:14 | Автор: admin

Приглашаем на эфир live-coding на SwiftUI. Реализуем фичу для опенсорсного проекта StackOv, который написан полностью на SwiftUI. Обсудим, почему использовать некоторые системные View при работе со SwiftUI не всегда удачная идея. Посмотрим, как можно сделать по-другому. Эфир состоится 24 июня, четверг, в 18:30 мск.

РЕГИСТРАЦИЯ

В формате live-coding напишем облако тегов для опенсорсного проекта StackOv. Это мобильный клиент для Stackoverflow, сделанный полностью на SwiftUI.

Реализовать фичу облака тегов в SwiftUI можно двумя способами:

очевидным и не совсем правильным,

неочевидным, но почти правильным (почему почти узнаете во время эфира).

В чём суть: в SwiftUI для динамического подсчета размеров используется GeometryReader, он реагирует на любое движение, поэтому нагружает систему. Расскажем и покажем, как можно по-минимуму его использовать, чтобы избавиться от этих проблем.

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

Ведущие:

Гриша Бернгардт, iOS Lead Surf

Влад Климов,iOS разработчик Surf

Как попасть на эфир

24 июня, четверг. Начнём в 18:30 мск, планируем закончить примерно в 20:00. Трансляция на YouTube-канале Surf.

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

До встречи!

РЕГИСТРАЦИЯ

Подробнее..

Телеграмм-бот для анализа опционов

07.06.2021 10:04:02 | Автор: admin

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

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

Автор статьи реализовал анализ опционов с помощью телеграмм-бота, что дает возможность быстрого получения информации об инвестиционном портфеле на смартфоне.

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

Запоминание состояния бота между вебхуками

Бот получает сообщения от пользователя через встроенный в телеграмм механизм вебхуков. Каждый вебхук заново запускает программу, но для каждого пользователя необходим свой набор данных. Идентификация пользователей осуществляется через просмотр потока ввода:

$id_init = file_get_contents('php://input');$id=sbs($id_init, '"from":{"id":',',"is_bot":'); //в эту переменную записываем уникальный номер пользователяfunction sbs ($str,$m1,$m2){ //из строки str возвращает подстроку между двумя метками-словами m1 и m2$p1=strpos($str,$m1)+strlen($m1); //длина слова-метки слева$p2=strpos($str,$m2);return substr($str,$p1,$p2-$p1);}

Для каждого пользователя строится следующая структура данных:

  1. файл состояния: переменные флажки , которые описывают в частности, идентификационные номера сообщений ( message_Id) для дальнейшей их редакции, актуальное состояние ( ввод количества, ввод страйка и т.д.), вспомогательные данные для построения графика

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

  3. файлы для построения графика

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

Построение графика для анализа портфеля

График строится по состоянию на момент экспирации опционов, что дает возможность упрощенно представить график каждого инструмента в виде y=kx+b,

где y это размер прибыли/убытка на момент экспирации

х стоимость базового актива

После записи данных в портфель создаются файлы с расширением png с помощью библиотеки GD в несколько этапов:

1) определение Х-координат всех точек перелома на графике (очевидно, что сумма всех линий даст ломанную кривую)

2) определение масштаба изображения (средняя всех координат точек перелома по оси Х, максимальное отклонение от среднего, и максимальный размер по оси Y)

3) создание ассоциативного массива точек, в котором координата X это ключ, координата Y величина, для всей цифровой полуплоскости:

$typ опцион колл, пут или фьючерс

$q количество ( отрицательное продажа)

$cena цена приобретения ценной бумаги

$strike страйк для опционов

$x0 начальная координата по оси Х

$sx масштаб по оси Х

function pparr($typ, $q, $cena, $strike,$x0,$sx){ //функция выдает одномерный массив - координаты x=>y точек по //типу цб, направлению (покупка продажа), цене приобретения и страйку (для опционов)  if ($q<0) { $q=-$q; $drct='-'; }  else $drct='+'; $a=array(); $b=array(); $delta=$sx; //расстояние между точками равно масштабу $scalx for ($i=0;$i<740;$i++){ //кол во точек 740 определено заранее $xkk=$x0+$delta*$i; //значение по оси X if ($typ=='fut') { if ($drct=='+') $a[$xkk]=($xkk-$cena)*$q; else $a[$xkk]=(-$xkk+$cena)*$q; } if ($typ=='call'){ if ($drct=='+') { if ($xkk<=$strike) $a[$xkk]=-$cena*$q; else $a[$xkk]=$q*($xkk-$strike-$cena);} else { if ($xkk<=$strike) $a[$xkk]=$q*$cena; else $a[$xkk]=(-$xkk+$strike+$cena)*$q;}  } if ($typ=='put'){ if ($drct=='+') { if ($xkk<=$strike) $a[$xkk]=(-$xkk+$strike-$cena)*$q; else $a[$xkk]=-$q*$cena;} else { if ($xkk<=$strike) $a[$xkk]=($xkk-$strike+$cena)*$q; else $a[$xkk]=$cena*$q;}  } $b[(string)$xkk]=(string)$a[$xkk]; }return $b; };

4) создание файлов изображений, при этом одновременно строится график для каждой строки из портфеля ( зеленый цвет) и результирующий для портфеля ( красный цвет). Кроме того, know-how заключается в том, что одновременно строится еще четыре изображения для увеличения/уменьшения изображения по оси Х и по оси Y. За счет этого достигается эффект работы он-лайн с клавишами X+,X-,Y+,Y- под графиком. Таким образом, для каждого пользователя в каждый момент времени существует пять файлов изображения.

Анализ рисков опционного портфеля

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

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

Гарантийное обеспечение для фьючерсов считается по формуле, которая предложена самой Московской биржей:

ГО=БГО+(Цена-Расчетная_Цена)*БП;

где Расчетная_Цена определяется по результатам клиринга и практически равна цене базового актива на момент клиринга, определяется в пунктах

БП стоимость пункта в рублях, зависит, в частности, от курса доллара,

БГО базовое гарантийное обеспечение, определяется биржей, может произвольно увеличиваться, например, перед праздниками

Таким образом, по фьючерсам ГО считается достаточно просто, поскольку все данные есть в открытом доступе. Что касается опционов и тем более сочетаний их в разных комбинациях, Московская биржа не дает однозначного рецепта, вернее не дает данных для их расчета, а предлагает купить модуль расчета ГО.

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

Вот как выглядит покупка колла в нашем боте:

Запись в портфеле покупки опциона "колл" страйк 75000 дата экспирации 03.06.2021 по цене 25 Запись в портфеле покупки опциона "колл" страйк 75000 дата экспирации 03.06.2021 по цене 25 График зависимости прибыли/убытка по купленному опциону "колл" в зависимости от стоимости базового актива на дату экспирации График зависимости прибыли/убытка по купленному опциону "колл" в зависимости от стоимости базового актива на дату экспирации

Гарантийное обеспечение=23.

Что нам показывает график: если стоимость базового актива ( в данном случае стоимость фьючерса на курс рубля к доллару) [вечером] 03.06.2021 будет 75000 и ниже, то наш убыток составит 23 . При повышении этой стоимости до 75023 мы выйдем в безубыток, при дальнейшем росте получим прибыль.

Что мы имеем с точки зрения риска: не при каких обстоятельствах наш убыток не превысит сумму 23. Следовательно, наш опцион совершенно не похож на фьючерс, и в расчете ГО мы можем записать просто сумму 23.

Покупка пута примерно та же картина.

Продажа пута.

Запись в портфеле продажи опциона "пут" страйк 72750 по цене 44 с датой экспирации 03.06.2021Запись в портфеле продажи опциона "пут" страйк 72750 по цене 44 с датой экспирации 03.06.2021График зависимости прибыли/убытка по проданному опциону "пут" от стоимости базового актива на дату экспирацииГрафик зависимости прибыли/убытка по проданному опциону "пут" от стоимости базового актива на дату экспирации

Гарантийное обеспечение= 5436.

Можно убедиться, что при стоимости базового актива выше 72750 мы имеем прибыль 44. При снижении стоимости БА до 72706 мы выходим в ноль. При дальнейшем падении стоимости БА наш убыток НИЧЕМ НЕ ОГРАНИЧИВАЕТСЯ.

С точки зрения рисков это фьючерс, купленный по цене 72706. Подставляем это число в формулу ГО для фьючерса и получаем ГО для опциона! Этот ГО достаточно велик (5436), но может превратится в прибыль в течение нескольких дней.

Стоит ли овчинка выделки? Если при условных затратах сегодня 5436 мы получим через несколько дней 44? Мне кажется, риск очень велик. С другой стороны, курс рубля к доллару был таким примерно 3 месяца назад.

С продажей колла будет аналогичная ситуация.

А если одновременно продать пут и кол?

Запись в портфеле продажи опциона "пут" страйк 72750 и продажи опциона "колл" страйк 75000Запись в портфеле продажи опциона "пут" страйк 72750 и продажи опциона "колл" страйк 75000График зависимости прибыли/убытка по портфелю от стоимости базового актива на дату экспирации График зависимости прибыли/убытка по портфелю от стоимости базового актива на дату экспирации

Гарантийное обеспечение не изменилось!

С точки зрения риска понятно почему может реализоваться только один из сценариев либо по фьючерсу, купленному по примерно по 72700 (левая нога) либо по фьючерсу проданному по 75190 ( правая нога). Из них выбираем вариант

с наибольшим ГО , оно и будет мерилом риска.

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

Интерфейс телеграмм-бота

На экране отображаются следующие группы данных:

  • подробная инструкция по работе с ботом

  • текущие котировки ближайших фьючерсов по трем базовым активам

  • таблица Портфель, отображающая состав портфеля, сделанная с помощью интерфейса телеграмм ( можно редактировать)

  • значение гарантийного обеспечения

  • таблица, дублирующая состав портфеля, построенная как изображение формата png, которую можно копировать и сохранять

  • нижняя клавиатура, которую можно скрывать, с кнопками: Добавить позицию в портфель, Анализ портфеля с помощью графика, Обновить котировки

Таблица Портфель создана с помощью InlineKeyboard.

При нажатии на клавиши в этой таблице происходят следующие действия:

  • клавиша в столбце К-во редактирует количество ценных бумаг, соответствующее строке, в которой нажата клавиша

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

  • клавишей Х можно удалить строку.

Прочие клавиши в таблице заблокированы и служат только для передачи информации.

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

Заключение

В телеграмм-боте реализовано запоминание портфеля ценных бумаг для каждого пользователя. Под ценными бумагами понимаются опционы и фьючерсы, базовым активом для которых являются: курс рубля к доллару (Si), стоимость нефти брент (BR), а также индекс РТС (RI). Это самые высоколиквидные деривативы на московской бирже.

В телеграмм-бот заложен алгоритм подсчета гарантийного обеспечения, которое является мерой риска.

С помощью телеграмм-бота можно анализировать опционный портфель на графике прибылей/убытков (P/L график).

Протестировать телеграмм-бота можно по ссылке t.me/@test09062020bot. Или попробовать найти в телеграмме по названию опционный портфель.

Подробнее..

Нужно ль развивать прототипирование софта в медицине, психологии и биологии?

02.06.2021 20:09:34 | Автор: admin

Пришло время сказать правду, зачем я начал писать на Хабр. Хотя я занимаюсь mHealh, digital health и прототипированием софта всего 9 лет официально, цифровизация алгоритмов науки и информатизация практики меня интересуют более 20 лет. Недавно мои коллеги (или соавторы), которым я помогал в работе последние 4 года, в том числе и как сисадмин, попросили меня найти им программистов для улучшения evolutionary prototyping и допиливания мобильных приложений. На Хабре таких статей десятки вроде. Если вы считаете, что рыночно стоит доделать нижеперечисленные прототипы, то пишите, я им передам контакты и прибыль пополам (примерно) с ними. Сразу скажу, мне ничего от этого финансово не перепадёт, будет только удовлетворение, что две стороны нашли друг друга, как происходит в журнале Врач и ИТ, например))

Номер один. Персональная программа здорового образа жизни Баланс

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

2. Дифференциальная диагностика, терапия и профилактика головной боли

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

3. Программа для прогноза и профилактики метеоклиматической дизадаптации у людей при краткосрочных путешествиях

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

4. Балльная система оценки степени ограничений в социально значимых категориях жизнедеятельности

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

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

Подбирает алгоритм хирургического лечения пациентам с язвенными гастродуоденальными кровотечениями (ЯГДК), согласно последним национальным клиническим рекомендациям Российского общества хирургов и международным руководствам. Программа позволяет персонифицировано определять и проводить следующую тактику: ведение больных на догоспитальном этапе, оценку необходимости зондирования желудка, диагностическую и лечебную эндоскопию, ведение больных с массивной кровопотерей, медикаментозный гемостаз, прогнозирование рецидива ЯГДК, ведение больных при рецидиве кровотечения, ведение пациентов с кровотечениями, ассоциированными с приёмом нестероидных противовоспалительных препаратов. Программное обеспечение предназначено для работников здравоохранения профильных специальностей, ординаторов и студентов медицинских ВУЗов.

6. Мобильное приложение Лечение заболеваний желудка и двенадцатиперстной кишки

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

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

Обучает методике эндоскопических подслизистых инъекций аутоплазмы, обогащенной тромбоцитарными факторами роста в комплексной терапии гастродуоденальных язв, осложненных кровотечением, учитывая различные факторы, влияющие на процесс эпителизации язв желудка и двенадцатиперстной кишки и на частоту рецидивов кровотечения. Программа даёт возможность подобрать и реализовать алгоритм хирургической помощи пациентам, начиная от методики забора крови пациента, приготовления и периульцерозного введения аутоплазмы, обогащенной тромбоцитарными факторами роста, которая позволяет ускорить лечение длительно незаживающих гастродуоденальных язв у коморбидных пациентов и служит эффективным методом профилактики рецидивов кровотечения. Предназначена для работников здравоохранения профильных специальностей, ординаторов и студентов медицинских ВУЗов.

8. Программа для выполнения авторской методики внутрисуставных инъекций

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

9. САНАТА - метод аудиовизуальной психокоррекции

Разработана на основе алгоритмизированного руководства для специалистов (психологов, психиатров, психотерапевтов) САНАТА - метод неосознаваемой аудиовизуальной психокоррекции, отражающего описание метода, описание психотерапевтических механизмов, инструкцию с подробным алгоритмом проведения сеансов и описанием вариантов последовательностей этапов психокоррекции, с применением различных комбинаций из 4-х программ, используемых в методе и направленных на реализацию процедуры неосознаваемой аудиовизуальной психокоррекции. Данное программное обеспечение предназначено для оптимизации проведения процедуры аудиовизуальной психокоррекции. В программе представлены рекомендации для специалистов (психологов, психиатров, психотерапевтов) по использованию семантического аппарата и построению психотерапевтических суггестивных формул при проведении психотерапевтических сеансов, а также алгоритмы и варианты проведения самих процедур неосознаваемой аудиовизуальной психокоррекции.

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

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

11. Шкала оценки уровня ригидности

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

12. Тест оценки уровня агрессивности

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

13. Тест оценки тревожности

Основана на адаптированной авторами шкале Спилбергера с последующей дополнительной самодиагностикой и рекомендациями по терапии. Предназначена для скрининговой диагностики уровня тревожности у пользователей интернета с медицинскими и психологическими проблемами. Позволяет обнаружить начальные признаки тревожности с 12 лет. Может применяться для выявления тревожных расстройств разной степени тяжести и для выработки дальнейших лечебных и профилактических мероприятий.

14. Индивидуальный подбор растений для экологического и медицинского фитодизайна

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

15. Дифференцированный подбор рецепта медицинского и экологического фитодизайна

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

16. Учебное пособие для врачей Основы фитотерапии

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

17. Программа оптимизации и прогресса технологий инновационной продуктивности физических и юридических лиц

Предназначена для развития прикладной науки, изобретательства и патентного дела в России и мире. Программа подбирает индивидуально подходящие для физического и юридического лица различные инновации: готовые патенты или программы для ЭВМ для продажи; патентный поиск для создания новых патентов; научные публикации; подбирает новую формулу и описание патента или программы для ЭВМ; формат обучения созданию инновационной интеллектуальной собственности. С помощью кроссплатформенного онлайн-конструктора интерактивного выбора техник обучения, стимуляции, создания, регистрации и продаж патентов и программ возможно повышение знаний и навыков изобретательства и программирования методами психологии и ТРИЗ, с 16 лет и коммерческое внедрение российских научных разработок в биологии, медицине, образовании, информационных технологиях и т.п.

18. SmartMedFitoLabs BioSoftPatent

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

19. Feedback: diagnosis, rating, correction

Программа на базе ПрЭВМ 2017614931 помогает проводить через смартфон или планшет верифицированное (с видеофиксацией) голосование для подсчёта более объективного рейтинга и оценки специальных параметров наружной, печатной, телевизионной, радио-, интернет-рекламы, а также самих товаров и услуг для персонализации target group, lifetime value и покупок клиентов в кратко- и долгосрочном плане. Программа на 50 основных уровнях использует улучшенные (как ноухау) методы медицинской, социальной и медиапсихологии, психиатрии, психодиагностики, client-centered, cognitive therapy, аутотренинга, психогигиены, санологии, экологии человека, ТРИЗ, omni-channel brand health, customer experience marketing, cross-device service blueprint, brand lift, Яндекс.Взгляда, programmatic backstage adverts, addressable, connected и advanced television для индивидуализации продукции под боли и цели покупателей.

20. Подбор методов медицинской реабилитации психосоматических расстройств при постковидном синдроме

Данная программа является дополнением к программам для ЭВМ 2017614931 и 2019618242 и 2021612109, помогая, на основе актуальных научных и патентных открытых международных англоязычных источников информации проводить онлайн и офлайн персонифицированный подбор методов медицинской реабилитации психосоматических расстройств (депрессивных, тревожных, соматоформных) при постковидном синдроме (Post-COVID-19 syndrome, по МКБ-10 - U09.9), в частности: физиотерапии, психотерапии, лечебной физкультуры, Fitwel-техник, бальнеотерапии, курортологии, диетотерапии, фитотерапии, витаминотерапии, рефлексотерапии, медицинского фитодизайна, телемедицины, цифровых медицинских технологий, аппаратов и устройств для этого. Программа позволяет пациентам и специалистам в сфере здравоохранения подбирать подходящие под индивидуальные симптомы методики реабилитации.

21. Сервис Iotmedecohome для создания и оптимизации оздоровительных, зелёных и умных (IoT) загородных объектов недвижимости и экодевелопмента

Программа для ЭВМ является синергией развития авторских ПрЭВМ 2017614931 и 2019618242 на основе современных научных, патентных и практических открытых источников информации, помогая проводить онлайн и офлайн подбор, с учётом индивидуальных приоритетов, для улучшения подсчёта финансовых, временных затрат, эффективности: места проживания, типа дома, земельного участка, умных устройств, вида ипотеки, созаемщиков, субсидий, вакансий, оздоровительных устройств, экологических устройств, специальных растений, соседей, коливинга, риэлтора, архитектора, фитодизайнера, преподавателя, психолога, врача, тренера, массажиста, парикмахера, строителя, слесаря и т.п. Программа позволяет пользователям проектировать, покупать, строить и настраивать жилые модули семи размеров для медицинских, экологических и других целей в сфере Life Science.

Вот это первая треть программ, которым попросили найти программистов коллеги и соавторы, остальные потом как-нибудь обнародую. Через примерно недельку.

Кстати, началось моё увлечение созданием ИТ-продуктов и кодингом в 2001-м году, когда я сам, вот этими самыми кривыми ручонками, скачал программу Adobe PageMaker, скомпилировал, сверстал, поправил в тексте ссылки на интернет, распечатал свою первую книгу (я не пиарюсь, честно, она давно везде есть и не приносит прибыли абсолютно, как и всё остальное, что публикую здесь) и потом её размножил, разброшировал и стал раздавать коллегам и пациентам для пропаганды святого оздоровления и всемогущего саморазвития. Потом я стал потихоньку делать всякие простые приложения, экзешники и сайты на JavaScript, а затем учить разработке софта студентов медицинских и психологических специальностей.

Ну а сейчас мы стартап Fitwel-технопарк #ВОИР, который подали в акселератор ВШЭ, МТС и 3 другие места для инвестиций и ТП). Это как бы минитехнопарк, экоковоркинг, мобильное приложение и онлайн-сервис для создания и техноброкерства программ, зарегистрированных патентов членов ВОИР и затем готовых продуктов в сфере Fitwel, в том числе новых IoT-устройств для здоровья, также и против COVID-19. Используются там три специализированные методики и программы для ЭВМ и Big Data с техниками ТРИЗ для обучения студентов, аспирантов, научных и педагогических сотрудников основам изобретательства, регистрации интеллектуальной собственности, а также их дальнейшей коммерциализации. Всё это только в сферах экологии, медицины, биологии, психологии, фитодизайна и т.п.

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

Подробнее..

Кто, где, когда система компонентов для разделения зон ответственности команды

09.06.2021 18:07:37 | Автор: admin

Меня зовут Евгений Тупиков, я ведущий PHP-разработчик в Badoo и Bumble. У нас в команде более 200 бэкенд-разработчиков, которые работают над сотнями модулей и отдельных сервисов в наших приложениях. Но поначалу всё было не так масштабно. В 2006 году это был один проект, над которым работала небольшая команда. Каждый разработчик хорошо понимал, как всё устроено: легко ориентировался в коде, знал, какие есть сервисы и как они взаимодействуют между собой. Однако по мере роста проекта всё больше времени занимал поиск хранителей знаний тех, кто отвечает за ту или иную функциональность и к кому можно обратиться с вопросом или предложением.

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

Предыстория

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

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

  • @team команда, ответственная за данную часть системы;

  • @maintainer человек, разрабатывающий данную функциональность (таких сотрудников может быть несколько).

/** * @team Team name <team@example.com> * @maintainer John Smith <john.smith@example.com> * @maintainer .... */

Такой подход очень просто внедрить и использовать. Например, можно настроить шаблон в PhpStorm и нужные теги будут автоматически проставляться при создании нового файла. Мы ещё сделали отдельный Git hook, следящий за тем, чтобы у всех файлов были проставлены нужные теги в требуемом формате.

Но вскоре такой подход стал терять свою гибкость. В компанию приходили новые люди, кто-то переходил из одной команды в другую и каждый раз нужно было актуализировать информацию об ответственных. Кроме того, эта информация дублировалась при настройке мониторинга в Zabbix. И если поправить код это довольно тривиальная задача, то обновить список получателей уведомлений о результатах определённой проверки быстро не получится. Нужно поставить задачу отделу мониторинга и ждать, когда он выполнит её в рамках заданного процесса.

Нам же хотелось иметь возможность обновлять список ответственных в одном месте. И желательно, чтобы все остальные системы автоматически подхватывали изменения.

Так мы пришли к компонентному подходу.

Что такое компонент

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

Компонент это не обязательно функциональность, непосредственно связанная с кодом. Компонентом может быть и организационный процесс, например выпуск новой версии приложения.

При переходе на компонентный подход мы сформировали ряд правил и ограничений:

  • структура компонентов должна быть линейной;

  • каждая команда должна иметь свой набор компонентов (один и тот же компонент не может относиться к нескольким командам);

  • для каждого компонента должен быть задан список ответственных, при этом оптимальное количество ответственных за один компонент двачетыре человека;

  • только менеджер или тимлид команды может добавлять и удалять компоненты;

  • у каждого компонента должен быть уникальный идентификатор (alias).

Для управления компонентами у нас есть специальный интерфейс в интранете. Страница компонента выглядит следующим образом:

Пример страницы компонента в интранете Пример страницы компонента в интранете

Мы видим, что у компонента есть:

  • уникальный идентификатор;

  • email;

  • название команды, которая отвечает за данный компонент;

  • название проекта, к которому относится компонент, в Jira;

  • краткое описание, которое помогает понять, для чего нужен компонент и какая у него зона ответственности;

  • список ответственных: у каждого компонента есть владелец, который может его редактировать (это может быть как менеджер или тимлид команды, так и другой человек, который был явно указан как владелец при добавлении компонента);

Как мы используем компоненты в коде

Докблок файла

/** * @component component_alias */

Мы доработали Git hook, проверяющий докблок. Он следит за тем, чтобы файлы, в которые были внесены изменения, содержали тег @component и чтобы указанный компонент существовал.

remote: ERROR in SomeClass.php:        remote: * Unknown @component: UnknownComponent. You have to create component before using it in the code   

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

Сервис для работы с компонентами в коде

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

$componentManager = new \Components\ComponentManager();$component = $componentManager->getComponent('component_alias');$recipients = [];foreach ($component->getMaintainers() as maintainer) {    $recipients[] = $maintainer->getEmail();}

или найти дежурного по компоненту:

$componentManager = new \Components\ComponentManager();$component = $componentManager->getComponent('component_alias');foreach ($Component->getMaintainers() as $maintainer) {    if ($maintainer->isDuty()) {        return $maintainer;    }}

Интеграция с PhpStorm

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

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

Дежурный по компоненту

Думаю, многие из вас сталкивались с проблемой переключения контекста. На мой взгляд, надо стараться этого избегать. У каждого своя скорость и требуется разное количество времени, чтобы снова погрузиться в задачу (контекст). Кому-то достаточно нескольких минут, а кому-то нужно гораздо больше.

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

Это не значит, что команда бросает дежурного на произвол судьбы. В случае если он не сталкивался с какой-либо проблемой ранее, он всегда может подключить коллег. Но если дежурный самостоятельно отвечает даже на 80% вопросов, это означает, что остальные члены команды 80% времени спокойно работают над своими задачами, не опасаясь, что их вырвут из контекста.

Кроме того, дежурства позволяют делиться знаниями внутри команды, тем самым повышая bus factor.

Интеграция с внутренними системами

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

Система сбора и анализа PHP-ошибок

Исторически для сбора и анализа PHP-ошибок мы используем самописную систему, которая по функциональности похожа на популярные Sentry и Splunk, но адаптирована к нашим внутренним процессам. В неё первую мы добавили поддержку компонентов.

Один из этапов сбора ошибок насыщение события дополнительной информацией. Мы добавили в пайплайн новый шаг, на котором система собирает список затронутых компонентов на основе списка файлов из стек-трейса ошибки.

Эту информацию можно использовать:

  • для поиска ошибок по определённому компоненту;

  • для построения отчётов и графиков в разбивке по компонентам.

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

Реестр баз данных

Бэкенд наших приложений Badoo и Bumble состоит из сотен различных модулей, систем и сервисов. Большинство из них для хранения данных использует MySQL.

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

  1. Найти в коде, на каком хосте живёт база.

  2. Подключиться к хосту через любой удобный инструмент (консольная утилита, phpMyAdmin, Sequel Pro, IDE и т. д.).

  3. Найти нужную базу и таблицу.

  4. Изучить информацию о таблице.

А если нужно узнать размер таблицы на продакшене?

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

Другой пример: нужно найти список таблиц, которые долгое время не используются и просто занимают место на сервере. Тут уже нужно писать скрипт, который обойдёт все нужные серверы и соберёт статистику.

Чтобы упростить жизнь разработчикам, мы создали систему под названием DBRegistry. Она хранит в себе информацию для всех баз данных, доступную через INFORMATION_SCHEMA.

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

Информация о компоненте будет полезна в случае, если с каким-то сервером начались проблемы (например, выросла нагрузка на CPU) и администратор баз данных нашёл проблемный запрос и хочет сообщить о проблеме разработчику. Он просто находит нужную таблицу в DBRegistry, смотрит, к какому компоненту она привязана, и пишет о проблеме дежурному.

Заключение

С момента нашего перехода на компонентный подход прошло больше трёх лет, и за это время поддержка компонентов была реализована во всех внутренних системах. Нам удалось сделать процессы более быстрыми и понятными. Теперь ни у кого не возникает вопроса А кто отвечает за этот код?. Достаточно открыть интранет и найти нужный компонент он содержит всю необходимую информацию.

Актуализация списка ответственных теперь сводится к нескольким кликам в интерфейсе, хотя до внедрения компонентов на обновление этой информации во всех системах могли уйти дни, а то и недели.

На этом всё. Спасибо за внимание!

Подробнее..

Wild Horizon. Обзор наших первых изменений

02.06.2021 00:12:39 | Автор: admin

Очередной выпуск "игровой газеты". Изменения на первой полосе. Ответы на вопросы.

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

Мы услышали все пожелания, учли наши ошибки, обратили внимание на жалобы.

Проект находится на стадии доработки.

Краткие ответы на ваши вопросы:

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

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

На каком движке игра? Unity. Работали на нем ранее, полностью устраивает.

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

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

Делали ли рекламу, покупали трафик? Нет, на продвижение игры не пострадал ни один рубль. Продвижение это всегда грамотное вливание огромных сумм. Думаю с этим в данных реалиях может справиться только издатель или довольно крупная компания.

Разрешение игры режется, не видно названий иконок. Программист Александр провел огромную работу по оптимизации экранов под разные форматы. В моем распоряжение есть убогий вытянутый формат экрана Samsung а51, наверное один из самых неудобных в плане экрана, с которого и начали замечать проблемы. Проблема решена для него и остальных основных форматов.

Samsung а51Samsung а51

Будут ли еще добавлены ресурсы? Да, раз в неделю добавляем по одной шахте для разных металлов.

ШахтыШахты

Как мне набрать людей / рабочих? Они приходят сами раз в пол часа, а также при строительстве домов. Теперь вы можете изучать, крафтить разные инструменты, снаряжать рабочих и назначать их на работу в ту или иную область карты. Инструменты и снаряжение имею разные уровни, делаются из разных материалов и в зависимости от качества дают повышенный бонус к производству.

Планируете ли внедрять еще персонажей? На данный момент в игре 8 персонажей, но 25 полностью прописанных заготовок. Всех персонажей четко прописывали в табличке, что бы не повторялись бонусы и каждый персонаж был бы уникальным.

Работаешь ли ты еще где то? Да, безусловно, дизайн мое всё, а проект это что-то вроде хобби, которое в будущем хотелось бы превратить в работу.

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

Проект дает интересный опыт каждому из нас, учит нас думать иначе, искать ошибки там, где их не должно быть. До нужного нам результата еще далеко, но я очень рад постоянно получать от вас обратную связь, видеть как проект перевалил за 300+ установок, как органически приходят люди с разных стран. Забавный факт! На втором месте по скачкам - Корея. Хз как так получилось.

Большинство из вас знает, что в разработке игры довольно мало романтики, много нагрузок и много ошибок. Слишком много, они повсюду. Но для меня это все же начальное детище, на которое просто приятно смотреть и не осознавать, что ты на пару с приятелем это смог сделать)

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

Любите игры, играйте в игры!

Подробнее..

Перевод 4 технических решения, которые делают API сервис успешным

03.06.2021 12:19:11 | Автор: admin
Есть API, которые в целом как-то работают, но имеют проблемы с безопасностью, документацией или валидацией данных. Автор статьи объясняет, почему в современных реалиях это недопустимо, и даёт рекомендации по исправлению недостатков.



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

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

А если от публичного API напрямую зависит доход компании, то ставки по-настоящему высоки. Эта мысль подробнее раскрыта в книге Непрерывное развитие API. Правильные решения в изменчивом технологическом ландшафте (Мехди Меджуи, Ронни Митра и др):


а мы пойдём дальше...

Разработчики могут быть в основном сосредоточены на том, чтобы в API была реализована вся запланированная функциональность. Но существуют нефункциональные требования, которые часто выполнены не в полной мере и требуют особого внимания.

На мой взгляд, для всех API обязательно качественное выполнение следующих нефункциональных требований:

  • Безопасность
  • Документация
  • Валидация
  • Тестирование

Безопасность


Наверное, не стоит объяснять, почему безопасность оказалась на первом месте. Я выделил четыре наиболее важных задачи по обеспечению безопасности:

  1. Использование HTTPS с SSL-сертификатами
  2. Совместное использование ресурсов из разных источников (CORS)
  3. Аутентификация и JSON Web Tokens
  4. Авторизация и привилегии доступа


* Здесь и далее сузим контекст до REST и JSON API.

1. Использование HTTPS с SSL-сертификатами


Сейчас HTTPS с использованием SSL-сертификатов является де факто стандартом безопасности. Для генерации сертификатов лично я использую Let's Encrypt бесплатный, центр автоматизированный сертификации от некоммерческой организации Internet Security Research Group (ISRG).

Эти сертификаты гарантируют, что данные, идущие от вашего API к пользователю, будут зашифрованы.

2. Совместное использование ресурсов из разных источников (CORS)


Чтобы обеспечить безопасность запросов к другим источникам, браузеры используют механизм под названием CORS. Аббревиатура CORS расшифровывается как Cross-Origin Resource Sharing технология совместного использования ресурсов разных источников. Несмотря на то, что браузеры (в силу правила одинакового источника) не позволяют получать доступ к ресурсам из разных источников, CORS позволяет обойти эти ограничения и при этом быть уверенным, что доступ к ресурсам будет безопасным.

Пользовательские агенты (к примеру, браузеры) на основе значений дополнительных заголовков для CORS в HTTP-запросе могут выполнять запросы к другим источникам, которые без CORS были бы заблокированы.



Приведём пример:

HTML страница, обслуживаемая сервером с http://domain-a.com, запрашивает src по адресу http://domain-b.com/image.jpg .

Многие страницы загружают ресурсы вроде CSS-стилей, изображений и скриптов с разных доменов, соответствующих разным CDN (сетям доставки контента).

Сегодня достаточно популярна реализация CORS для Node.js.

3. Аутентификация и JSON Web Tokens (JWT)


Существует несколько подходов к аутентификации пользователя API, но один из лучших это использование JWT. Эти токены подписываются с использованием различных криптографических алгоритмов.

JSON Web Token это открытый стандарт для создания токенов доступа, основанный на формате JSON. Как правило, используется для передачи данных для аутентификации в клиент-серверных приложениях.

Для создания токена необходимо определить заголовок (header) с общей информацией по токену, полезные данные (payload), такие как id пользователя, его роль и так далее, а также подписи (signature). Простыми словами, JWT это лишь строка в следующем формате header.payload.signature.

Когда клиент входит в систему, служба управления идентификацией предоставляет клиенту JWT. Затем клиент может использовать этот токен для выполнения запросов к API. У API есть доступ к публичному ключу или секрету, который он использует для проверки токена.

Для проверки можно использовать, например, библиотеку jsonwebtoken. Приводим ниже код на JavaScript:

import jwt from 'jsonwebtoken'

export default function (req, res, next) {

// req.headers.authorization Bearer token

const token = extractToken(req)

jwt.verify(token, SECRET, { algorithms: ['HS256'] }, (err, decoded) => {

if (err) { next(err) }

req.session = decoded

next()

})

}

Больше информации про JWT, библиотеки и поддерживаемые языки программирования на сайте JWT.io.

4. Авторизация и привилегии доступа


Аутентификация важна, но так же важна и авторизация: имеет ли клиент, прошедший аутентификацию и получивший JWT, привилегию выполнить тот или иной запрос?

Чтобы проверить это, мы используем скоуп. Анализируя его, сервис API определяет, может ли этот запрос клиента быть выполнен без дорогостоящих операций поиска в списке контроля доступа.

Скоуп это текстовый блок (обычно разделённый пробелами), который описывает привилегии доступа конечной точки API. Там описаны Ресурсы и Действия, которые к ним можно применять. Такая формализация хорошо работает для REST / JSON API, поскольку они очень похожи по структуре.

RESOURCE: ACTION (например, ARTICLE: WRITE или ARTICLE: READ, где ARTICLE это ресурс, а READ и WRITE действия).

Это позволяет разработчикам API сосредоточиться на функциях, а не на ролях или пользователях. Служба управления идентификацией может связывать роли и пользователей с определёнными скоупами, а затем вместе с JWT отправлять скоуп клиенту.

Спать спокойно


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

Документация


Что может быть хуже отсутствия документации? Устаревшая документация!

Разработчики относятся к документированию неоднозначно. У многих явно нет большой любви к этому делу. Как бы то ни было, эта задача очень важна особенно, когда речь идёт про публичное API. Сторонние разработчики должны иметь возможность изучить, как его использовать. Кроме того, хорошая документация поможет вам быстрее обучать новых разработчиков, пришедших в вашу команду.

Документация по API должна включать три базовых раздела:

  1. Вводная часть (README)
  2. Техническое описание (Спецификации)
  3. Примеры использования (Getting started и другие подобные подразделы)

1. README


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

Об этом пишут в файле README. Этот файл обычно тоже размещают в репозитории, он даёт разработчикам отправную точку для работы с вашим проектом.

README должен содержать:

  1. Описание API
  2. Ссылки на технические справочники и руководства
  3. Руководство по настройке для разработчика
  4. Руководство для тестировщика
  5. Руководство по развёртыванию
  6. Управление зависимостями
  7. Руководство для контрибьюторов
  8. Нормы поведения
  9. Лицензия
  10. Благодарность

Будьте лаконичны в своем README; вам не нужно объяснять все нюансы, но предоставить достаточно информации, чтобы разработчики могли погрузиться в ваш проект.

2. Спецификации


В REST / JSON API каждая конечная точка представляет собой функцию, созданную с определённой целью. Важно иметь техническую документацию, описывающую каждую конечную точку, входные и выходные данные и особенности работы сервиса с разными клиентами.

Создать собственную документацию для API можно на основе OpenAPI.

Это спецификация и полноценный фреймворк для описания, создания, использования и визуализации веб-сервисовREST. Его задача позволить системам документации синхронизировать свои обновления с изменениями на сервере. Методы, параметры, модели и другие элементы посредством OpenAPI интегрируются с программным обеспечением сервера и всё время с ним синхронизируются.

3. Примеры использования


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

Отличный способ познакомить пользователей с вашим API создать подраздел Getting started (Начало работы). Это поможет разобраться с типовыми сценариями использования и на их примере оценить преимущества вашего API.

Три кита


Документация ключевой компонент любого API. Создавая документацию, помните о трёх китах успешного документирования API README, спецификации и примеры использования. И будет вам (и вашим пользователям) счастье!

Валидация данных


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

Лучшая стратегия запускать проверку до того, как ваш сервис произведёт какие-то операции с данными. Когда клиент отправляет вашему API свои данные, например email, дату и имя, убедитесь, что это действительно адрес электронной почты, дата правильно отформатирована, а строка соответствует требованиям к длине. Эта простая проверка сделает работу вашего сервиса более безопасной и организованной.

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

Вы можете реализовать валидацию руками, но для этой цели также можно использовать и такие библиотеки, как Lodash или Ramda. Они отлично подходят для небольших объектов данных. Такие библиотеки, как Joi, Yup или Zod, работают ещё лучше, поскольку они позволяют описать общую схему валидации, сэкономив время и усилия. Если вам нужно что-то не зависящее от конкретного языка программирования, посмотрите на JSON Schema.

Лучше перебдеть


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

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

Тестирование


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

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

Этот метод позволяет вам сосредоточиться только на логике обработки данных, не учитывая внутреннюю кухню бэкенд-сервисов или логику представления данных. Отсутствие зависимостей делает выполнение теста более надёжным, легким для автоматизации и более простым для включения в пайплайн непрерывной интеграции.

Для интеграционного тестирования я использую Tape, Test-server и Fetch-mock. Эти библиотеки позволяют запускать изолированные тесты для конечных точек API, проходя путь от запроса до ответа.

Игра в имитацию


Другие типы тестирования и проверки типов, безусловно, тоже полезны, интеграционное тестирование даёт наибольшее преимущество: оно показывает высокую эффективность при небольших тратах человеко-часов на написание и сопровождение тестов. А использование таких инструментов, как Fetch-mock, может обеспечить полную имитацию обмена данными.

Не останавливайтесь на достигнутом


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



Облачные серверы от Маклауд быстрые и безопасные.

Зарегистрируйтесь по ссылке выше или кликнув на баннер и получите 10% скидку на первый месяц аренды сервера любой конфигурации!

Подробнее..

Проекты в Gradle 7 как не зависеть от зависимостей

03.06.2021 16:16:28 | Автор: admin

Привет! Меня зовут Ксения Кайшева, я пишу приложения под Android в компании 65apps. Сегодня расскажу о новой возможности, которая позволяет централизованно описывать зависимости на проектах с системой сборки Gradle.

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

В 7й версии Gradle представлена новая функция, позволяющая описывать все зависимости централизованно. Эта функция находится на стадии превью, и чтобы воспользоваться ей в файле settings.gradle(.kts) необходимо добавить строку:

enableFeaturePreview("VERSION_CATALOGS")

Так выглядит использование (описанных в централизованном каталоге) зависимостей в любом build.gradle скрипте:

dependencies {
implementation libs.lifecycle.runtime
implementation libs.lifecycle.viewmodel.ktx
implementation libs.lifecycle.extentions
implementation libs.lifecycle.livedata.ktx
}

Здесь:

libs это сам каталог
lifecycle.runtime это зависимость в этом каталоге.

Каталог описывается в settings.gradle(.kts) файле:

dependencyResolutionManagement {
versionCatalogs {
libs {
alias('lifecycle-runtime')
.to(androidx.lifecycle:lifecycle-runtime:2.2.0')
alias('lifecycle-viewmodel-ktx').to(androidx.lifecycle', 'lifecycle-viewmodel-ktx').version {
strictly '[2.2.0, 2.3.0['
prefer '2.3.1'
}
}
}
}

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

Разделение через тире является рекомендованным.

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

Например,

lifecycle-runtime
lifecycle_runtime
lifecycle.runtime
junit5-test-core
spek-runner-junit5

Недопустимо иметь псевдоним для зависимости, которая также принадлежит вложенной группе. Например, lifecycle-viewmodel и lifecycle-viewmodel-ktx.

Gradle рекомендует в таком случае использовать регистр для различения.
Например, lifecycleViewmodel и lifecycleViewmodelKtx.

Версии можно объявлять отдельно и затем ссылаться на них в описаниях самих зависимостей:

dependencyResolutionManagement {
versionCatalogs {
libs {
version('lifecycle', '2.3.1')
alias('lifecycle-viewmodel-ktx').to('androidx.lifecycle', 'lifecycle-viewmodel-ktx').versionRef('lifecycle')
}
}
}

Объявленные таким образом версии также доступны из любогоbuild.gradle файла:

version = libs.versions.lifecycle.get()

Часто бывает, что некоторые зависимости используются вместе. В каталоге такие зависимости можно объединять в пакеты и подключать их сразу через псевдоним пакета. То есть пакет это список нескольких зависимостей:

dependencyResolutionManagement {
versionCatalogs {
libs {
version('lifecycle', '2.3.1')
alias('lifecycle-runtime').to('androidx.lifecycle, 'lifecycle-runtime').versionRef('lifecycle')
alias('lifecycle-viewmodel-ktx').to('androidx.lifecycle, 'lifecycle-viewmodel-ktx').versionRef('lifecycle')
bundle('lifecycle',
['lifecycle-runtime', 'lifecycle-viewmodel-ktx'])
}
}
}

Подключение пакета зависимостей будет выглядеть так:

dependencies {
implementation libs.bundles.lifecycle
}

Добавление одного пакета эквивалентно добавлению всех зависимостей из пакета по отдельности.

Помимо описания каталога в settings.gradle(.kts) файле, есть более простая возможность собрать все зависимости вместе использовать toml-файл каталоге gradle: libs.versions.toml.

То есть, плюс еще один стандарт к представленному стандарту описания зависимостей.

По умолчанию libs.versions.toml файл будет входом в libs каталог. Можно также изменить имя каталога по умолчанию, например:

dependencyResolutionManagement {
defaultLibrariesExtensionName.set('deps')
}

Toml-файл состоит из 3 основных разделов:

[versions] - раздел для объявления версий
[libraries] - раздел для объявления зависимостей
[bundles] - раздел для объявления пакетов зависимостей

Например,

[versions]
lifecycle = "2.3.1"

[libraries]
lifecycle-runtime = { module = "androidx.lifecycle:lifecycle-runtime", version.ref = "lifecycle" }
lifecycle-viewmodel-ktx = { module = "androidx.lifecycle:lifecycle-viewmodel-ktx", version.ref = "lifecycle" }

[bundles]
dagger = ["lifecycle-runtime", "lifecycle-viewmodel-ktx"]

Версию можно объявить просто как строку с номером, и в этом случае она считается обязательной версией, или в расширенном варианте, комбинируя информацию о версиях разного уровня:

[versions]
any-lib1 = 1.0
any-lib2 = { strictly = "[1.0, 2.0[", prefer = "1.2" }

Более подробно о расширенном варианте версии по ссылке

Семантика объявления номера версии по ссылке

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

[libraries]
any-lib = "com.company:anylib:1.4"
any-other-lib = { module = "com.company:other", version="1.4" }
any-other-lib2 = { group = "com.company", name="alternate", version="1.4" }
anylib-full-format = { group = "com.company", name="alternate", version={ require = "1.4" } }

Если необходимо сослаться на версию, объявленную в [versions] разделе, то следует использовать свойство version.ref:

[versions]
some = "1.4"

[libraries]
any-lib = { group = "com.company", name="anylib", version.ref="some" }

Можно использовать несколько toml-файлов.Для этого нужно указать, как импортировать соответствующий файл:

dependencyResolutionManagement {
versionCatalogs {
testLibs {
from(files('gradle/test-libs.versions.toml'))
}
}
}

Также есть возможность создать каталог зависимостей и использовать его между разными проектами в рамках одной компании, например.

Подробнее по ссылке

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

При использовании Groovy не работает автоподстановка при указании зависимости в build.gradle файле и, соответственно, нет возможности провалиться в описание зависимости при нажатии на нее. Исправлять это не планируют. Решение для автоподстановки использовать Kotlin DSL.

Подробнее..

Как сделать экран подтверждения СМС-кода на iOS

03.06.2021 16:16:28 | Автор: admin

Привет, Хабр!

Меня зовут Игорь, я Head of Mobile в компании AGIMA.

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

Важно: в примере кода на github будет полноценный пример с вводом номера телефона и кодом, но экран ввода номера телефона совсем скучный, поэтому сегодня мы вводим код :)

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

  • отправить код на сервер;

  • включить таймер повторной отправки + отобразить визуально;

  • после завершения таймера показать кнопку отправить еще раз;

  • отправить повторный запрос на получение кода;

  • отобразить все ошибки;

  • обработать успешное подтверждение кода.

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

Можно, конечно, отправить всю логику про таймеры и isLoading на View слой, но мне больше нравится относить это к логике. Особенно учитывая то, что я большой поклонник MVVM+Rx (и буду это использовать в статье), это более чем уместно смотрится. Ну да ладно.

ViewModel в этом случае играет роль некоего преобразователя пользовательских действий: у нее есть input и output (видно на картинке выше). За навигацию будет отвечать кто-то еще, например, координатор.

Со стороны UI нам будут интересны следующие компоненты:

final class ConfirmCodeViewController: BaseViewController {  /// поле ввода кода  private lazy var codeTextField = CodeTextField()  /// лейбл для отображения ошибок   private lazy var errorLabel = UILabel()  /// один лоадер для запросов на отправку кода и на повторный запрос кода  private lazy var loader = UIActivityIndicatorView()  /// лейбл с обратным отсчетом для повторной отправки кода  private lazy var timerLabel = UILabel()  /// кнопка повторной отправки кода  private lazy var retryButton = UIButton(type: .system)  /// это все будет в стеквью  private lazy var stackView = UIStackView()}

ViewModel будет выглядеть так:

/// Например, после успешного подтверждения кода нам могут предложить ввести перс. данныеenum AuthResult {case successcase needPersonalData}protocol ConfirmCodeViewModelProtocol {    /// Введенный пользователем код для подтверждения    var code: AnyObserver<String> { get }        /// Пользователь нажал на отправить повторно    var getNewCode: AnyObserver<Void> { get }        /// Результат подтверждения кода    var didAuthorize: Driver<AuthResult> { get }        /// Один индикатор на все запросы на этом экране    var isLoading: Driver<Bool> { get }        /// Ошибки из всех запросов на этом экране    var errors: Driver<String> { get }        /// Таймер отправки нового кода    var newCodeTimer: Driver<Int> { get }        /// Запросили новый код при нажатии на отправить заново    var didRequestNewCode: Driver<Void> { get }      /// Таймер отправки нового кода запущен    var codeTimerIsActive: Driver<Bool> { get }}

Обратите внимание, что при таком подходе мы стараемся не использовать PublishSubject, BehaviourRelay итп, чтобы четко разделить input и output у ViewModel. Теперь давайте это все свяжем.

View отдает следующие потоки данных:

let codeText = codeTextField.rx.text.share()codeText    .bind(to: viewModel.code)    .disposed(by: disposeBag)retryButton.rx.tap    .bind(to: viewModel.getNewCode)    .disposed(by: disposeBag)

ViewModel будет как-то (покажу ниже) обрабатывать ввод кода пользователя, а также делать запрос на повторную отправку кода, если мы нажмем на кнопку.

Сначала давайте посмотрим ViewModel целиком, далее разберем ее более подробно.

ViewModel рассмотрим по кусочкам:

let _codeSubject = PublishSubject<String>()self.code = _codeSubject.asObserver()let codeObservable = _codeSubject.asObservable()let validCodeObservable = codeObservable.filter { $0.count == codeLength }

_codeSubject это поток данных из textfield ввода кода.

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

Выше мы договорились, что PublishSubject не используем, но внутри нам от того же кода нужен не только AnyObserver, но и Observable , чтобы использовать его, например, для отправки кода на сервер. В дальнейшем я планирую использовать такую технику: AnyObserver или Observable в публичном интерфейсе и PublishSubject внутри.

let codeEvents: Observable<Result<Void, Error>> = validCodeObservable    .flatMap { (code) in        authService.confirmCode(code: code, token: token).materialize()    }.share()

Собственно, отправка кода на сервер :) Обращаем внимание на .materialize(). Поскольку мы планируем использовать этот Observable в реактивных цепочках, мы не хотим получить ошибку и прерывать их. materialize позволяет завернуть все значения и ошибки в Result<Value, Error> и тем самым мы никогда не прервем реактивную цепочку из-за ошибки.

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

Состояние загрузки

Здесь довольно интересный момент. Если мы получили валидный код, готовый к отправке, то мы отображаем интерфейс загрузки. Если мы получили ответ от сервера, это означает, что нам надо скрыть состояние загрузки. Таким образом, мы можем взять эти потоки данных (на примерах выше), смаппить их в true или false и забиндить в isLoading.

didAuthorize = codeEvents.elements()...

.elements() работает как фильтр и пропускает только значения из codeEvents и игнорирует ошибки. Напомню, что тип значений у codeEvents это Result<Void, Error> , что является частью RxSwiftExt.

Таймер повторной отправки кода

Таймер включается при следующих событиях:

  • мы отправили код на подтверждение (validCodeObservable.mapTo(Void()));

  • мы перезапросили код (didRequestNewCode);

  • сразу же при заходе на экран (.startWith(Void())).

Именно это описано в строчке Observable.merge... Сам таймер делается стандартными средствами RxSwift. Останавливаем таймер с помощью оператора take(while:), пока значение таймера не станет равно 0.

Лейбл с таймером и кнопка переотправить должны скрываться/показываться в зависимости от того, активен ли таймер:

viewModel.codeTimerIsActive    .drive(retryButton.rx.isHidden)    .disposed(by: disposeBag)        viewModel.codeTimerIsActive    .not()    .drive(timerLabel.rx.isHidden)    .disposed(by: disposeBag)

За ошибки отправки и запроса нового кода у нас будет отвечать один поток данных errors.

errors = codeEvents.errors().merge(with: fetchNewCode.errors())            .compactMap { ($0 as? ErrorType)?.localizedDescription }            .asDriver(onErrorJustReturn: "")

Также запретим редактировать код, во вркмя того, как он отправляется:

viewModel.isLoading    .not()    .drive(codeTextField.rx.isEnabled)    .disposed(by: disposeBag)

ViewModel получилась довольно-таки тестируемая, поэтому давайте напишем тесты! Я приведу примеры тестов, которые будут показывать, как ViewModel реагирует на пользовательский ввод. Создадим вспомогательный метод, который будет создавать поток событий ввода кода. Внимание, используется RxTest!

class ConfirmCodeViewModelTests: XCTestCase {    // properties// methods     //MARK:- Helpers    private func bindCodeInputEvents(        _ events: [Recorded<Event<String>>] = [.next(100, "1"), .next(200, "11"), .next(300, "111"), .next(400, "1111")])    {        codeInputEvents = scheduler.createHotObservable(events)        codeInputEvents.bind(to: viewModel.code).disposed(by: disposeBag)    }}

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

   func test_timerInvokedAutomatically() {        let sut = scheduler.start(created: 0, subscribed: 0, disposed: 1000) { self.viewModel.newCodeTimer }        XCTAssertEqual(sut.events, [.next(1, 2), .next(2, 1), .next(3, 0)])    }

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

 func test_errorEmmitedValueAtFailure() throws {        bindCodeInputEvents()        setConfirmCodeResult(.error(0, MockError.confirmFailure))         let sut = scheduler.start { self.viewModel.errors }        XCTAssertEqual(sut.events, [.next(400, "confirmFailure")])    }

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

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

Подробнее..

Дайджест интересных материалов для мобильного разработчика 396 (31 мая 6 июня)

06.06.2021 16:09:40 | Автор: admin
Сегодня в нашем дайджесте архитектурные паттерны и победители Swift Student Challenge, инициализация цепочек и цветов Fuchsia, инди-акселератор и инди-фестиваль от Google, Android 12 для разработчиков, $643 млрд из App Store и многое другое!



Этот дайджест доступен в виде еженедельной рассылки. А ежедневно новости мы рассылаем в Telegram-канале.

iOS

Архитектурные паттерны в iOS: привет от дядюшки Боба, или Clean Architecture
Тернистый путь внедрения Swift Package Manager. Доклад Яндекса
Swift и CoreData. Или как построить Swift ORM на основе Objective-C ORM
Как сделать экран подтверждения СМС-кода на iOS
Мои приложения для разработчиков вышли в топ iOS и Mac App Store: сколько это принесло?
WWDC21: Школьники и студенты из России победители Swift Student Challenge
Объявлены номинанты Apple Design Awards 2021
Добавляем поддержку Siri в iOS-приложение за считанные минуты
Как сериализовать и десериализовать объекты в iOS
Как улучшить время компиляции и выполнения Xcode
Удаление фона с помощью Core ML и SwiftUI
Как извлечь функциональность из устаревшего iOS-кода
Приложение для чата без пароля для iOS с Auth0
Как добавить Swift-код в качестве кастомной LLDB команды
Design to Code: превращая дизайн в код
SPIndicator: индикатор в стиле Apple

Android

Проекты в Gradle 7: как не зависеть от зависимостей
Всё о PendingIntents
Инициализация Rx цепочки
Proto DataStore + AndroidX Preferences на Kotlin
Подробный обзор Android 12 для разработчиков
Введение в систему Снапшотов Compose
Недоверенные события касания
Понимаем юнит-тесты для Android в 2021
Polestar предлагает эмулятор для разработчиков, создающих приложения для Android Automotive
QA-инженеры, функциональное и UI-тестирование в Azimo
10 лучших библиотек для разработчиков Android в 2021 году
Сохранение данных на Android с помощью Room Database и Data Store Руководство для начинающих
CheckboxQuestions: вопросы и чекбоксы
Compose Space Invaders: игра для декстопа на Jetpack Compose
Carousel Recyclerview: красивая карусель

Разработка

Как художнику найти работу мечты в геймдеве. А также советы по оформлению портфолио
4 технических решения, которые делают API сервис успешным
C# vs Kotlin
Как и зачем Mail.ru Group провела редизайн мобильной версии главной страницы портала
Mobile People Talks: какого же цвета Fuchsia?
Podlodka #218: схемотехника
HarmonyOS заработала на смартфонах
Новый SDK от Loomдобавляет видео-сообщения в любые веб-приложения
Facebook открывает Messenger API в Instagram для всех
Задачи с собеседований: зарплата
Дизайн приложений: примеры для вдохновения #44
Stack Overflow продан за $1.8 млрд
Что не так с Flutter?
Исследование продакт-менеджеров 2021 от Product Plan
Как оставаться в физической и ментальной форме, продолжая программировать
О создании гибкого пользовательского интерфейса на примере Instagram Threads
Представляем новый язык дизайна Material You от Google
Сеты бесплатных иконок для разработчиков и дизайнеров
Как привлечь первых 100 клиентов в SaaS: 5 простых шагов
Следующим стартапом на триллион станет образовательная компания
5 задач для автоматизации с помощью Python
Я не мог быстро тратить деньги, и это чуть не убило мой стартап
Flutter 2.2: создаем первую Universal Windows Program (UWP)
Мой код плохо пахнет, но все в порядке
Как создать свою первую Облачную функцию Firebase
5 вещей, которые я узнал после двух лет работы инженером-программистом в Microsoft
Test-driven Development для создания пользовательских интерфейсов
Мой опыт интервью в Twitter
Flutter: создание красивых приложений для Windows удобная структура дизайна и навигация
Вселенная no-code/low-code стартапов и ее игроки
Пример дизайна: Safe Space wellness-приложение для Android
База данных с вопросам из интервью в Apple

Аналитика, маркетинг и монетизация

В Android также ограничивают действие рекламного идентификатора
make sense: О запуске агротех-стартапа
Voodoo открывает летний конкурс гиперказуальных игр
Google запускает Indie Games Accelerator и Indie Games Festival
Продажи в App Store в 2020 выросли на 24% до $643 млрд
Создатели читов для PUBG Mobile заработали $77 млн
3 лучшие техники геймификации
Greg: приложение для любителей растений
Маркетплейс для разработчиков Malt получил 80 млн
Социальная сеть Poparazzi стала 1 App Store: секреты роста
Проектирование продуктов, формирующих привычки
Ошибки при расчете юнит-экономики
9 способов встроить виральность в ваш продукт
Как создать отличные скриншоты для страницы приложения в App Store

AI, Устройства, IoT

Учиться, учиться, и ещё раз учиться?
Теория игр как механизм для анализа крупномасштабных данных

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

Создание прекрасных приложений с помощью Xamarin.Forms

09.06.2021 10:16:43 | Автор: admin

Есть вопрос, который мне постоянно задают в Твиттере: как создавать приложения с крутым дизайном с помощью Xamarin.Forms? Это отличный вопрос, ведь любой может создавать красивые приложения, немного вдохновившись и поработав над стилем. Я не дизайнер и не претендую на звание дизайнера, но есть много отличных источников вдохновения для дизайна приложений, включая Dribbble, Uplabs и другие. Эти дизайны от талантливых людей со всего мира могут повлиять на внешний вид ваших собственных приложений.

Приложение для ресторана от Oludayo AlliПриложение для ресторана от Oludayo Alli

Встроенные возможности Xamarin.Forms

В Xamarin.Forms есть несколько функций, которые можно использовать, чтобы воплотить важные проекты в жизнь. Зачем вам что-то, кроме нового Shapes API для рисования фигур, линий, многоугольников и многого другого. Хотите, чтобы ваши собственные элементы управления были единообразными? Как насчет добавления Material Design с помощью одной строчки кода. А еще сгруппируйте свои коллекции с помощью CarouselView в сочетании с IndicatorView и, конечно же, CollectionView.

Приложение "Галерея напитков" от Javier SurezПриложение "Галерея напитков" от Javier Surez

Пойдите дальше с кастомными элементами управления от сообщества

Xamarin Community Toolkit добавляет отличные элементы управления, включая DockLayout, Shield, TabView и другие. Но есть еще более потрясающие элементы управления от сообщества, включая потрясающие Magic Gradients, PancakeView, MaterialFrame, CardView, Shadows и многие другие. Наконец, мы не можем забыть SkiaSharp, систему 2D-графики общего назначения для .NET.

Компонентная экосистема

Переиспользуемые компоненты пользовательского интерфейса от ведущих поставщиков компонентов, таких как Telerik, UX Divers, GrapeCity и Syncfusion, помогут вам быстро повысить продуктивность. Обязательно ознакомьтесь с множеством вариантов, когда будете готовы начать работу.

Вдохновляйтесь

Наш коллега Хавьер уже несколько лет собирает интересные примеры крутых приложений с открытым исходным кодом, созданных с помощью Xamarin.Forms, которые вы можете изучить на GitHub. Выше вы уже видели несколько из этих приложений, но вот еще, чтобы вас вдохновить.

Кошелек карт от Altevir Кошелек карт от Altevir Приложение для авиаперелетов от Leomaris ReyesПриложение для авиаперелетов от Leomaris ReyesКнига рецептов от Steven ThewissenКнига рецептов от Steven ThewissenCake app от Shaw YuCake app от Shaw Yu

И есть еще очень много прекрасных дизайнов. Вы даже можете добавить свой собственный, просто создав pull request в репозитории Хавьера на GitHub.

Adobe XD Exporter

Многие дизайны, которые вы найдете в интернете или получите от вашего дизайнера, могут быть созданы с помощью таких инструментов, как Adobe XD. Вы можете легко импортировать цвета и стили в свое приложение Xamarin.Forms благодаря экспортеру XD в Xamarin.Forms (его автор -- наш коллега Kym Phillpotts).

Создавайте красивые приложения

Расскажите нам о своих приложениях, оставив комментарии ниже или отправив pull request в репозиторий Хавьера на GitHub.

Подробнее..

Apple убивает TeamCity, Bitrise, Appcenter, Fastlane, Firebase, Sentry и иже с ними. Краткий обзор Xcode Cloud

10.06.2021 14:04:32 | Автор: admin

Заголовок конечно громковат, может не убивает, но уменьшит им доходы точно. Давайте кратко посмотрим что представила Apple на WWDC 2021, что такое Xcode Cloud?

Xcode Cloud - это сервис CI/CD, встроенный в Xcode и разработанный специально для разработчиков Apple. Он ускоряет разработку и доставку приложений, объединяя облачные инструменты, которые помогают создавать приложения, параллельно запускать автоматические тесты, доставлять приложения тестировщикам, а также просматривать отзывы пользователей и управлять ими.

Цикл разработки по мнению Apple заключается в этапах 1) Написать код 2) протестировать его 3) Интегрировать (в текущий) 4) Доставить до пользователя 5) Улучшить, и по новой. На то он и цикл. В принципе похоже на правду, так оно и есть.

Если вы хоть раз настраивали CI/CD для iOS приложений, вы знаете примерно какие там шаги, ничего сложного, но это может включать в себя использование нескольких сервисов, генерации сертификатов и тд и тп.

Теперь же Apple предлагает нам сделать это все не выходя из Xcode, давайте взглянем на процесс.

Для начала нам нужно настроить первый workflow, а потом уже который будет пробегать при PR/MR (pull request/merge request) на main/develop ветку в системе контроля версий.

I CI/CD

1) Жмем в новом Xcode при подключенном сервисе Xcode Cloud кнопку "создать workflow" и видим настройки

Name - название воркфлоу, Start condition когда запускать воркфлоу (например при изменении в main ветке), Environment - можно выбрать стабильную версию Xcode или новую бета версию, Actions - что собственно надо сделать, обычно выполнить archive и опубликовать например в TestFlight, после прогонки тестов, Post-Actions - что сделать после того как воркфлоу пройден, например написать в slack/telegram канал об этом событии

2) Выбираем репозиторий где хранится наш код

3) Выбираем с какой ветки собрать билд (при первой настройке)

Собственно готово, теперь можем посмотреть как выглядит в Xcode место где можно управлять сборками, запускать их, пересобирать и тд

Давайте теперь посмотрим как выглядит управлени воркфлоу (выше показан путь настройки первой сборки)

1) Выбираем "управление воркфлоу"

2) Выбираем настройки (например при pull/merge request что-то выполнять)

3) Выбираем какие тесты мы хотим прогнать в воркфлоу (UI или Unit тесты), я так понимаю речь именно про нативные тесты, про Appium и тд, пока ничего не известно.

4) И выбираем отправить сообщение в Slack после того как воркфлоу пройден

5) Готово

II Тесты

1) Давайте посмотрим как выглядит интерфейс работы с тестами, мы видим тут тесты которые пройдены при сборке а также устройства на которых они прогонялись

2) Посмотрим какие конкретно тесты прогнались на iPad Air, видим что тест кейс с Light mode, портретный режим, с Английским языком, далее видим какие конкретно тесты пройдены

3) Ну и совсем чудеса, можно смотреть скриншоты пройденных тестов

4) Можно также посмотреть какой тест упал, можно также пометить тест как Flaky (Флаки тест или другими словами тест неактуальный, который надо либо удалить либо переписать), для этого используется XCTExpectFailure (что в переводе логично видно по названию метода ожидаемый фейл)

Удобно.

III - Работа с системой контроля версий (и переписка прямо в коде в Xcode)

1) Изменения теперь видно еще нагляднее (привет всем кто пользуется визуальными штуками, а не через консоль при работе с git). Сверху мы видим наши локальные изменения (которые мы накодили) а снизу "висящие" pr/mr реквесты, которые можно посмотреть, и дать свой комментарий или approve (одобрение на слияние кода)

2) Даже видно какой тест план для этой фичи, которая просится в главную ветку

3) Переписка,комменты прямо в Xcode при pr/mr (а не на веб мордах gitlab/github/bitbucket и тд)

В общем очень круто и удобно

IV - Улучшения (Crashes/Сбои/Ошибки)

1) Все краши/сбои теперь видно прямо в Xcode (а не в веб морде Firebase или Sentry), код приходит сразу символизированный (symbolized log), то есть человекопонятный с указанием что и как произошло

2) А тестер (возможно и пользователь) может оставить комментарий при краше который вы сможете прочитать (и даже ответить!)

3) Ну и самое интересное вы сможете кликнуть открыть место краша в проекте

4) И вас за ручку проведут к вашему куску кода который натворил зло

Послесловие

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

В общем как по мне сервис выглядит очень интересно, но пока недоступен для всех. Понятно что видимо он еще в стадии разработки, но как все задумывается, это выглядит круто, и очень упростит разработку для iOS.

Можете подать заявку на бета-тест здесь https://developer.apple.com/xcode-cloud/

Сколько он будет стоить пока тоже неизвестно.

И пока непонятно что с Android потому что обычно сервисы CI/CD используют сразу для двух платформ, так как приложения обычно тоже для двух платформ разрабатывают. Но может быть когда нибудь приложения для Android можно будет писать и в Xcode))

Изображение и информацию брал из видеосессий WWDC 2021, кому интересно как это выглядит вот видео про Xcode Cloud https://developer.apple.com/videos/play/wwdc2021/102/

Подробнее..

We need to go deeper как пасхалка в приложении Delivery Club сократила субъективное время ожидания еды

11.06.2021 16:11:37 | Автор: admin


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

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

Сашин скриншот того, как всё начиналось.

Саша:
У меня есть свой небольшой проект словесно-карточная игра Кто из нас? На одном из очередных разборов игры родилась мысль, что можно внутри игры спрятать ещё одну игру. Люди найдут её и скажут: Ого, я играл в одну, а сейчас играю в совершенно другую. Но игра, которую я делаю, не настолько популярна, поэтому если туда прятать ещё одну игру, то её просто никто не увидит. Возникла вторая идея. Я работаю в Delivery Club, и у нас миллионы пользователей, у которых есть общая проблема время ожидания заказа. Нужно либо сокращать время доставки, либо как-то развлечь пользователя, пока он ожидает. И я пошёл по второму пути: придумал решение в виде небольшой игры внутри основного приложения.
Дизайн для первого прототипа змейки сделала девушка Саши, а звуки Саша создал сам в интернет-синтезаторе.


Прототипы первых экранов.

Уже в январе ребята буквально за полдня в коворкинге написали MVP на Swift и SpriteKit. Там были крупные кнопки и небольшой игровой экран, как в тетрисе. В финальной версии от кнопок на экране отказались: из-за того, что они плоские, а не объёмные, как на настоящей консоли, змейкой было неудобно управлять.
Саша:
Мы собрались с Сахеем и начали писать приложение в духе лучших стартапов. Заказали пиццу. Пива там не было, поэтому мы пили кофе. За один день у нас был готов прототип, который уже выполнял свою задачу. Игра запускалась, был первый квадратик, который начинал ездить. Он поедал эмодзи, змейка росла; врезавшись в стенку, она умирала. Осталось её только докрутить: добавить включение и выключение звука, доработать экраны начала и конца игры. Этим мы занялись уже в свободное время дома.
Сахей:
Очень понравился этот режим стартапа. Обычно на работе есть все спецификации и документация протоптанная тропинка, по которой ты идёшь. А тут был полный полёт мысли. Мы ещё хотели изначально поменять рендеринг на SwiftUI или на UIKit, но не стали так извращаться, SpriteKit отлично подходил для нашей задачи. Он оптимизирован под отрисовку спрайтов. Если в UIKit 100-200 вьюшек, то FPS очень сильно проседает, а в SpriteKit нет. Но мы фана ради хотели попробовать.


Разработка MVP.

В феврале ребята пришли с готовым прототипом к руководителю направления и показали, как змейка могла бы выглядеть внутри приложения Delivery Club. Мы собрали небольшую рабочую группу, в которую, помимо ребят, вошла дизайнер продукта Лера Зуйкова. И решили доводить проект до совершенства.

Финальную версию змейки пришлось достаточно сильно упростить ребята увлеклись и придумали много дополнительных возможностей. Решили оставить простой и красивый вариант, чтобы не отвлекать пользователя от основной функции приложения.
Саша:
Когда Лера показала свой дизайн, у нас с Сахеем загорелись глаза. Мы такие: Вау! Можно же настолько красиво и современно всё сделать! У нас появилась куча новых идей. Можно нарабатывать опыт у змейки с каждой игрой и набирать очки, за них покупать змейке какой-то апгрейд, типа шапочки или щита, чтобы она врезалась в стенку, а у неё на одну жизнь больше было. Но всё-таки история со змейкой должна была где-то кончиться, чтобы дойти до релиза. И мы решили упростить игру, чтобы не смещать фокус с основного функционала Delivery Club.
Лера:
На самом деле, когда в работе есть много рутинных задач, и внезапно кто-то приходит и предлагает сделать игру, это очень воодушевляет. Поэтому мы сразу активно включились в историю со змейкой и стали делать супер-красивые дизайны, продумывать механики. Все механики не были добавлены в финальный релиз ещё и потому, что вначале мы хотели всё проверить. Просто потратить кучу времени на разработку и сделать фичу, которую потом нашли бы три человека, было бы странно. Поэтому мы сошлись на простом решении, которое можно было быстро сделать, запустить и посмотреть реакцию пользователей. Если это окажется интересным, мы будем развивать игру: делать рейтинги, баллы и так далее.
Георгий:
После того, как ребята реализовали версию под iOS, мы принялись адаптировать приложение под Android. Разработка велась на Kotlin, всё сделали нативно, без использования сторонних библиотек. В конечном итоге версию под Android получилось написать всего за четыре дня. Идея была творческой и разнообразила череду рутинных задач.
Реализацию Android-версии Змейки можно посмотреть на GitHub.



Промежуточные варианты дизайна экранов.

18 мая змейку добавили в приложение Delivery Club. Чтобы в неё поиграть, нужно потрясти телефон на экране с заказом. Мы нигде не писали про пасхалку, но уже сейчас в неё играют 5-7 тысяч человек в день со средним временем игры 3 минуты 10 секунд. Нескольким тысячам пользователей игра скрасила минуты ожидания заказа. Надеемся, теперь игроков станет больше.

А если после прочтения у вас появились собственные идеи для пасхалок в Delivery Club, принимайте участие в нашем конкурсе. Лучшие идеи будут опубликованы на N + 1 и, возможно, реализованы в нашем приложении.
Подробнее..

Дайджест интересных материалов для мобильного разработчика 397 (7 13 июня)

13.06.2021 14:11:44 | Автор: admin
В этом дайджесте обсуждаем конференцию WWDC и ее последствия, быстрые обновления Android и ответственность команд, автоматизацию с помощью таблиц, применение КММ, цвета, элементы управления и многое другое.



Этот дайджест доступен в виде еженедельной рассылки. А ежедневно новости мы рассылаем в Telegram-канале.

iOS

Xcode Cloud, SharePlay, Focus самое важное с Keynote WWDC21
Apple убивает TeamCity, Bitrise, Appcenter, Fastlane, Firebase, Sentry и иже с ними. Краткий обзор Xcode Cloud
Делаем OpenVPN клиент для iOS
iOS интервью в Vivid
Лучшие приложения для iPhone весят почти в 4 раза больше, чем пять лет назад
Mobile People Talks: WWDC21
Apple выпускает бета-версии прошивок AirPods для разработчиков
iOS 4 воссоздали как приложение для iPhone
Дырявим вьюхи на Swift
Apple уточняет правила публикации в App Store
Apple разрешит пользователям остаться на iOS 14
Новые функции iPadOS 15
Apple представила новые технологии и инструменты для разработчиков приложений
watchOS 8: новые функции доступа, возможности подключения и практики осознанности
Apple представила iOS 15
Главное в iOS 15 для дизайнеров
Доклад Platforms State of the Union с WWDC 2021
Отчеты о сбоях iOS с LLDB
Онбординг SwiftUI в приложении UIKit
Лучшая маршрутизация глубоких ссылок в iOS-приложении
Что мы узнали из инцидента с OOM в iOS-приложении Pinterest
Делаем бесконечную прокрутку фотографий в iOS
Что нового в SwiftUI после WWDC21
SwiftUI двунаправленный список SnapList
Использование SwiftUI с View Model, написанной на Kotlin Multiplatform Mobile
Пишем первое приложение для iOS с помощью Realm, SwiftUI и Combine
Что нового в StoreKit 2
Как мы используем SwiftUI в приложении Medium
Что нового в SwiftUI 3.0?
Как сделать иконку для темного режима для вашего приложения
iOS 15 привносит атрибутные строки в SwiftUI
Понимаем AsyncImage в SwiftUI
Indicate: тосты в стиле AirPods
SimpleAnalytics: своя аналитика для iOS

Android

Долгая дорога к быстрым обновлениям Android
Миграция с LiveData на Kotlins Flow
Бесконечная автопрокрутка списков с помощью RecyclerView и LazyLists в Compose
Разработчики могут подать заявку на снижение комиссии до 15% через Play Store
Flutter Dev Podcast #28: Google I/O 2021
Корутины обработки ошибок
Проблема трех фреймворков в Kotlin Multiplatform Mobile
Современная архитектура Android с шаблоном проектирования MVI
Азбука модульности Android в 2021 году
Навигация в Jetpack Compose
Несколько бэк-стэков
Работа с сетью в Kotlin Ktor на Android
Автогенерация пользовательских размеров для Android с помощью Kotlin
Глубокое погружение в интернационализацию приложений для Android на Jetpack Compose
Датабиндинг в Android
Чистая архитектура Android [точка зрения]
Создаем приложение CoroutineScope с помощью Hilt
Пагинация в Android с Paging 3, Retrofit и Kotlin Flow
CompleteKotlin: автодополнение для всех платформ
TimeRangePicker: круглый range picker для Android

Разработка

Кто, где, когда: система компонентов для разделения зон ответственности команды
Автоматизация или смерть: как управлять тысячами единиц игрового контента с помощью гугл-таблиц
Appwrite, open-source бэкэнд-платформа
Роль QA Lead в продуктовой компании: особенности и зоны ответственности
Вызов кода Go из Dart с использованием cgo и Dart FFI на простом примере
Создание прекрасных приложений с помощью Xamarin.Forms
We need to go deeper: как пасхалка в приложении Delivery Club сократила субъективное время ожидания еды
Тестируем и визуализируем с помощью Mind Map
Автоплатеж, автооплата или автопополнение? UX-кейс
Как стать тестировщиком с нуля
Podlodka #219: выбор первой профессии в IT
Дизайн приложений: лауреаты премии Apple Design Awards 2021
КММ на практике или выбор кроссплатформенного фреймворка для Леруа Мерлен
Исследование разработчиков HackerEarth 2021
Отключенные кнопки не должны путать пользователей
Распродажа книг по Data Science и аналитике данных в Humble Bundle
6 мощных инструментов для разработчиков, использующих Mac
Как мы улучшили сегментированные элементы управления (segmented control)
Руководство для новичков по применению цвета в UI дизайне
Пошаговое руководство по работе в Figma. Урок по созданию мобильного приложения
Принцип IBM Leadership-as-a-service обеспечивает профессиональный рост команд
Топ-5 шаблонов проектирования распределенных систем
ELI5: Flipper кроссплатформенный дебагер
Как ежедневно улучшать навыки архитектуры ПО
Анимированный TabBar Coinbase в React Native
Как проверять код Junior разработчику
Разработчики не могут исправить плохой менеджмент

Аналитика, маркетинг и монетизация

WWDC 2021: новое и полезное для разработчика, ASO спецалиста, маркетолога мобильных приложений
Почему подписываются пользователи? Как повысить конверсию мобильных приложений
Classplus: Spotify для образования
AppsFlyer: на 570% выросло количество неорганических установок финансовых приложений в России
Стратегия победителя: как покорить весь мир, начиная с Якутска? Кейс inDriver и Rocket10
Кейс: как вытеснить конкурентов из поиска, оптимизируя инаппы?
Практические инструменты и преимущества отслеживания удалений мобильных приложений
Онбординг в мобильном приложении: как поддерживать интерес пользователей

AI, Устройства, IoT

Как Яндекс применил генеративные нейросети для поиска ответов
Маленький и быстрый BERT для русского языка
Начинаются продажи карманной игровой приставки Playdate
Защищенный смартфон, контролируемый ФБР, раскрыл действия сотен преступников

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

Гайд по тестированию рекламы для мобильных приложений

15.06.2021 18:13:51 | Автор: admin

Тестировать рекламные механики не так просто, как может показаться. Главные действующие лица здесь сторонние SDK, которые не особо подконтрольны команде разработки. А так как рекламные интеграции важная часть наших мобильных приложений, то ниже вместе с @maiscourt и @santypa расскажем, как мы это делаем.

Далее список инструментов с описаниями, задачи тестирования и некоторые внутренние гайдлайны.


Для тестирования в основном используется тестовая реклама, которую партнёры готовят заранее. Это делается, потому что разные характеристики рекламы на продакшене не позволяют быть уверенным, что новый функционал или фикс бага не задели основные параметры и работу рекламного креатива.

Но получение тестовой рекламы требует изменения определённых параметров в наших экспериментах, обращения к тестовой админке медиатора, добавления тест-мода (специальные параметры, чтобы партнёр понимал, что запрашивается именно тестовый креатив), использования своей дебаг-панели, а также VPN по странам, а в отдельных кейсах по городам.

И тут нам понадобятся некоторые инструменты.

Инструменты

Ниже список инструментов, которые мы используем при тестировании рекламы, а потом перейдём к задачам.

  1. Сниффер для анализа трафика (у нас Charles).

  2. Админка у медиатора, где можно настроить получение рекламы от конкретного партнёра на свой тестовый юнит (специальный id, используя который, паблишер запрашивает рекламу у медиатора).

  3. Своя админка с фича-тогглами, где можно включить/отключить, или изменить наши эксперименты.

  4. Наша дебаг-панель.

  5. VPN.

  6. Внешние гайдлайны.

  7. Внутренняя база знаний и Confluence для её хранения.

  8. Чек-листы.

  9. Zephyr для хранения тест-кейсов.

Пройдёмся по каждому.

Инструмент 1. Charles. Активно используется не только тестировщиками, но и разработчиками. Практически все задачи требуют замены продакшн параметров на тестовые. Например, часто возникает необходимость добавить в конфиг эксперимент или обращаться к тестовым юнитам медиатора.

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

Инструмент 2. Тестовая админка медиатора. Медиатор это специальная платформа, которая позволяет подключать приложение сразу к нескольким рекламным сетям, а также управлять показом рекламы (например, Google AdMob, Fyber и другие). Ещё во время онбординга мы проводим обучающие курсы по рекламе, где сотрудники в тестовой админке медиатора создают свой тестовый юнит для настройки параметров рекламы под себя.

Инструмент 3. Админка с фича-тогглами. Практически все рекламные (и не только) механики в приложении iFunny закрыты под фича-тогглы (механизм реализации, при котором часть кода прячется за флаг, контролирующий его включение или выключение). Это нужно, чтобы сделать более надёжным и безопасным выпуск той или иной функциональности.

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

Документацию обновляем и дополняем по мере необходимости: если после обновления SDK изменилась описанная логика работы, или если вышли нормативы/регламенты, требующие внесения обязательных правок.

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

Инструмент 5. VPN. В основном используется для проверки задач, связанных с GDPR и CCPA. Для тестирования GDPR подходит VPN с возможностью получения IP европейской страны. Для тестирования CCPA необходим VPN с возможностью получения калифорнийского IP.

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

  • рекламные креативы и их идентификаторы, которые используются для настройки и получения тестовой рекламы;

  • форматы запросов и ответов рекламной SDK, а также параметры, из описания которых понимаем, за что они отвечают, и какие возможные значения для них допустимы;

  • changelog изменений рекламных SDK чтобы понять, на какие изменения при обновлении SDK нужно обратить внимание во время тестирования.

Инструмент 7. Внутренняя документация. Внешние гайды не всегда являются достаточно подробными. Кроме того, проверка одной и той же функциональности от разных SDK требует переключения между разными источниками для поиска необходимой информации. Поэтому оказалось удобным агрегировать информацию из разных гайдлайнов SDK и делать сборную внутреннюю документацию в нашем Confluence, дополняя её своими комментариями.

Инструмент 8. Чек-листы. Наравне с внешней и внутренней документацией для проверок различных задач используем чек-листы (пример можно посмотреть ниже в разделе про обновление SDK). Для такого типа задач, как проверка обновлений SDK, обновлений медиатора или адаптеров, мы используем уже составленный чек-лист, который изменяется по мере необходимости.

Для остальных задач составляем чек-листы либо в процессе разработки задачи, либо непосредственно перед тестированием, в зависимости от сложности задач.

Инструмент 9. Тест-кейсы. Тест-кейсы неотъемлемая часть тестирования любого проекта/функциональности, в том числе рекламы. Тест-кейсы разделены по приоритетам, что позволяет использовать risk-based testing, о котором будет рассказано подробнее ниже. В тест-кейсах фигурируют такие проверки, как загрузка и показ рекламы, запросы на рекламу, работа разных механик (например: водопад, аукцион), а также запрос и отображение рекламы от партнёрских рекламных сетей. Данные проверки в полной мере позволяют убедиться, что рекламный функционал работает без сбоев/корректно.

Задачи

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

Разберём, с чем приходится сталкиваться на постоянной основе:

  1. Обновление SDK.

  2. Тестирование форматов.

  3. Безопасность.

  4. Регрессионное тестирование.

  5. Смоук тестирование.

  6. Другие задачи (юридические вопросы, локализации, эксперименты, аналитика, рефакторинг и так далее).

Задача 1. Обновление SDK. Можно сказать, что обновление SDK наиболее популярная задача в рамках тестирования рекламы. Из-за частого проведения тестирования обновлений SDK (а также медиатора или адаптеров) составили чек-лист проверок:

  • Вёрстка. Проверяем всё: центрирование, размер, отображение на устройствах с разными разрешениями экранов.

  • Пользовательские сценарии. Тап по контенту/кнопке и по privacy icon, возврат в приложение, воспроизведение и остановка видеорекламы.

  • Репорт (отправка жалоб, связанных с рекламой). Пользователь может пожаловаться на рекламный контент или сообщить о технических проблемах.

  • Соответствие стандартам GDPR и CCPA.

  • Отправка аналитики. Внутренняя и внешняя (партнёру и медиатору).

  • Технические проверки. Например, уход в фон во время загрузки рекламы.

Задача 2. Тестирование форматов. Баннерная и нативная рекламы у нас закрепились и работают стабильно, но мы пробуем интегрировать и другие виды, в частности, fullscreen-рекламу. В целом, тестирование Rewarded Video и Interstitial во многом схоже с тестированием других видов: проверяется корректная загрузка и отображение рекламы, а также отправка аналитики.

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

Отдельно нужно сказать про механику Rewarded Video после окончания просмотра рекламы (или просмотра до определённой временной метки) пользователь должен получить вознаграждение. Поэтому очень важно хорошо протестировать этот функционал.

Подробно про разные форматы мобильной рекламы мы уже писали в отдельной статье.

Задача 3. Безопасность. Чтобы следить за качеством трафика, интегрировали в iFunny внешнее антифрод-решение. В него для дополнительной проверки атрибуции показов и кликов на каждое событие генерируется новое. На стороне системы с помощью технологий машинного обучения и большого объёма накопленных данных происходит дальнейший анализ. Со своей стороны мы проверяем отправку и разметку событий для разных сетей и разных типов рекламы.

Задача 4. Регрессионное тестирование. Раз в две недели iFunny релизится на iOS и Android. Независимо от количества рекламных задач, попавших в релизную ветку, мы проводим регрессионное тестирование рекламного функционала/блока. В регрессионных паках собраны следующего рода проверки:

  • Основные проверки, что реклама запрашивается и отображается на нужных экранах приложения.

  • Работа нативной и баннерной рекламы, а также рекламных сетей, с которыми сотрудничаем по сути, это упрощённый чек-лист, используемый для тестирования SDK (добавления, обновления).

  • Работа разных механик: водопад и биддинг (что это такое, можно ознакомиться здесь).

  • Проверка на соответствие юридическим нормам.

  • Проверки каких-то наших внутренних разработок (например, эксперименты с дизайном).

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

Проведение полного ручного прогона регресса занимает порядка 2-3 дней. Поэтому, чтобы сократить время прохождения регресса, используется практика проведения Risk-based testing (вид тестирования, основанный на вероятности риска). Суть такого тестирования исключить некоторое количество тест-кейсов из прогона, проведение которых не может выявить потенциальных ошибок на текущем релизном билде. Иными словами, кейс не имеет смысла включать в регрессионное тестирование, если при разработке не был затронут функционал, проверяющийся в кейсе.

Задача 5. Смоук тестирование. Перед тем, как выкладывать сборку в сторы, а также при тестировании хотфиксов, мы прогоняем смоук тесты. В рамках смоук тестирования реклама проверяется, но не так детально, как при регрессе. Мы тестируем основные моменты, связанные с рекламой, а именно её загрузку и отображение.

Задача 6. Другое. К тестированию других задач можно отнести:

  • юридические задачи, например, связанные с GDPR и CCPA;

  • задачи локализации (для пользователей iFunny из Бразилии);

  • эксперименты, связанные с дизайном рекламы;

  • задачи аналитики;

  • рефакторинг, оптимизации. Например, оцениваем доступный нам для анализа контент на предмет валидности.

Бонус. Онбординг новых сотрудников

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

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

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

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

Вместо заключения

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

Подробнее..

За что App Store может отклонить приложение чек-лист

18.06.2021 14:19:30 | Автор: admin

App Store самая строгая площадка для размещения приложений. Ревью проходит дольше и строже, чем у Google Play и Huawei App Gallery. В 2020 году AppStore отклонил миллион приложений, которые публиковались впервые, и миллион апдейтов.

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

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

Мы составили чек-лист очевидных и не очень очевидных причин, по которым AppStore отклоняет приложения. Сам чек-лист в гугл-доке. В статье раскроем подробнее каждый пункт.

Нарушения политики конфиденциальности и пользовательских данных

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

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

Нарушение функциональных требований

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

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

У нас в Surf, например, однажды отклонили приложение, потому что в нём была подключена библиотека для Apple Pay, но она нигде не использовалась.

UI, не соответствующий Human Interface Guideline. Сложное для использования приложение, имеющее нелогичное поведение и расположение элементов, отклонят.

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

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

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

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

Для распознавания по FaceID используются сторонние технологии. Идентификация пользователя по FaceID должна происходить только с помощью библиотеки LocalAuthentication.

Нет входа по AppleID, если есть возможность входа через соцсети. Это обязательно для iOS 13 и новее.

Нарушения в оформлении приложения

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

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

Есть слова Beta, Demo или Debug в названии приложения. Такие приложения запрещены к публикации в магазине App Store. Для бета-версий есть Test Flight.

Нет описания новой функциональности у обновлённого приложения. Если в приложении появилась новая функциональность, необходимо описать её в поле в App Store Connect. Без чёткого описания приложение ревью не пройдёт.

Скриншоты приложения, иконка и другой контент на странице магазина не подходят для аудитории 4+. И не важно, что приложение может быть не предназначено для такого возраста: аудитория App Store дети от четырёх лет.

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

Не стоит указывать в описании или на скриншотах, что продукт имеет отношение к Apple либо компания отвечает за качество, если это не так. Если приложение станет выбором редакции, Apple автоматически установит на нём соответствующую иконку.

Файл с расширением .ipa превышает размер 50 мб в момент публикации.

Нет демо-пользователя для ревью, если приложение требует обязательной авторизации.

Не указаны правила участия и выигрыша, если в приложении есть розыгрыши, рулетки или казино. Следует явно написать, что Apple не имеет никакого отношения к этим конкурсам и розыгрышам.

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

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

В период пандемии этот пункт стал особенно важен: Apple строго следит за распространением информации, связанной с COVID-19.

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

Контент оскорбляет людей разных рас, вероисповеданий, сексуальной ориентации, национальности.

Приложение поощряет незаконное использование оружия или позволяет его купить.

Есть откровенно сексуальный или порнографический контент.

Приложение разрешает анонимную отправку смс/ммс, анонимные звонки, розыгрыши.

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

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

Покупки в приложении

Цифровой контент продаётся не через in-app purchase.К цифровому контенту относятся подписки, музыка в приложении, видео, расширенный доступ к функциям.

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

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

Приложение не предоставляет пользователю всю необходимую информацию о покупке до момента продажи. Это важно, если приложение использует Apple Pay. Также недопустима кастомизация окна оплаты.

Категория Kids

Kids в App Store отдельный вид приложений. К ним Apple относится максимально строго. Категория Kids делится на три подкатегории: до 5 лет, 68 лет, 911 лет.

Есть внешние ссылки, покупки и другие отвлекающие факторы. Такие элементы требуют дополнительной защиты и отделения от функциональности, которую используют дети. Исключение составляют опции родительского контроля.

Не соблюдены законы, касающиеся защиты конфиденциальности детей в интернете. Запрещено отправлять личную информацию и данные об устройстве третьим лицам.

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

Составили гугл-док с чек-листом требований для ревью App Store.

А по каким причинам App Store отклонял ваши приложения? Расскажите в комментариях.

Подробнее..

Дайджест интересных материалов для мобильного разработчика 398 (14 20 июня)

20.06.2021 12:09:43 | Автор: admin
В этой подборке исследуем StoreKit 2, распознаем лица и позы на Android, улучшаем производительность React-приложений, учим сквирклморфизм и многое другое!



Этот дайджест доступен в виде еженедельной рассылки. А ежедневно новости мы рассылаем в Telegram-канале.

iOS

За что App Store может отклонить приложение: чек-лист
Meet StoreKit 2
Тим Кук: на Android в 47 раз больше вредоносных программ, чем на iOS
Новый антимонопольный акт может заставить Apple продать App Store
Что нового во встроенных покупках в iOS 15 WWDC 21
Строим лабиринты с SwiftUI
iOS 15: заметные дополнения к UIKit
Info.plist отсутствует в Xcode 13 вот как его вернуть
ScrollView в XCode 11
Создаем игры на SwiftUI с помощью SpriteKit
Мастерим списки в SwiftUI
Как лучше структурировать свои проекты в Xcode
Глубокое погружение в Акторы в Swift 5.5
Разработка функций iOS-приложения в виде модулей в Xcode
Как делать видеозвонки с помощью SwiftUI
Euler: вычислительный фреймворк на Swift
WorldMotion: положение устройства относительно Земли

Android

Как использовать Android Data Binding в пользовательских представлениях?
AppSearch из Jetpack вышел в альфа-версии
Распознавание лиц и поз за 40 минут
Android Broadcast: новости #10
Создайте свою библиотеку KMM
История моего первого а-ха-момента с Jetpack Compose
Как стать ассоциированным разработчиком Android (Kotlin Edition)
Анимации Jetpack Compose в реальном времени
RecyclerView с NestedScrollView: лучшие практики
Android Bitbucket Pipeline CI/CD с Firebase App Distribution
CompileSdkVersion и targetSdkVersion в чем отличие?
Нижняя панель навигации Android с Jetpack Compose
Интеграция Google Sign-in в Android-приложение
Focus в Jetpack Compose
DashedView: полосатые View
Screen Tracker: название видимого Activity/Fragment
SquircleView: красивые View

Разработка

5 000 000 строк кода, 500 репозиториев: зачем мы адаптировали приложение AliExpress для Рунета
Десятикратное улучшение производительности React-приложения
gRPC + Dart, Сервис + Клиент, напишем
Podlodka #220: волонтерство в IT
Хороший день разработчика: Good Day Project от GitHub
К 2024 году 80% технологических продуктов будут создавать непрофессионалы
Сквирклморфизм (Squirclemorphism) в дизайне интерфейсов
12 рекомендаций, которые помогут улучшить процесс регистрации и входа в систему
React Native в Wix Архитектура (глубокое погружение)
Как узнать плохой код? 8 вещей
5 лучших пакетов Flutter, которые вы должны знать
Советы по кодинг интервью в Google
Как стать плохим разработчиком

Аналитика, маркетинг и монетизация

Гайд по тестированию рекламы для мобильных приложений
Вслед за Apple и Google комиссию магазина приложений снизила Amazon
make sense: О инфлюенсер-маркетинге
UserLeap получает еще $38 млн на отслеживание пользовательского опыта
Классическая MMORPG RuneScape запускается на iOS и Android
Маркетологи в мобайле: Александр Плёнкин (Vprok.ru Перекрёсток)
Почему такие скриншоты пустая трата времени? (пока у вас нет 4,000 загрузок в месяц)
Amplitude получил еще $150 млн
$100 млн для Free Fire: как младший брат может обогнать старшего на уже сложившемся рынке?
App Annie: рынок мобильных игр в России в 2020 вырос на 25% до $933 млн
Темные паттерны и уловки в мобильных приложениях
Использование BigQuery и Firebase Analytics для привлечения, вовлечения и оценки пользователей

AI, Устройства, IoT

Запускаем DOOM на лампочке
Быстрое обнаружение Covid-19 на рентгеновских снимках с помощью Raspberry Pi
Как я учу Python на Raspberry Pi 400 в библиотеке
Топ-5 преемников GPT-3, о которых вы должны знать в 2021 году

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

Категории

Последние комментарии

© 2006-2021, personeltest.ru