¿Cómo dar a conocer la programación genérica entre los miembros del equipo?

20

Me estoy quedando en un ambiente donde la gente cree:

  1. Los genéricos de Java son la característica utilizada exclusivamente para la escritura de bibliotecas y no para la codificación real.
  2. C ++ es un lenguaje de programación OO; templatees una característica opcional y evitable

Sin embargo, estas personas dependen en gran medida de las bibliotecas escritas utilizando programación genérica (por ejemplo, STL, contenedores Java). Si escribo un código usando templates o generics, es muy probable que el revisor de código lo rechace y haga comentarios para escribirlo de una manera "adecuada / comprensible / elegante" .

Dicha mentalidad es aplicable desde el programador normal hasta el gerente superior. No hay salida, porque el 90% del tiempo, estas personas ejercen presión.

¿Cuál es la mejor manera ( sin que se les corte la garganta ) de explicarlos, el enfoque práctico de escribir código que constituye OO y la programación genérica al mismo tiempo?

iammilind
fuente
11
Te deseo la mejor de las suertes, pero probablemente tengas que irte si quieres a tu manera ...
The Muffin Man
3
@TheMuffinMan, tienes razón. Dejé ese lugar de trabajo y ahora tengo mi propia compañía. ¡Aquí tengo control total sobre la codificación!
iammilind

Respuestas:

14

Todavía hay personas en el mundo que no usan genéricos jave en la "codificación ordinaria". Puedo creerlo con plantillas C ++, pero ¿genéricos? Ni siquiera son difíciles de aprender / usar. En serio, las mejores características de Java y C ++ son genéricos y plantillas respectivamente.

La mejor manera de convencer a la gente de las cosas es hacer un argumento convincente, no ser amenazante y tener razón.

Mientras no esté haciendo algo como usar plantillas como su lenguaje de programación, el polimorfismo paramétrico (genéricos / plantillas) es casi seguro bueno.

1. Evita la duplicación de código.

Esto es obvio, pero el código polimórfico es un código general. Por eso se llama genéricos.

2. Soporta una mejor comprobación estática.

Sin polimorfismo paramétrico que terminan escribiendo cosas como public Object clone()o public boolean equals(object b)que no son sólo abominaciones, tienen tipos que proporcionan ninguna información sobre lo que hacen, e invariablemente terminan lanzar excepciones por todo el lugar. La alternativa al polimorfismo paramétrico son los moldes por todo el lugar.

3. El código OOP de polimorfismo no paramétrico es básicamente incapaz de manejar los "métodos binarios" de manera correcta.

Usas estos a menudo.

4. Es la mejor práctica.

En Java, el uso de genéricos se considera la mejor práctica (ver Java efectivo por Josh Bloch). Los principales pensadores de C ++ como Sutter y Alexandrescu también fomentan el uso de plantillas para resolver una variedad de problemas.

5. Se ajusta al paradigma OO.

La gente a menudo no se da cuenta de esto, pero la combinación de subtipado y genéricos produce un sistema MUCHO más potente, expresivo y orientado a objetos que cualquier sistema con solo uno de ellos.

Considere los mixins de Scala. Esta es una buena característica que le permite juntar sus objetos de las partes componentes. Los genéricos y las plantillas pueden simular algunos de estos beneficios. Por ejemplo, supongamos que uno de sus objetos usa una base de datos. Un buen diseño le permitirá resumir el acceso a la base de datos en una clase separada. Si se hace correctamente, esto no solo le permite burlarse de su almacén de datos (clave para la capacidad de prueba) sino que también puede agregar implementaciones alternativas como esa nueva base de datos no-sql. Sin embargo, aquí podría tener un problema, independientemente de la implementación que use obtendrá diferentes capacidades de su objeto comercial.

Genéricos al rescate!

   public class Business<S extends Datastore>{
      private S store; ...
   }

Ahora puede comenzar a diferenciar estáticamente sus Businessobjetos en función de la capacidad de usar características específicas de la base de datos. Todavía necesita algunas comprobaciones de tiempo de ejecución y conversión, pero puede comenzar a construir MUCHO mejor código.

y

6. El código normal no existe.

Solo hay tres cosas en el universo de programación:

  1. bibliotecas
  2. configuraciones, y
  3. código malo

Si no piensa en su código como si fuera una biblioteca, se encuentra en serios problemas cuando cambian los requisitos para su proyecto. La arquitectura es (posiblemente) el arte de diseñar buenas API.

Esta actitud me parece deslumbrante. Después de acostumbrarse a la programación con tipos parametrizados, no usarlos simplemente hace que todo sea un dolor. Y, Java y C ++ tienen un montón de puntos difíciles que ayudan a remediar.

Philip JF
fuente
77
Me gusta la idea de que normal codeno existe y que sólo hay tres tipos: libraries, configurationsy bad code. Es un razonamiento idealista, aunque todavía tiene que explicárselo a sus colegas, que quizás no sean tan idealistas como usted. Sin embargo, estoy de acuerdo en que usar tipos parametrizados es simplemente increíble una vez que lo dominas.
Spoike
3
Diablos, incluso las plantillas de C ++ no son tan difíciles de usar si no las usas para propósitos de metaprogramación de plantillas. :-)
En silico
-1 por sugerir que todos los que deciden no usar genéricos lo hacen simplemente porque no saben cómo funciona la función.
tp1
dado el potencial de mal uso, diría que restringir / no usar genéricos / plantillas puede ser una decisión mucho mejor por la que le da crédito.
Ryathal
Las personas que se niegan a usar genéricos / plantillas para la ingeniería de software a gran escala construirán accidental e inevitablemente un "segundo idioma": un intérprete que se ejecuta en Java, que implementa cualquier "lenguaje comercial" que tengan en mente. en.wikipedia.org/wiki/Inner-platform_effect
rwong
16

Esta es una forma especializada de la pregunta más general "¿cómo convencer a sus superiores para que comiencen a utilizar una tecnología / forma de hacer cosas más nueva y mejor?

Desafortunadamente, no creo que puedas, y no estoy seguro de que debas hacerlo. Es, por definición, su elección, ya que le están pagando para que haga las cosas de la manera que han elegido, no de la manera que desee. Lo mejor que puede hacer es sugerir que esta tecnología está disponible, que mucha gente la está utilizando y que parece ser el camino hacia el futuro. Es posible que incluso desee mencionar el hecho que, por supuesto, ya deberían saber: que es mejor que las personas no dejen que su conjunto de habilidades se estanque. Pero eso es todo: si no lo compran, no hay nada que puedas hacer.

Pueden tener otras consideraciones que usted no tiene, porque no está pensando a su nivel. Estás pensando como ingeniero, pueden estar pensando más en términos comerciales o incluso en términos de recursos humanos.

  • ¿Los genéricos (o lo que sea) mejorarán el valor de su producto? Probablemente no.

  • ¿Los genéricos (o lo que sea) harán más difícil para las personas que ya han contratado para hacer su trabajo? Sí.

  • ¿Los genéricos mejorarán el tiempo de comercialización? Si el único ingeniero fuiste tú, tal vez. Pero si un grupo completo de ingenieros necesita ser educado en genéricos antes de que se escriba otra línea de código en la casa, No.

Por lo tanto, es posible que desee considerar simplemente cambiar de trabajo. En mi último trabajo fui el primero en usar genéricos con Java, y afortunadamente no tuvieron ningún problema; Expresaron su preocupación porque los genéricos hacen que el código sea "más difícil de leer", pero me dejaron salirse con la mía. Encuentra un trabajo así.

Mike Nakis
fuente
9

Transmitiría los méritos de los genéricos al revisor de código y a otros colegas antes de cualquier revisión:

1) Al permitirle especificar tipos sobre los que actúa una clase o método genérico, la función genérica desplaza la carga de seguridad de tipo de usted al compilador. No es necesario escribir código para probar el tipo de datos correcto porque se aplica en tiempo de compilación. La necesidad de conversión de tipos y la posibilidad de errores en tiempo de ejecución se reducen.

2) Los genéricos proporcionan seguridad de tipo sin la sobrecarga de múltiples implementaciones.

Entonces, [1] y [2] reducen el riesgo de error en el código. Esto ahorra tiempo al desarrollador y, por lo tanto, dinero a la empresa.

Si la legibilidad es un problema, la incomodidad de usar tipos genéricos podría verse comprometida. Esta es una razón por la que es posible que desee ampliar las pautas de codificación. Esto se puede hacer en un contexto de jornada laboral y no solo para ampliar las bibliotecas (sin embargo, es una idea refactorizar a medida que avanza y marcar posibles métodos candidatos para bibliotecas en el código para un fácil reconocimiento más adelante). Por lo tanto, no habría razón para no usarlos en un contexto laboral.

Añadiría algunas declaraciones sobre cómo otros programadores no tienen problemas con los genéricos: los genéricos se usan ampliamente en Java y en muchos otros lenguajes como C #. Cualquier programador serio encontraría la vida difícil sin ese tipo de bloques de construcción seguros.

Sin embargo, es posible que desee considerar que algunos de los desarrolladores pueden no estar a la altura. La gerencia podría haber tomado una decisión consciente para proteger proyectos en el pasado, manteniendo así a estos grupos fuera de las áreas peligrosas. Aquí, tanto los inocentes como los culpables suelen ser los culpables, ya que raramente se realizan análisis o microgestiones suficientes.

Si presenta un buen caso y no recibe una respuesta razonada a cambio, comience a buscar en secreto otra compañía que tome en serio la programación.

CarneyCode
fuente
7

A menos que sea el arquitecto / líder tecnológico, será difícil exigir que use genéricos / plantillas. Realmente debería proponer la solución genérica / plantilla mucho antes de la revisión del código, preferiblemente antes de comenzar a implementarla.

Lo que puede hacer es demostrar por qué debería usar un genérico en algún caso. Si puede demostrar los beneficios, entonces sus colegas podrían estar de acuerdo. Las posibles razones por las que debería usar genéricos / plantillas deberían ser las siguientes:

  • Debería permitirte escribir menos código para tareas repetitivas
  • Facilita el trabajo de los programadores
  • Aplica un patrón establecido por el arquitecto de la solución.
  • Encapsula características comunes, que obligarían a los programadores a no copiar y pegar código (es decir, evitar el doble problema de mantenimiento)
  • Es razonablemente futuro prueba su código (aunque esta vía es difícil de razonar)

En un proyecto Java reciente agregué con éxito una clase abstracta genérica porque satisfizo algunas cosas básicas: facilitó las cosas para los demás en el equipo, impuso el patrón que el arquitecto ya propuso y tenía un código común que los programadores no necesitaban copiar y pegar. Era un patrón simple que el arquitecto escribió sobre que las personas razonablemente competentes todavía se equivocaban (debido a la complejidad del sistema real en juego), pero los genéricos marcan a qué clase va.

Obviamente no puedo mostrar el ejemplo real sin violar el acuerdo de confidencialidad. Pero como ejemplo de lo que hice sería hacer el patrón de estrategia y aplicarlo con genéricos. Entonces este es el patrón de estrategia:

ingrese la descripción de la imagen aquí

Y para que los programadores apliquen este patrón, puede agregar el tipo genérico en el Contextque debe usar algo que tenga un Strategytipo. En cuanto al código, se vería algo así en Java:

// declare the generic Context class that has a type "S" 
// that is an upper bound class of Strategy
public class Context <S extends Strategy> {
    S strategy;

    // Constructor with an initial strategy
    public Context(S initialStrategy) {
        this.strategy = initialStrategy;
    }

    public void doSomething() {
      strategy.execute(); // assumes that Strategy has an execute() method.
    }

    public void setStrategy(S strategy) {
        this.strategy = strategy;
    }
}

Puedes hacer esto prácticamente con cualquier patrón, que yo sepa. Asegúrese de que puede probar su diseño genérico / plantilla con pruebas unitarias para ver si funciona, a fin de tener confianza en el diseño del código.

Si a sus colegas no les gusta la idea, entonces no la tomen como algo personal, es posible que no haya sido una solución tan fácil de manejar como pensaban. Es por eso que debe proponer una solución genérica / plantilla antes de comenzar a implementarla. Todavía tiene que trabajar junto con sus colegas para resolver el problema real de una manera diferente.

Spoike
fuente
Me encanta el diagrama! ¿Qué herramienta usaste?
yannis
@YannisRizos Usé el yuml.me que crea diagramas a partir de la entrada de texto. Sin embargo, el servicio beta es un poco defectuoso en este momento (sin embargo, puede cargar la imagen generada en su publicación utilizando el enlace generado).
Spoike
marcado, gracias por compartir. aunque realmente no quiero aprender otra sintaxis, por simplista que sea, se ve genial y lo intentaré en algún momento.
yannis
@YannisRizos Oh, constantemente me olvido de la sintaxis. Es por eso que hay una práctica página de muestras . Encontré que era más rápido escribir diagramas de clase simples en yuml que usar Visio.
Spoike
@YannisRizos yUml es una herramienta genial. Aquí hay algunos otros ejemplos de lo que puede hacer con él: carnotaurus.philipcarney.com/tagged/yUML
CarneyCode
4

Siempre hay varias formas de hacer lo mismo. Si su uso de plantillas es un mal uso de plantillas, entonces debería fallar la revisión del código.

Sin embargo, si su código falla la revisión, porque no entienden las plantillas, entonces el problema es de otro tipo. En ese caso, aconsejarlos (de una manera agradable) para aprender plantillas.

BЈовић
fuente
4

De lo que se trata aquí es de una colección de prejuicios. La gente prefiere el status quo, se ha desarrollado un pensamiento grupal y el argumento se ha planteado varias veces para que las personas se hayan atrincherado en sus creencias.

Una de las estrategias más efectivas aquí es centrarse en una pequeña victoria. Leí el siguiente ejemplo en un libro : el autor era un usuario incondicional de Apple. No le gustaban, y no quería tener nada que ver con ellos. Tuvo muchas conversaciones con personas con una postura pro-Apple, y cada una empujó sus talones más profundamente en el suelo. Entonces alguien le compró un iPod shuffle y así, sus prejuicios desaparecieron. No la hizo querer comprar solo productos Apple, pero la postura dura y arraigada contra Apple había sido reemplazada por un punto de vista más equilibrado. Había margen para el compromiso, y ella terminó convirtiéndose lentamente en Apple por completo.

Así que no intentes convencer a todos a la vez: tendrá el efecto contrario. Céntrate en una pequeña cosa, y el resto sucederá por sí solo. Simplemente elimine la naturaleza bilateral del argumento para que las personas puedan cruzar poco a poco, en lugar de hacerlo todos a la vez.

El punto específico en el que centrarse depende de su situación, pero aquí hay una idea: la división que bosqueja entre bibliotecas y 'código real' parece muy poco natural. En mi opinión, un programador que hace una aplicación debería pasar el 80% de su tiempo en una biblioteca para el tipo de aplicación que está haciendo y el 20% usa esa biblioteca para construir la aplicación. Todo código que valga la pena conservar debe considerarse una biblioteca. Sugeriría a sus superiores que generalice parte de su código en una biblioteca interna (si aún no lo ha hecho). Por su propia lógica, deberían usar genéricos para esto, y según la estimación anterior, el 80% de su código puede terminar dentro de la biblioteca. Una vez que todos usan genéricos del otro lado, deberían acostumbrarse y los prejuicios deberían desaparecer.

Peter
fuente
Gracias Peter, fue una respuesta muy perspicaz. Sus pensamientos se aplican no solo a mi pregunta, sino también a la filosofía general de nuestro día a día.
iammilind
2

Nota "comprensible". Si el revisor del código no ve el beneficio de los genéricos, entonces todo el material <<<>>>es un ruido incomprensible que es innecesario.

Sugeriría echar un vistazo a cuántos errores actuales (abiertos o recientemente corregidos) contiene su base de datos de errores que podrían haberse evitado mediante el uso de genéricos. Busque ClassCastExceptions.

También tenga en cuenta que si no tiene ningún error que podría haberse evitado mediante el uso de genéricos, sus colegas tienen un punto en el que no los necesita.


fuente
2

Sería fácil en esto. Me mudé de Java 1.4 a 1.6 hace un par de años, y los genéricos han sido una verdadera sorpresa. Es simple y muy útil si está tratando de hacer malabarismos con algunas colecciones, mapas y otras estructuras. Sin embargo, escribir clases que toman datos genéricos como parámetros, los manipulan y los pasan a otras clases rápidamente se vuelve monumentalmente confuso. Obtengo una gran satisfacción al hacer que todo funcione, pero me pregunto si el tiempo y el esfuerzo adicionales valieron la pena. También me temo que un buen número de programadores de Java nunca lo entenderán.

Algunos pensamientos aleatorios más de mi viaje genérico hasta ahora:

  • Las ClassCastExceptions ocurren en el tiempo de ejecución, pero generalmente aparecen en las primeras ejecuciones y son fáciles de solucionar.
  • Todos los artículos que he leído sobre genéricos afirman que a veces simplemente no funcionan y que debes usar @SuppressWarnings(value="unchecked")ocasionalmente. ¿Cómo saber si está más allá de los límites de los genéricos, o si simplemente está siendo estúpido y necesita pensar más?
  • Puede ser difícil de aplicar @SuppressWarnings(value="unchecked")a una sola línea.
  • Agregué algunos genéricos elegantes a una de mis clases. He conocido a varios programadores que podrían haber mejorado la clase antes de que la genérica, que nunca la hubieran tocado y luego obtuviera una compilación limpia.

Generics ha limpiado mi código y me advirtió de problemas demasiadas veces para que lo rechace, pero también veo un mayor tiempo de desarrollo, tiempo adicional dedicado a la capacitación y los programadores de Java obligados a trabajar en C #, C y Visual Basic. ..o Java 1.4. Me concentraría en escribir código que tus compañeros de trabajo puedan entender. Si puede introducir algunos genéricos comprensibles, genial. Veo los genéricos de Java como una oportunidad / problema que aún no se ha resuelto.

RalphChapin
fuente