embedded - sistemas - ¿Qué pueden aprender los ingenieros de firmware de los ingenieros de software?
que es ingenieria en sistemas computacionales (9)
¿Qué pueden aprender los ingenieros de firmware de los ingenieros de software? ¡Mucho!
Estoy sorprendido de cómo se practica el desarrollo de firmware similar hoy en día como hace 25 años, cuando empezamos a usar C para el desarrollo integrado. C fue un gran paso adelante del ensamblador, pero hay muchas más lecciones aprendidas que los ingenieros de firmware pueden y deben aprender. Sí, algunas de las herramientas son mejores, pero muchas prácticas están estancadas en los años 70 y 80.
El desarrollo de software integrado agrega algunos desafíos adicionales a los desafíos que enfrentan los desarrolladores no integrados. Pero todos los principios y prácticas que utilizan los desarrolladores de software capacitados son aplicables al desarrollo integrado. Por cierto: no son solo los desarrolladores de software integrado los que no están al tanto de estas prácticas de vanguardia, sino también muchos desarrolladores de software no incorporado.
Las personas que conozco y que conozco haciendo firmware son, en general, un grupo muy hábil que trabaja para resolver problemas difíciles. Desafortunadamente, por el motivo que sea, muchos no han seguido los desarrollos en el mundo del software. Creo que tiene que ver con una barrera imaginaria erigida por los ingenieros de firmware.
Los desarrolladores integrados y no integrados hablan diferentes idiomas, pero resuelven problemas similares. Mantener el código incorporado independiente de un dispositivo de hardware es esencialmente lo mismo que mantener el código de la aplicación independiente de la IU o la base de datos. Los principios subyacentes son los mismos.
Aquí hay algunas cosas que creo que los desarrolladores integrados deberían prestar más atención. Algunos de estos principios y prácticas pueden usarse de inmediato, mientras que otros pueden necesitar un pequeño ajuste para enfrentar los desafíos incorporados. Si desea sustituir la palabra firmware por software a continuación, adelante, realmente no distingo entre los dos.
Gestión de la dependencia
Las dependencias entre módulos deben ser gestionadas. La dependencia del software al hardware es un caso especial que debe ser administrado activamente por el desarrollador de software incorporado. Si no manejas la dependencia, te manejará a ti.
En la práctica, esto significa que solo un subconjunto limitado de los módulos de software debe tener conocimiento del hardware subyacente (y del sistema operativo). A medida que el hardware evoluciona, y siempre lo hace, se puede preservar la inversión en el código independiente del hardware. Ver mi ah ha! momento.
Robert Martin ha escrito extensamente sobre los principios de diseño SOLID. Los desarrolladores integrados deben conocerlos y aplicarlos a sus diseños.
- Principio de responsabilidad de S-Singled
- Principios cerrados de O-Open
- Principio de sustitución de L-Liskov
- Principio de segregación de interfaz I
- Principio de inversión de dependencia D
Estos principios conducen a diseños que resisten mejor la prueba del tiempo. Los principios SOLID fomentan la creación de módulos cohesivos e independientes. Se basan en ideas orientadas a objetos, pero se pueden aplicar a C. Tenemos que detener la función de llamada de datos de forma gratuita para todos, que es muy común en el código C incrustado.
Lenguajes C ++ y OO
¿Por qué no puedes usar C ++ y OO? Porque son demasiado lentos, o demasiado grandes. ¿Cuáles son los hechos? C ++ es un lenguaje grande y misterioso, pero no tienes que usarlo todo. Echa un vistazo a ¿Por qué sigues usando C?
C ++ compensa algunos de los problemas con los que C no ayuda mucho como:
- Encapsulamiento y ocultamiento de información.
- Programación a interfaces.
- Objetos sustituibles.
- Inicialización ad-hoc
C ++ se puede utilizar de manera efectiva para el desarrollo integrado. Bueno, sí necesitas un compilador de C ++, y el espacio libre. Tal vez eso no sea posible en su mundo, o tal vez sea el costo de hacer negocios. Empieza por aprender:
- Clases: estas son estructuras con funciones miembro así como también datos de miembros.
- Constructores: esto hace posible obtener una inicialización correcta todo el tiempo.
- destructores: si aprendes a los constructores, también debes aprender a los destructores para mantener el universo en equilibrio.
- herencia: utilícela principalmente para definir interfaces que solo contienen funciones virtuales puras. Las interfaces proporcionan importantes descansos de dependencia y puntos de flexibilidad. Estos suelen ser injustamente desanimados en incrustados. No debe haber misterio o prejuicio aquí; Las funciones virtuales son punteros a funciones bajo el capó. La alternativa al uso efectivo de las interfaces es la lógica condicional compleja, algo que los programas C embebidos generalmente tienen demasiado.
Si los desarrolladores incrustados usaran esas partes de C ++, podrían construir un diseño más flexible y no incurrir en un alto costo.
Desarrollo guiado por pruebas
Este podría ser el mayor cambio de juego. Me alegra ver que otras publicaciones también lo mencionan. TDD puede ayudar a prevenir defectos ahora y en el futuro. Para ver por qué TDD puede ayudar a echar un vistazo a The Physics of TDD .
Embedded presenta algunos desafíos únicos para TDD. Por ejemplo, TDD requiere un ciclo de edición / compilación / enlace / ejecución incremental extremadamente rápido. Para muchos desarrolladores integrados, esto significa una administración de dependencia cuidadosa y una prueba unitaria de ejecución primero en el objetivo. Ver más sobre la adaptación de TDD para Embedded .
Con TDD, está creando un código que se ha probado exhaustivamente. La cobertura completa de pruebas automatizadas actúa como una red de seguridad, lo que permite cambiar el código de forma segura a medida que cambian los requisitos. Las consecuencias involuntarias se descubren de inmediato.
Además, tener las pruebas que obtiene casi gratis , le permite refactorizar sin temor su código ...
Refactorización continua
El código se escribe una vez, pero se lee muchas veces. Luego se cambia y se ajusta, lo que lleva a diseños que se degradan con el tiempo. Si los desarrolladores no refactorizan continuamente para mantener el código limpio, se convierte en un desastre. Tal vez algunos de ustedes están lidiando con ese lío. Las pruebas automatizadas de TDD permiten la refactorización de bajo costo y bajo riesgo.
Integración continua
Automatiza tu proceso de construcción. Haga que se ejecute con cada registro de espacio de trabajo. Este es un desafío con los conjuntos de herramientas heterogéneas que a menudo se necesitan para obtener el código compilado en el objetivo, pero sigue siendo el objetivo correcto.
Cuanto antes sepa el desarrollador integrado que un cambio es de alguna manera incompatible con algún otro trabajo, más rápido podrá repararse y menos tiempo se gastará en fusiones dolorosas.
Entrega incremental
Encuentre formas de dividir el trabajo para evitar grandes integraciones dolorosas y probar las ideas de diseño de manera temprana. Evite dividir a lo largo de líneas arquitectónicas, concéntrese en entregar porciones de funcionalidad visible.
Colaboración
Desarrolladores embebidos! Salgan de allí cubos y trabajen juntos. ¿Cómo puedes mejorar cuando solo ves tu propio código? ¿Cómo puedes mejorar cuando eres el experto en tecnología XXX, lo dominas y no tienes la oportunidad de trabajar en diferentes áreas?
Hay mucho que aprender por ahí. ¿Eres responsable de ser todo lo que puedas?
A juzgar por mi conocimiento de la historia de las herramientas de ingeniería de firmware, prácticas, etc., se ha rezagado constantemente en el campo de la ingeniería de software por varios años. Por ejemplo, hasta donde puedo decir, todavía hay una gran cantidad de debate en el mundo del firmware sobre si realmente vale la pena usar C ++ para nuestras aplicaciones, y algunos compiladores de C ++ están notablemente ausentes (¿microchip?!?). Me imagino que, en gran parte, esto se debe a las diferencias en los requisitos entre el firmware y el software. Una vez más, a juzgar por la historia, parece que es solo una cuestión de tiempo antes de que las herramientas y técnicas debidamente revisadas se conviertan en el mundo del firmware.
¿Qué métodos, herramientas, mejores prácticas, etc., que los ingenieros de software modernos utilizan regularmente, podrían los ingenieros de firmware aprovechar también para mejorar su oficio?
Específicamente estoy pensando en los siguientes ejes (pero no dejes que te limiten):
- Mejora de la limpieza / mantenibilidad del código.
- Reducir la introducción de defectos y mejorar la detección.
- Mejora de la documentación.
- Gestión de requerimientos
- Mejora de la reutilización.
También me encantaría ver que las tiendas integradas respondan o comenten las respuestas para proporcionar comentarios sobre la viabilidad teórica o, mejor aún, las experiencias personales.
ACTUALIZAR
Estoy especialmente interesado en saltar un poco por delante de la curva. Por lo tanto, las cosas relativamente nuevas que han sido examinadas razonablemente bien (funciona bien para la mayoría de las personas), como C ++, TDD, etc. ¿Qué usas todo el tiempo y amor?
ACTUALIZACIÓN 2
Recibo muchos buenos consejos generales de programación en las respuestas hasta ahora, lo cual es genial, pero realmente estoy buscando más enfoques poco convencionales que hayan resultado exitosos para las personas. Estoy tratando de sacar a los practicantes de Agile, a los TDD, y al resto de ustedes que han probado cosas y han visto cómo se pagan con creces o fracasan horriblemente. Como ingeniero de software, ¿ha habido una herramienta o práctica que ha adoptado en los últimos años que ha tenido un impacto muy positivo o negativo?
Esto es probablemente un poco fuera de contexto.
Una breve referencia a una columna de firmware en Embedded ,
- Estándares para eliminar errores en la codificación de firmware
- Algunas páginas remiten al artículo, Diez Reglas para matar errores
Siempre he encontrado buenos artículos sobre ingeniería de firmware en Embedded.
Que probablemente muchos interesados en esta pregunta tienen también ...
He trabajado como ingeniero de software integrado y como desarrollador de software. Al estar en ambos mundos, he aprendido que no importa cuán pocos recursos tenga su sistema y qué lenguaje está programando, hay muchas cosas que pueden hacer su vida más fácil.
Lo primero es las herramientas que está utilizando. En el software integrado, usted solo trata con el compilador / enlazador la mayor parte del tiempo. Hay más que estos. Las herramientas de diferencia, las expresiones regulares, el lenguaje de scripting y las herramientas de documentación le ahorran mucho tiempo.
Otra cosa es la calidad del código. Es necesario seguir las convenciones de estilo, pasar por ciclos regulares de refactorización y, en general, tener en cuenta que la lectura del código se realiza con mayor frecuencia que la escritura del código y realmente vale la pena tener un código más legible.
Algunas veces en software embebido perdemos por completo la fase de diseño. Los proyectos incrustados generalmente no son tan grandes como los de escritorio / servidor, pero eso no es excusa para no hacer un diseño adecuado.
El software debe probarse solo y no solo como parte del dispositivo. Realmente se ahorra mucho tiempo para construir un simulador de software de su sistema, solo para probar que el software cumple con las especificaciones requeridas. Es mucho más caro hacerlo cuando todo el hardware y el software están listos.
La ingeniería de firmware es bastante amplia. Desde PIC hasta DSP, todos tienen diferentes grados de recursos físicos. En estos días, los DSP son bastante potentes (comparables con las CPU ~ 5 años de antigüedad), pueden admitir una gran cantidad de memoria, etc. Pero, nuevamente, tiene PICS que operan con varios kilobytes. Más escasos los recursos, el programador tiene que usar ingeniosos hacks para sacar el máximo provecho del dispositivo. Y el enfoque está en ''hacer que funcione'' en lugar de ''escribir código elegante''.
Lo que me gustaría ver son buenas herramientas de gestión de proyectos que incorporan código y documentos, ya que tiene que consultar muchas hojas de datos, documentos de diseño que se encuentran dispersos por la red y en correos electrónicos, etc.
También me gustaría ver mejores herramientas de desarrollo para DSP (TI: entregar CCS a alguien que sea bueno para hacer IDE) y más creadores de bibliotecas que usan C ++ (te estoy mirando ATEME) para crear mejores bibliotecas.
Y también los ingenieros de hardware deben tener una mejor apreciación de la Orientación al Objeto en lugar de dejar escapar, "si es C ++ va a ser lento".
No estoy seguro de qué grado de software se considera firmware (BIOS, controlador o utilidades), pero la queja estándar que escucho es que la interfaz de usuario no es estándar. Darse cuenta de que la IU es importante y que debería seguir algunos estándares o tradiciones sería algo bueno.
En lo que se refiere a C ++, es comprensible que vacilen en hacerlo porque hay muchos gastos generales en comparación con C. C es casi como un lenguaje ensamblador con libc, mientras que en C ++ incluso una simple función puede ser virtual. Implementar el tiempo de ejecución completo de C ++ no puede ser tan fácil dada la complejidad del lenguaje.
Hay demasiadas cosas para enumerar en términos de "mejores prácticas" de desarrollo de software (odio esas palabras). ¿Por qué no comenzar con la prueba de Joel: 12 pasos para mejorar el código?
La prueba de joel
- ¿Utilizas control de código fuente?
- ¿Se puede hacer una acumulación en un solo paso?
- Haces contrucciones todos los dias.
- ¿Tienes una base de datos de errores?
- ¿Tú arreglas los errores antes de escribir un nuevo código?
- ¿Tienes un horario actualizado?
- ¿Tienes alguna especificación?
- ¿Los programadores tienen condiciones de trabajo silenciosas?
- Utilizas las mejores herramientas que el dinero puede comprar?
- ¿Tienes probadores?
- ¿Los nuevos candidatos escriben código durante su entrevista?
- ¿Haces pruebas de usabilidad en el pasillo?
Permítanme primero abordar un supuesto en su pregunta. El supuesto es que los ingenieros de software integrado (ESE) no conocen o no conocen las prácticas modernas de ingeniería de software y necesitan aprender nuevas prácticas. Este supuesto debe ser eliminado de inmediato. Creo que encontraría la misma distribución estadística de ESE que mantienen sus habilidades y técnicas actualizadas como SE no incrustadas.
Entonces, tal vez tu pregunta se convierta en una serie de preguntas como:
- ¿Por qué los ESE utilizan un editor de código separado y un compilador de línea de comandos y no un IDE?
- ¿Por qué se prefiere C sobre C ++ en la mayoría de los proyectos integrados?
- ¿Por qué no hay tanta experimentación en las prácticas de programación en el mundo integrado?
Los siguientes párrafos responden a estas preguntas.
Los ESE suelen utilizar un editor de código específico porque es una preferencia personal o es lo que utiliza su empresa. Los IDE no son tan comunes porque los ESE trabajan muy de cerca con el silicio y no todos los fabricantes de chips desarrollan un IDE para su línea de chips. Solo los chips que logran la mayor penetración en el mercado, como ARM, tienen el impulso suficiente para garantizar el desarrollo de herramientas basadas en IDE. Además, un IDE no proporciona tanta asistencia al ESE como a un desarrollador de escritorio, por ejemplo. Los IDE proporcionan ayuda para hacer el pegamento a la GUI o la finalización de código para API grandes; ninguno de los cuales se encuentra comúnmente o es tan estándar como en el mundo integrado.
Estoy seguro de que hay mejores informes sobre por qué se prefiere C en lugar de C ++ en los sistemas integrados que los que puedo inventar en el momento. Lo mínimo es que usas lo que funciona. C funciona y es más común (más programadores saben C que C ++). La otra razón podría ser que la metodología OO se diseñó para ayudar a los programadores a resolver grandes problemas al abstraer la solución en objetos conceptuales manejables. En el mundo integrado, los problemas generalmente se reducen a un problema (y solución) lo más pequeño posible, de modo que el sistema integrado se vuelve más confiable al tener una base de código más pequeña.
Los ESE experimentan menos porque un producto incorporado, en general, debe ser mucho menos propenso a errores y tener mayor confiabilidad que un programa de escritorio. Esto significa una aplicación rígida de prácticas probadas y más tiempo dedicado a las pruebas. ¿Por qué? Porque a menudo no hay una ruta viable para actualizar el firmware de un dispositivo integrado; O bien es imposible debido a que el sistema se implementó más allá del alcance o inverosímil debido al costo de actualizar millones de dispositivos.
En conclusión, las ESE utilizan las herramientas y prácticas que mejor se adaptan a sus necesidades, al igual que las SE no integradas. Como ESE practicante, creo que la disciplina del software incorporado es mucho más diferente de lo que mis amigos que no son de ESE creen. Por lo tanto, la aparente disparidad de las prácticas de programación no es una cuestión de que las ESE necesiten aprender prácticas modernas, sino que las que no son ESE tienen que entender qué tan diferente es la programación integrada.
Suponiendo que los "ingenieros de firmware" se refieran a "ingenieros de software integrado", entonces mi respuesta sería: son ingenieros de software, por lo que deberían, donde sea posible, estar haciendo las mismas cosas que cualquier otro ingeniero de software.
Obviamente, el software de escritura para sistemas integrados requiere algunas habilidades diferentes, como un conocimiento detallado del procesador de destino y la capacidad de manejar recursos limitados (en comparación con una PC o similar).
Como han mencionado otros, las pruebas unitarias se complican por el hecho de que esto debe hacerse en un simulador que se ejecuta en una PC, lo que, aunque es muy útil, nunca puede ser un sustituto de las pruebas completas del sistema real, especialmente dada la naturaleza asíncrona. de eventos a los que está sujeto un sistema embebido.
Una de mis preocupaciones en cuanto a por qué el software integrado parece estar "detrás de la curva" es porque la ingeniería de software, y como parte de eso, el software integrado, generalmente no se enseña en profundidad en los títulos de ingeniería electrónica. Dado que la carrera de un ingeniero electrónico es probable que se dedique a la codificación en la actualidad, esto parece ser un descuido masivo.
Afortunadamente, hay quienes están tratando de compensar esto. Recomiendo encarecidamente leer los artículos de Jack Ganssle (en su sitio web y en su columna habitual en embedded.com ).
Además, MISRA-C se creó hace un tiempo para tratar de evitar las fuentes comunes de errores en el software C para la industria automotriz, y desde entonces ha sido adoptado por muchos en el mundo del software integrado. Agregue un verificador de análisis estático como PC-Lint , y ya ha mejorado su código.
Los proveedores de herramientas tampoco han ayudado, en muchos casos al crear sus propios IDE, cuando quizás hubiera sido mejor concentrarse en el compilador y el depurador, y dejar el IDE a otros, por ejemplo, Eclipse.
Por cierto, para más información sobre la no utilización de C ++ en sistemas integrados, consulte esta pregunta .
Finalmente: como los ingenieros de firmware son ingenieros de software, enfrentamos muchos de los mismos problemas, desafíos y preocupaciones, por lo que deberíamos usar los mismos recursos; después de todo, hay muchos de ellos alrededor, ¡y estás leyendo uno de ellos!
Algunos de los otros sitios web que frecuento incluyen:
- blog y podcast
- El diario WTF
- Hablar de calidad
- Codificación del horror
- Secreto geek
- Joel en software
- Un diferente blog de desbordamiento de pila ; Este es uno dedicado a sistemas embebidos.
EDITAR: En respuesta al comentario de Gabe, "¿qué herramientas deberíamos estar buscando para adaptarnos?", Un par de ejemplos vienen a la mente:
IDEs independientes del compilador: hay muchos IDE para C, pero por lo que puedo decir, pocos de ellos pueden ser utilizados en su potencial sin un compilador compatible. Me gustaría ver a los desarrolladores del compilador y los desarrolladores de IDE converger, de modo que, idealmente, cualquier compilador se pueda usar con cualquier IDE.
En ausencia de un compilador compatible, me gustaría poder usar PC-Lint (o equivalente) como mi compilador "oficial" con un IDE de mi elección.
Simulación y modelado: las herramientas de simulación como Simulink permiten simular, modelar y probar software para PC y algunos procesadores integrados de gama alta. Herramientas como esta serían igual de útiles para los chips más pequeños, por lo que sería bueno verlos extendidos a esa área del mercado.
PD: la columna de Jack Ganssle de esta semana se titula " ¿Qué hace diferente a la incrustación? ", Y así se relaciona (libremente) con la pregunta anterior.
Pruebas automatizadas
No escanee visualmente las salidas de simulación para verificar si todo está bien. Necesita una prueba automatizada completa porque siempre va a perder algo en esa masa de formas de onda.
Control de versiones
No vas a recordar cuál era la versión de trabajo. Use el software de control de versiones para que sepa con qué programar esa placa.
Seguimiento de errores
Te vas a olvidar tarde o temprano. Un registro de errores debe contener la versión (ver Control de versión) en la que se detectó el problema por primera vez y la versión en la que se solucionó.
Vaya , pensé que te referías a firmware como en FPGA, pero lo mismo es cierto para el software integrado. Si ya tiene estos procesos implementados, olvídese de los unconventional approaches
hasta obtener los conceptos básicos correctos.
- Fuente de control
- Pruebas unitarias (TDD)
- Integración continua (o construcciones nocturnas)
- Seguimiento de errores
Los ingenieros de firmware con los que he trabajado no hacen nada de esto.
Las pruebas unitarias pueden no aplicarse muy a todos los tipos de firmware. Imagino que es más difícil hacer una prueba de unidad cuando se ejecuta en hardware físico. Depende si tienes emuladores disponibles supongo.