¡SDK para ti, SDK para mí, SDK para todos! Cómo hacer un SDK y por qué es necesario


Hola a todos!


Nuestra empresa ofrece un servicio para almacenar y procesar datos de dispositivos industriales (bombas, taladros y otros equipos industriales). Almacenamos los datos de nuestros clientes y brindamos funcionalidad para su análisis: creación de informes, gráficos y mucho más.


Y en el curso del trabajo, notamos que la integración de cada nuevo cliente se retrasa enormemente, y la cantidad de varios errores aumenta constantemente. Entonces quedó claro que era hora de lidiar con esto. Como lo mostró un análisis de la situación, el departamento de TI de cada uno de nuestros clientes desarrolló su propia solución para recopilar datos localmente desde dispositivos y enviarlos a nuestro servicio. Esto complica el hecho de que, teniendo en cuenta las características específicas de la industria, no siempre hay acceso a Internet y es necesario almacenar datos localmente y enviarlos lo antes posible. Y hay un número suficientemente grande de tales matices, lo que conduce a un aumento en el número de errores.


Y luego nos dimos cuenta de que la mejor solución en esta situación sería desarrollar un SDK y proporcionarlo al cliente. Inmediatamente comencé a buscar mejores prácticas y debates sobre el desarrollo del SDK y me sorprendió mucho: prácticamente no hay nada al respecto en RuNet, pero hay muy poca información en Internet Basurmani y está dispersa. Bueno, la tarea es clara, pensada e implementada.


Pero fue la falta de información sobre este tema lo que creó el deseo de contarle a la comunidad sobre los pensamientos, las decisiones tomadas y las conclusiones sobre el desarrollo del SDK. Este artículo analiza una solución para .NET, pero es un concepto, por lo que será interesante para muchos. Detalles debajo del corte!


Es hora de ser determinado


Comencemos definiendo qué es el SDK y por qué podría ser necesario.


SDK (del kit de desarrollo de software en inglés) es un conjunto de herramientas de desarrollo que permite a los especialistas en software crear aplicaciones para un paquete de software específico, software de desarrollo básico, plataforma de hardware, sistema informático, consolas de juegos, sistemas operativos y otras plataformas. El SDK aprovecha cada plataforma y reduce el tiempo de integración.
...
Un ingeniero de software generalmente recibe un SDK del desarrollador del sistema de destino.

Bueno, eso es lógico. En palabras simples, el SDK es un paquete de bibliotecas, por lo que el cliente puede comenzar a trabajar de manera fácil y rápida con su sistema (en este artículo hablaremos sobre nuestro servicio, pero todo lo descrito en el artículo se aplica a otros tipos de SDK) o realizar las mismas acciones.


Pero, como cualquier enfoque, la ruta SDK tiene ventajas y desventajas.


Los beneficios


Integración de alta velocidad de un nuevo cliente : sus clientes necesitan escribir menos código.


Reutilización de código : el mismo código se usa en varios lugares a la vez. Podemos decir que esto es una duplicación del párrafo anterior, pero estamos hablando del hecho de que la lógica del trabajo es solitaria en todas partes, lo que implica


Previsibilidad del comportamiento : el uso de las mismas bibliotecas lleva el comportamiento de los sistemas a un determinado estándar, lo que facilita en gran medida la búsqueda y eliminación de errores y vulnerabilidades.


La calidad del código es donde a muchas personas les gusta ahorrar en las pruebas (perdón por el presupuesto, los plazos y otras razones). Está claro que en el mundo real probar todas las secciones del proyecto con pruebas es una tarea muy laboriosa. Pero probar cualitativamente todos los módulos SDK y luego usarlos es una forma de aumentar el porcentaje de cobertura de prueba, lo que conducirá a una reducción en el número de errores.


La documentación es el mismo escenario que con las pruebas. Documentar todo el proyecto es bastante problemático. La reutilización de los SDK aumenta el porcentaje de cobertura de documentación, lo que reduce el umbral para que los nuevos empleados ingresen al proyecto y, en general, ayuda en la vida.


De hecho, todas las ventajas son las consecuencias de lo más importante: escribimos el código de muy alta calidad una vez y luego lo reutilizamos .


Desventajas


Los requisitos de alta calidad del código SDK son el resultado de la principal ventaja. Un error en el SDK generará errores en todos los sistemas que lo usan.


Establecer restricciones : el SDK es un conjunto de bibliotecas para implementar scripts estándar . A veces, los desarrolladores de SDK creen que, además de implementar uno de los escenarios proporcionados, el cliente no necesita nada, que es más fácil para el cliente hacer todo desde cero por sí mismo que construir un pedestal con muletas para el SDK.


Infierno de dependencia y actualizaciones : al expandir la funcionalidad (por ejemplo, personalizar una solución para un cliente específico), lanzará una nueva versión de la biblioteca. Pero hay dependencias, diferentes conjuntos de versiones de biblioteca para diferentes clientes, y debe supervisar cuidadosamente la compatibilidad con versiones anteriores o las versiones estrictas.


Cuando realmente se necesita el SDK


Tiene varios escenarios estándar que se implementan nuevamente de vez en cuando , de hecho, nuestro caso.


Desarrollo interno : en diferentes proyectos, ¿utiliza sistemas de registro, configuraciones de sistema, trabajo con HttpRequest, bases de datos, archivos? Cree un SDK interno : un conjunto de bibliotecas para uso interno. Puede ampliar la funcionalidad del SDK en cualquier momento, pero la velocidad de desarrollo de nuevos proyectos, el porcentaje de cobertura con pruebas y documentación aumentará, y el umbral para que ingresen nuevos desarrolladores disminuirá.


Cuando es probable que el SDK sea redundante


Los escenarios de uso no están definidos o cambian constantemente : deje la implementación de soluciones personalizadas a los clientes y ayúdelos. No es necesario hacer un prodigio de wunderwaffle, que solo interferirá. Muy relevante para empresas jóvenes y startups.


No sabes cómo hacerlo cualitativamente . Tengo malas noticias para ti: es hora de aprender. Pero dar una decisión torcida a un cliente está muy, muy mal. Los clientes deben ser respetados, después de todo.


Entonces, decidimos qué es el SDK, con sus ventajas y desventajas, y cuándo lo necesitamos. Si después de eso se dio cuenta de que el SDK es realmente necesario, lo invito a embarcarse en el "camino del SDK" y descubrir qué debería ser y cómo demonios hacerlo.


"¿Amas a Lego?" - Modularidad


Imagine todos los escenarios posibles para usar el SDK (ya ha decidido por qué lo necesita, ¿verdad?) Y cree un script para la biblioteca. ¿Qué no es una opción? Pero este es un mal enfoque, por lo que no lo haremos. Y seremos así:


  • romper todos los guiones en pasos
  • identificar pasos comunes
  • construir una lista de módulos que implementen todos los pasos posibles (un módulo es responsable de implementar algo específico, por ejemplo, trabajar con configuraciones)

Por ejemplo, teniendo en cuenta los detalles de la tarea, necesitamos que toda la lógica se establezca desde las configuraciones. Implementamos el módulo para trabajar con configuraciones (leer, escribir, actualizar, validar y procesar configuraciones) y lo usaremos en todos los demás módulos.


Y para la implementación de escenarios estándar, realmente crearemos módulos, algún tipo de módulos de "control", cada uno de los cuales implementa un escenario específico utilizando otros módulos del mismo SDK. Por lo tanto, para la implementación de escenarios estándar, el cliente solo necesita conectar el módulo de control del script (y extraerá todas las dependencias), y para la implementación de los no estándar, usamos los módulos base, también reutilizando el código.


Esta es precisamente la razón por la cual el SDK no debe ser una biblioteca (aunque realmente lo quiero, lo entiendo. Después de todo, cuando todo el SDK está en una biblioteca, puede olvidarse de las dependencias y todo lo que está conectado con ellas), sino ser un conjunto de bibliotecas. Una ventaja adicional de este enfoque será la reducción del "peso" del programa del cliente: extraerá un SDK pesado y solo extraerá los módulos necesarios.


Pero de todos modos no debe producir módulos, porque cuantos más módulos, más dolor de cabeza de sus dependencias! Es decir Es importante dividir correctamente la lógica en módulos, manteniendo un equilibrio entre la decisión "todo en uno" y "cada módulo tiene su propio módulo".


"¿Y entonces fue posible?" - versatilidad


Proporcione al cliente varias interfaces para trabajar con su biblioteca. Daré un ejemplo:


public void LoadConfiguration(string filename); public async Task LoadConfigurationAsync(string filename); 

Si solo proporciona la versión síncrona, cuando implemente una aplicación asíncrona, el cliente se verá obligado a hacer envoltorios asincrónicos de su método síncrono. Si solo proporciona la versión asincrónica, la situación es similar. Dale al cliente ambos y él te lo agradecerá.


Los genéricos serán una buena ventaja. Por ejemplo, tenemos una clase para trabajar con configuraciones que implementa métodos para empaquetar una configuración en una cadena, cargar una configuración desde un archivo, etc. La configuración de un módulo específico se heredará de nuestra clase base, pero para trabajar con la nueva clase también debemos proporcionar métodos de desempaquetado.


 class BaseConfiguration{ public BaseConfiguration FromString(string source){...} public BaseConfiguration FromString(string source,Type configurationType){...} public T FromString<T>(string source) where T:BaseConfiguration } class CustomConfiguration : BaseConfiguration{} 

Por lo tanto, hemos proporcionado al cliente tres implementaciones que puede usar. Los genéricos son muy convenientes, pero cuando se trabaja con tipos dinámicos, solo se pueden llamar a través de la reflexión, lo que no es rentable. El principio general de universalidad, espero, es claro.


"Padre 1, Padre 2, Hijos []" - Nombramiento


¿Cuál es la parte más difícil en un programador? Inventar nombres para variables.

Sin embargo ... La asignación adecuada de nombres de módulos, clases, propiedades y métodos será de gran ayuda para aquellos que trabajarán con su SDK. Ejemplo que no requiere comentarios:


Ejemplo de Kinect 2.0 SDK


 var skeletons = new Skeleton[0]; using (var skeletonFrame = e.OpenSkeletonFrame()) { if (skeletonFrame != null) { skeletons = new Skeleton[skeletonFrame.SkeletonArrayLength]; skeletonFrame.CopySkeletonDataTo(skeletons); } } if (skeletons.Length == 0) { return; } var skel = skeletons.FirstOrDefault(x => x.TrackingState == SkeletonTrackingState.Tracked); if (skel == null) { return; } var rightHand = skel.Joints[JointType.WristRight]; XValueRight.Text = rightHand.Position.X.ToString(CultureInfo.InvariantCulture); YValueRight.Text = rightHand.Position.Y.ToString(CultureInfo.InvariantCulture); ZValueRight.Text = rightHand.Position.Z.ToString(CultureInfo.InvariantCulture); 

Todo está claro a partir de los nombres de clases y métodos. Y si se completa el código en su IDE, a menudo es posible no consultar la documentación si todo está claro.


"Estoy seguro de que si la Muerte supiera lo que es la burocracia, la gente nunca moriría, siempre parando en la fila ..." - Documentación


Pero incluso si todos los módulos, clases, métodos y propiedades tienen nombres muy hermosos y urgentes, aún necesita escribir documentación. En primer lugar, le ahorrará mucho los nervios (el número de preguntas de los clientes se reduce en un orden de magnitud. Todo está en la documentación), y en segundo lugar, siempre está claro por qué hizo esto y no de otra manera.


La documentación en el SDK suele ser simple y concisa. Por lo general, se divide en dos partes: Tutorial, un curso paso a paso al estilo de "Construir una ciudad en 10 minutos" y la sección Referencia, una referencia a todo lo que se puede hacer con este SDK.

Elegimos la forma más fácil: resumen + artículos. Agregamos atributos Xml para métodos y clases que brillan en intellisense como información sobre herramientas. Con Docfx, creamos documentación sobre estos atributos y obtenemos documentación detallada y conveniente, que se complementa con artículos que describen casos de uso y ejemplos.


"- ¡Para mantenerlo limpio! - ¿Cómo lo limpiaré con un tenedor?" - Pruebas


¿Qué se puede decir acerca de las pruebas como parte de la discusión del SDK ... Debe tener! La mejor solución sería TDD (a pesar de que tengo una actitud negativa hacia este enfoque, en este caso decidí usarlo). Si mucho tiempo Si aburrido Pero en el futuro no se ahorcará de las constantes caídas del SDK y las consecuencias de esta caída.


El jugo principal de la situación es que al darle el SDK al cliente, pierde el control: no puede solucionar el error rápidamente, es difícil encontrar este error y se verá lo suficientemente estúpido en tal situación. Por lo tanto, prueba. Prueba mejor. Y una vez mas. Y por si acaso, prueba tus pruebas. Y pruebas de prueba. Entonces, algo que me dejé llevar, pero la importancia de probar el SDK, espero, es clara.


"Una víctima que no pudo resistir su pasado fue consumida por él" - Logi


Dado que le da el SDK a una empresa de terceros, como resultado de lo cual pierde el control sobre la situación, en caso de error (en la etapa de prueba, todos decidieron "funcionará", ¿no?), Un proceso bastante largo y doloroso está esperando que busque este mismo error. Aquí es donde los registros vienen en tu ayuda.


Registre todo , absolutamente todo, y si ocurre un error, solicite registros a su cliente. De esta forma, ahorrará mucho tiempo y no podrá frotarse la cara frente al cliente.


"¡Alarma! ¡Achtung! ¡Atención!" - Errores



Mientras pensaba mucho en los errores, llegué a una conclusión interesante: ni un solo método en su SDK debería dar un error que no se describe en la documentación . Debe admitir que es muy desagradable cuando conecta una biblioteca de terceros para trabajar con HttpRequest, y arroja un poco de NullPointerException y StackTrace sobre usted, lo que lo lleva a las entrañas de la biblioteca. Y tienes que sumergirte en estos mismos "intestinos", tratando de entender qué tan profunda es la madriguera del conejo y cuál es el problema.


Por lo tanto, propongo la siguiente solución: declarar una lista cerrada de posibles excepciones y documentarlas. Pero porque no puede estar seguro de haber proporcionado todo, envolver el método en un try-catch y el error detectado en el declarado. Por ejemplo, una ConfigurationException que contendrá una InnerException es un error detectado. Esto permitirá que un desarrollador externo detecte todos los errores posibles, pero si sucede algo, descubra rápidamente cuál es el problema.


Versiones o "cómo no morderte la cola"


Para evitar futuros problemas, recomiendo usar versiones estrictas. Elija el sistema de versiones que más le convenga y úselo. Pero si la nueva versión de la biblioteca no tiene compatibilidad con versiones anteriores, esto debe indicarse. Cómo resolverlo, piensas. Pero definitivamente deberías pensarlo.


"Un tren que podría" - Implementar


La necesidad de relevancia de la documentación y las versiones da lugar al requisito de la corrección de la implementación. En nuestra decisión, usamos la siguiente solución (muletas, pero funcionan).
Cuando es necesario lanzar una nueva versión, el desarrollador tira el bat'nik con el número de versión y luego el archivo por lotes:


  • lanzamiento de compilación
  • pone todas las bibliotecas en el archivo
  • construir la última versión de la documentación (docfx)
  • indica la versión de lanzamiento en la documentación y en el nombre del archivo
  • pone todo lo más fresco en el repositorio de git
  • WebApp en MS Azure obtiene una nueva confirmación de enlace de git y publica cambios

En la salida, obtenemos una versión actualizada del sitio con documentación, desde donde puede descargar el archivo con la última versión del SDK.
Los planes futuros incluyen empacar todo en paquetes Nuget y publicarlo en el repositorio local de Nuget.


Recomiendo prestar atención a este punto, ya que puede reducir significativamente la cantidad de dolor de cabeza causado por la falta de información relevante sobre la nueva versión de la biblioteca.


"-Y para que puedas? - Mierda. ¡Mira cómo debería!" - Ejemplos y kit de herramientas


Un punto importante en la documentación son los ejemplos de uso. Pero además de esto, a menudo se requiere proporcionar no una biblioteca, sino una aplicación que implemente los escenarios más estándar. Recomiendo hacer estas aplicaciones con un código fuente abierto y bien comentado, que le permitirá matar dos pájaros de un tiro: proporcione una aplicación que funcione y brinde un ejemplo del uso del SDK.


Conclusión


El desarrollo de SDK se ha convertido en una nueva tarea interesante para mí, que ha planteado muchos problemas arquitectónicos importantes. Muchas de las cosas descritas en el artículo son obvias (para mí), pero considero importante anunciar incluso las cosas obvias para obtener una imagen clara.


PS


Gracias por leer, estaré encantado de sus comentarios. Espero que este artículo te sea útil.

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


All Articles