¿Qué habilidades se necesitan para crear una aplicación de iOS? Informe Yandex

Un desarrollador móvil necesita tener un conjunto claro de habilidades. Debe hablar sobre ellos en el contexto de tareas específicas que surgen durante la creación y publicación de la aplicación. Arthur Antonov trabaja como desarrollador de iOS en el departamento de traducción automática de Yandex. En su informe para estudiantes y principiantes, Arthur explicó lo que un desarrollador debe poder hacer para crear un software móvil moderno.


- Hay dos aplicaciones móviles en nuestro departamento: Yandex.Translate y Yandex.Keyboard. En Translator tenemos muchas tecnologías sofisticadas, por ejemplo, entrada de voz, reconocimiento de texto por foto, traducción de texto usando redes neuronales. Un desafío separado es mantener esta funcionalidad fuera de línea. Es decir, esta funcionalidad funcionará incluso sin Internet.



El teclado es una clase separada de aplicaciones; existen requisitos separados para su velocidad y la calidad de la aplicación misma. La corrección automática en ruso funciona para nosotros: ayuda al usuario, pero no lo molesta. Entrada de voz, entrada de deslizamiento.





Otra característica interesante es la cuadrícula dinámica: intenta predecir la siguiente letra y, dependiendo de esto, cambia el tabson. Es decir, es más fácil entrar en una carta más probable.



En la escuela me dedicaba a la programación deportiva. Pero cuando ingresé a la universidad, me pareció que ya era un poco aburrido, quería desarrollar programas para la gente común, y es deseable que estén disponibles siempre y en todas partes. Entonces decidí elegir el desarrollo móvil. Pero las aplicaciones móviles son multifacéticas, y la pregunta más importante que me ha surgido es por dónde comenzar.

Internet ahora está lleno de cursos en línea, tutoriales, libros sobre diversos temas, y la cabeza simplemente explota. No está claro por dónde empezar. Por lo tanto, en mi informe, me gustaría ayudarlo a construir su camino de aprendizaje para convertirse en un desarrollador móvil. Lo que vale la pena estudiar al principio, el estudio de lo que se puede posponer.



Después de analizar mi trabajo durante varios años, identifiqué varias habilidades clave que son necesarias para resolver la mayoría de los problemas. Estas son habilidades fundamentales y las llamadas habilidades de caja de herramientas. No son necesarios al desarrollar aplicaciones móviles, pero si las posee, su vida será más fácil y la calidad de sus aplicaciones será mucho mejor.

Dado que una teoría sin práctica está muerta, estudiaremos habilidades usando el ejemplo de una versión simplificada de Yandex.Translator. Cuando haya realizado el proyecto, todo lo que verá es una pantalla en blanco.

Revivamos nuestra aplicación usando la interfaz de usuario.





Hay dos formas clásicas de crear una interfaz: un editor gráfico y un código. Este es uno de sus temas de Hollywood en el desarrollo móvil. Hay seguidores del desarrollo en un editor gráfico, y alguien no reconoce nada excepto el código. Pero te aconsejo que pruebes ambos métodos. Seguramente los encontrará, y además, nadie le prohíbe combinar enfoques, por ejemplo, cosas simples que hacer en un editor gráfico y complejas que ya están en el código.



Y recientemente, los desarrolladores de iOS tienen un nuevo marco SwiftUI que está tratando de combinar estos dos enfoques. Es decir, cuando cambia en un editor gráfico, su código cambia y viceversa. Quizás cuando este marco se generalice, todas las disputas quedarán en el olvido.

Desafortunadamente, SwiftUI solo está disponible a partir de iOS 13, por lo que hasta ahora no se puede usar en proyectos grandes.



El editor gráfico tiene una interfaz muy simple. Tomamos componentes listos, los arrastramos a una pantalla virtual e inmediatamente vemos lo que obtenemos. Por esta razón, es muy rápido crear componentes de interfaz de usuario simples. También podemos cambiar el tamaño de la pantalla virtual para diferentes dispositivos y probar nuestra interfaz sin iniciar la aplicación.





Por otro lado, tenemos un diseño de interfaz en el código. Al desarrollar una interfaz en su código, la biblioteca UIKit será útil, y usará pequeños bloques de construcción llamados UIView. Los objetos UIView corresponden aproximadamente a los componentes que ha mostrado en la pantalla. Y al igual que en un editor gráfico, tiene subclases listas para usar para componentes de uso común, como botones y texto.

Cuando se desarrolla en código, es muy importante comprender que otras UIViews pueden crear UIView dentro de sí mismas, es decir, puede construir interfaces de cualquier complejidad. Como resultado, obtienes el llamado árbol. Es más fácil modificar desde el código. Es decir, si tiene una interfaz de usuario muy dinámica, puede valer la pena escribirla en código y le será más fácil modificarla más adelante.



Veamos qué código se puede escribir para nuestro traductor.

Primero establecemos el color de fondo en amarillo. Luego agregamos un campo de entrada donde el usuario ingresa el texto en inglés. A continuación, agregamos un separador para belleza y, finalmente, agregamos un campo de salida, mientras prohibimos que el usuario lo edite.

Tenemos una interfaz de usuario lista, pero la aplicación sigue siendo bastante inútil. No resuelve la tarea principal del usuario: la traducción del texto.

Agreguemos esta funcionalidad. Las características de la plataforma SDK nos ayudarán.



Los SDK de plataforma son un conjunto de herramientas y bibliotecas para crear aplicaciones móviles que nos proporcionan Apple y, en consecuencia, Google.

Actualmente, el SDK tiene muchas bibliotecas de bajo nivel para interactuar con el sistema operativo, y puede implementar casi cualquier idea de una aplicación móvil sin mucho esfuerzo.

Las bibliotecas que usará dependen de los detalles de su aplicación. Por ejemplo, si queremos hacer una cámara, lo más probable es que necesite dos bibliotecas: AVFoundation para trabajar con la cámara y CoreImage para el procesamiento de imágenes.

Por lo tanto, en esta etapa no es necesario memorizar todas las bibliotecas, es simplemente imposible. Más importante es la capacidad de encontrar las herramientas adecuadas. Y desafortunadamente, la documentación oficial no siempre documenta completamente las características. A veces encuentras algunas cosas interesantes, por ejemplo, en un blog o en el twitter de otro desarrollador. Vale la pena seguir el campo de información.

Entonces, ¿qué necesitamos del SDK para nuestro traductor?



Nuestro traductor es una aplicación cliente-servidor clásica: hacemos una solicitud al servidor y obtenemos una respuesta. Luego, de alguna manera, lo transformamos y se lo mostramos al usuario. El marco de la Fundación nos ayudará para esta tarea. Contiene abstracciones convenientes para resolver tareas cotidianas.

Tomaremos la clase URLSession, esta es la clase para trabajar con el servidor utilizando el protocolo http, y JSONSerialization, esta es la clase que nos ayuda a convertir objetos del formato JSON.



Entonces, veamos qué código necesitamos escribir para esta funcionalidad. A la izquierda hay un método que se ejecuta cada vez que se cambia la entrada del usuario. Primero creamos una URL con la dirección del servidor del traductor y hacemos una solicitud. Además, después de recibir la respuesta, la analizamos desde el formato JSON, obtenemos el texto deseado, es decir, el texto de traducción. Y el último paso: decimos que en el campo de entrada debe configurar la respuesta recibida.

Veamos que tenemos. El usuario ingresa hola y aparece "hola":



Pero "hola" apareció de alguna manera durante mucho tiempo, no parecía retrasos en la red. Para mayor confiabilidad, comparemos con el hermano mayor:

GIF abierto

En ambas aplicaciones, ingresamos el texto hola y vemos que la traducción ya apareció varias veces en el traductor real. En nuestro traductor, la traducción aparece con un gran bloqueo.

Para solucionar este problema, debemos familiarizarnos con el modelo de subprocesamiento múltiple en aplicaciones móviles.



Al igual que las computadoras de escritorio, las aplicaciones móviles se ejecutan en un entorno multiproceso. Pero hay una limitación importante. Una aplicación móvil tiene un hilo principal o un llamado hilo de interfaz de usuario. Y cualquier operación con la interfaz de usuario, cualquier cambio en la interfaz de usuario debe ocurrir en este hilo principal. Si desea cambiar el color del botón o moverlo, todo debería estar en la secuencia de la interfaz de usuario.

Por otro lado, todas las interacciones del usuario también nos llegan en el hilo principal. Es decir, el usuario hizo clic en un botón: recibimos un mensaje en el hilo principal. Cambiamos el texto, como en nuestro caso, también lo obtuvimos en el hilo principal. Dado que solo hay una secuencia y todas las acciones con la IU tienen lugar en ella, es muy importante cuidarla y hacer el menor cálculo posible, de lo contrario corre el riesgo de estar en una situación en la que está procesando una acción del usuario durante mucho tiempo y tiene una cola de otras acciones del usuario. Entonces todo comienza a congelarse.

Por esta razón, muchas bibliotecas del sistema se ejecutan de manera predeterminada en una secuencia de fondo. Por ejemplo, un viaje a la red toma un promedio de 100 a 500 milisegundos. Esta es una operación bastante costosa para la transmisión principal, por lo que toda interacción con la red tiene lugar en la transmisión en segundo plano.

Y, de nuevo, esto nos crea problemas, porque si usamos el resultado obtenido del servidor de forma inadvertida para cambiar la interfaz de usuario de forma inadvertida, esto puede provocar un bloqueo o un bloqueo.

Recordemos nuestra última línea:

self.textOutputView.text = translation

En él, tomamos el resultado del servidor y lo configuramos en el campo de salida. Por lo tanto, violamos la primera regla: cambiamos la interfaz de usuario no desde el hilo principal. La biblioteca estándar Grand Central Dispatch ayudará a solucionar esto. Con bastante facilidad nos ayuda a cambiar al hilo principal y realizar esta acción en el hilo principal.

DispatchQueue.main.async {
  self.textOutputView.text = translation
}

Veamos qué obtuvimos con la aplicación al final.



El usuario ingresa texto, y vemos que la traducción ocurre casi instantáneamente. ¡Hurra! Derrotamos este problema. Pero, antes de lanzar la aplicación, hablemos de otro tema importante: la arquitectura.

Desafortunadamente, en el proyecto actual no podré demostrarle la importancia de la arquitectura, todavía es muy pequeña.



Pero, te aseguro, la arquitectura no surgió de una vida mejor, no del hecho de que los desarrolladores no tienen nada que hacer y escriben abstracciones para que no se despidan. La arquitectura es la respuesta a los desafíos del desarrollo móvil.

El principal de estos problemas es la escalabilidad. Cuando su aplicación se vuelve demasiado grande y tiene una funcionalidad diferente, es importante que sea fácil de entender, expandir y depurar. De lo contrario, cualquier adición de características cambiará todas las antiguas. Y aumenta el riesgo de que tengamos errores.

No espere hasta que su aplicación crezca. Ya en la etapa inicial, puede aprender las prácticas básicas de creación de software que también funcionan para aplicaciones móviles, como SOLID, patrones de pandillas de cuatro.

La arquitectura de las aplicaciones móviles tiene sus propios detalles: sus componentes globales o grandes se construyen de acuerdo con patrones arquitectónicos que dicen en un alto nivel qué objetos deben pertenecer a qué capa. Los más populares son MVC, MVP y MVVM.

Y no olvidemos que en realidad la arquitectura no es una bala de plata. Es necesario tener en cuenta los detalles del proyecto. Si está incorporando algún tipo de arquitectura a su proyecto con lágrimas en los ojos, tal vez algo salió mal.

Cuando estudias teoría, te parecerá terriblemente complicado. Pero, de hecho, cuando trabajas en un proyecto con buena arquitectura, estarás contento porque te ha resultado más fácil escribir código. Sabes qué y dónde agregar para tener una función. Por lo tanto, en esta etapa, para conocer bien la arquitectura, le aconsejo que trabaje o realice una pasantía en un gran proyecto. Si no tiene esa oportunidad, entonces muchas compañías ponen sus proyectos en código abierto: Wikipedia, Firefox. Y nadie te prohíbe ir a GitHub y ver allí.

Entonces, nuestra aplicación está lista. Vamos a ponerlo en el dominio público para que los usuarios puedan descargarlo.



En la mayoría de los casos, los usuarios obtienen aplicaciones de Google Play y App Store. Pero antes de agregar la aplicación a la Tienda, debemos firmarla. Esto se debe al hecho de que los sistemas operativos ejecutan aplicaciones solo de desarrolladores confiables. Por lo tanto, en las plataformas móviles tenemos mucho menos aplicaciones maliciosas y virus, porque solo los desarrolladores de confianza tienen acceso para trabajar en dispositivos móviles.

Para hacer esto, debe emitir un certificado de desarrollador. Esta es en realidad una pequeña burocracia y, afortunadamente, está automatizada en las últimas versiones de Xcode.

También debe tomar capturas de pantalla para su aplicación y descripción. Los dos últimos pasos no deben descuidarse, porque la página de su aplicación es su anuncio. Si no es brillante, lo más probable es que todo nuestro desarrollo haya sido en vano, porque nadie descargará la aplicación.

La aplicación se ha cargado, ahora hablemos sobre algunas habilidades adicionales que pueden simplificar su vida y mejorar la calidad de las aplicaciones.

La habilidad que usará con más frecuencia es la depuración.



El método principal de depuración es el viejo bien console.log o printf. Tiene muchos nombres, pero el significado es el mismo. Cuando algo sale mal, agregamos registros, variables de impresión. Pero desafortunadamente, este método también tiene inconvenientes críticos.

El primero de los inconvenientes es cambiar el código fuente. Hay errores que desaparecen cuando agrega printf. Y eliminas printf - surge de nuevo. Estos errores incluso tienen un nombre diferente: heisenbug.

La segunda consecuencia es que necesita volver a compilar su aplicación y ejecutarla nuevamente. En proyectos grandes, esto puede llevar minutos, y si necesita esperar un minuto al agregar cada registro nuevo, en total pasará mucho tiempo.

Y el último inconveniente más crítico de printf: desafortunadamente, no ayuda a todos los errores.

Un ejemplo de práctica personal. Al desarrollar



la incorporación del teclado , esto sucedió: en el teclado del sistema a continuación, en lugar del globo del sistema y los íconos del micrófono, aparecieron algunos identificadores. Al depurar este error, me sentí así:



¿Cómo puede una aplicación romper un teclado del sistema? Resultó que podía.



Al investigar el error, el conocimiento del depurador me ayudó mucho. En particular, establecer un punto de interrupción para llamar a ciertas funciones. Ver Debugger, donde podemos ver nuestra interfaz de usuario y ver quién tiene qué clase y en qué estado.

Cuando aproveché estos dos primeros puntos, resultó que el problema estaba en la biblioteca UIKit. Los desarrolladores de iOS están familiarizados con él y saben que no tiene código fuente abierto. Pero cuando conoces el ensamblador, cualquier biblioteca se convierte en código abierto para ti, por lo que los pequeños conceptos básicos del ensamblador pueden ser útiles.

También existe la llamada habilidad de la ingeniería inversa. A veces es bastante aburrido, a veces interesante: una historia de detectives, donde investigas cómo un componente está conectado a otro, cómo se hace todo dentro de la biblioteca. Como resultado, resultó que el problema estaba en el tiempo de ejecución del lenguaje Objective-C.

La siguiente habilidad importante es optimizar nuestras aplicaciones.



Los dispositivos móviles tienen recursos limitados, por lo que a menudo hay un problema de rendimiento. Al desarrollar, debemos pensar en cosas como el consumo de CPU. Muy a menudo, esta es la complejidad del código que escribe. Velocidad de procesamiento, memoria y tráfico de red, ya que es más probable que la mayoría de los usuarios usen su aplicación en el tráfico móvil. Respetemos a los usuarios y tal vez sea mutuo.

El quinto punto es la batería, se deduce de los primeros cuatro.

Lo más importante al optimizar aplicaciones es identificar áreas problemáticas. Si confía solo en sus suposiciones, es probable que pierda mucho tiempo y no obtenga demasiadas ganancias. Esto ayudará a las herramientas de la plataforma. Incluyen un generador de perfiles: un programa que le muestra en qué parte del código pasa más tiempo el programa. Es decir, verá el método en el que su programa se cuelga con mayor frecuencia, y lo más probable es que encuentre la razón de la congelación.

Conocer los algoritmos y las estructuras de datos lo ayudará a encontrar una solución más eficiente. Además, el conocimiento de subprocesos múltiples puede ayudar aquí. Ahora hay procesadores multinúcleo en dispositivos móviles, y al paralelizar el problema a través de múltiples subprocesos, obtienes un ligero aumento en el rendimiento.

A veces sucede que los dos primeros puntos, desafortunadamente, no ayudan. Luego, recibirá ayuda para comprender cómo funciona el sistema operativo y conocer las llamadas del sistema, como el mapa de memoria (mmap). En nuestro caso, los teclados iOS de terceros tienen una limitación en el consumo de RAM: 52 megabytes. Es decir, queremos agregar funciones, crear una interfaz de usuario hermosa, pero estamos limitados a 52 megabytes. Qué hacer con esto no está claro.

Al agregar otra función, esto sucedió. A menudo comenzamos a superar este límite y no sabíamos qué hacer con él. Como resultado, la llamada al sistema de mapas de memoria vino al rescate. Tomamos un archivo con un diccionario, de donde obtenemos todas las pistas, y comenzamos a llamar al mapa de memoria. Por lo tanto, trabajamos con parte del archivo sin cargarlo completamente en la RAM.

El último problema frecuente es la hora de inicio. Aquí puedo aconsejarle que lea lo que sucede antes de que su código comience a funcionar. En particular, sobre la vinculación estática y dinámica.



La última habilidad útil es la integración continua o la automatización de tareas aburridas.

A nadie le gusta hacer tareas aburridas, así que simplemente las automatizamos. En la mayoría de los casos, lo más simple es crear la aplicación para cada confirmación que realice, y cuanto más a menudo cree la aplicación, más rápido podrá encontrar el problema. Si tiene pruebas, ejecútelas también.

Como dije, la publicación está asociada con una pequeña burocracia, por lo que también está muy automatizada, y puede liberar el ensamblaje en la tienda beta para cada solicitud de grupo para que los evaluadores puedan probarlo. También puede automatizar la generación de capturas de pantalla para la App Store, para no hacerlas manualmente.

Para todas las habilidades enumeradas, reuní materiales útiles.eso ayudará en su estudio. También contiene el código fuente para una versión simplificada del Traductor. Gracias por su atención, espero que tenga un poco más claro qué estudiar para comenzar su viaje.

Source: https://habr.com/ru/post/undefined/


All Articles