¿Debo seguir un mal estilo de codificación solo para seguir las convenciones establecidas en mi lugar de trabajo?


102

He estado trabajando en mi trabajo durante aproximadamente un año. Principalmente trabajo en nuestra interfaz GUI que usa métodos de un servidor C, pero generalmente no tengo que lidiar con ellos excepto por los valores de retorno. Nuestra GUI está estructurada de manera bastante razonable, dadas nuestras limitaciones.

Me encargaron agregar una función a la parte de la línea de comando del programa. La mayoría de estas funciones son como 300 líneas de largo y difíciles de usar. Estoy tratando de reunir partes de ellos para obtener información específica de alarma, y ​​tengo problemas para mantenerme organizado. Sé que estoy haciendo mis pruebas más complicadas al hacerlo en una sola función larga.

¿Debería mantener todo en una gran función según el estilo de las funciones existentes, o debería encapsular las alarmas en sus propias funciones?

No estoy seguro de si es apropiado ir en contra de las convenciones de codificación actuales o si debería morder la viñeta y hacer que el código sea un poco más confuso para mí.

En resumen, estoy comparando

showAlarms(){
    // tons of code
}

en contra

showAlarms(){
   alarm1();
   alarm2();
   return;
}

alarm1(){
    ...
    printf(...);
    return;
}

EDITAR: Gracias por el consejo de todos, decidí que voy a diseñar mi código factorizado, y luego preguntar qué quieren, y si lo quieren todo en uno, puedo cortar mi código factorizado y volver a convertirlo en 1 Gran función. Esto debería permitirme escribirlo y probarlo más fácilmente, incluso si quieren todo el código en una sola definición.

ACTUALIZACIÓN: Terminaron siendo felices con el código factorizado y más de una persona me ha agradecido por establecer este precedente.


117
Es muy dudoso que la empresa para la que trabaja adopte la posición de que sus funciones deben tener 300 líneas de largo porque "esa es la forma en que siempre lo hemos hecho". Eso no es "convenciones de estilo de codificación"; Es solo un mal estilo.
Robert Harvey

64
Este es el tipo de cosas que deberías discutir con otros miembros de tu equipo, para descubrir qué prácticas ves son convenciones que consideran importantes que todos deben seguir, y cuáles son las cosas que alguien acaba de hacer una vez y que tú no. Necesito emular. Sin duda habrá alguna cantidad de ambos.
Servy

17
@beginnerBinx Eso se reduce a cómo lo expresas. No lo diga como: "X está haciendo algo realmente estúpido, ¿también tengo que hacer eso estúpido?" pero más bien como algo así como: "Me doy cuenta de que X está haciendo esto, ¿hay alguna razón en particular que lo haga de la manera que lo hace? ¿Sería un problema si no hiciera lo mismo al escribir Y?" Luego, se convierte en su decisión de descifrar el código anterior o explicar por qué tuvieron que hacerlo de esa manera (ya sea de mala gana o con entusiasmo).
Servy

11
El estilo bueno o malo se discute frecuentemente y se acuerda con poca frecuencia. La enseñanza universitaria es que las funciones deben ser cortas, pero si esto oscurece el significado, no lo hagas. La prueba debe ser clara, en lugar de seguir sin pensar un conjunto de reglas.
rapid_now

99
A las personas aleatorias en Internet no les importa leer a tus compañeros de equipo, por lo que todas las respuestas que obtienes aquí son solo preferencias personales de las personas. Deberías hablar con tu equipo. ¿Es la función larga un principio de diseño deliberado? ¿Les gustaría que continuaran con el estilo de la función larga o querrían que escribieran lo que consideran el más limpio?
JacquesB

Respuestas:


102

Esto es realmente entre usted y sus compañeros de equipo. Nadie más puede decirte la respuesta correcta. Sin embargo, si me atrevo a leer entre líneas, el hecho de que llame a este estilo "malo" proporciona información que sugiere que es mejor tomarlo con calma. Muy pocos estilos de codificación son realmente "malos". Hay algunos que no usaría, pero siempre tienen una rima o razón para ellos. Esto sugiere, para mí, que hay más en la historia de lo que has visto hasta ahora. Preguntar sería una decisión muy acertada. Alguien puede saber algo que tú no.

Me encontré con esto, personalmente, en mi primera incursión en la codificación de misión crítica en tiempo real. Vi un código como este:

lockMutex(&mutex);
int rval;
if (...)
{
    ...
    rval = foo();
}
else
{
    ...
    rval = bar();
}
unlockMutex(&mutex);
return rval;

Siendo el desarrollador OO C ++ brillante y brillante que era, inmediatamente los llamé sobre los riesgos de errores que tenían al bloquear y desbloquear mutexes manualmente, en lugar de usar RAII . Insistí en que esto era mejor:

MutexLocker lock(mutex);
if (...)
{
    ...
    return foo();
}
else
{
    ...
    return bar();
}

Mucho más simple y es más seguro, ¿verdad? ¡Por qué exigir a los desarrolladores que recuerden desbloquear sus mutex en todas las rutas de flujo de control cuando el compilador puede hacerlo por usted!

Bueno, lo que descubrí más tarde fue que había una razón de procedimiento para esto. Tuvimos que confirmar que sí, el software funcionó correctamente y que había una lista finita de herramientas que teníamos permitido usar. Mi enfoque puede haber sido mejor en un entorno diferente, pero en el entorno en el que estaba trabajando, mi enfoque multiplicaría fácilmente la cantidad de trabajo involucrado en la verificación del algoritmo diez veces porque acabo de incorporar un concepto C ++ de RAII en una sección de código eso estaba sujeto a estándares que eran realmente más susceptibles al pensamiento de estilo C.

Entonces, lo que parecía malo, francamente peligroso, estilo de codificación para mí en realidad estaba bien pensado y mi "buena" solución era en realidad la peligrosa que iba a causar problemas en el futuro.

Entonces pregunta por ahí. Seguramente hay un desarrollador senior que puede trabajar con usted para comprender por qué lo hacen de esta manera. O bien, hay un desarrollador senior que puede ayudarlo a comprender los costos y beneficios de un refactor en esta parte del código. De cualquier manera, ¡pregunta por ahí!


6060
Podría decirse que la parte más peligrosa del ejemplo de mutex es la aparente falta de comentarios de código que expliquen por qué no pudo usar RAII. De acuerdo, si este bloqueo / desbloqueo explícito está en toda la base de código, podría ser difícil agregar un comentario para cada instancia. En ese caso, tal vez debería escribirse un documento de introducción con el que los nuevos desarrolladores deben estar familiarizados.
Kelvin

10
Claro, hablar con una persona mayor siempre es bueno, y la refactorización debe hacerse con cuidado (y con pruebas). Y, por supuesto, la concurrencia / mutexes son una bestia especial por sí mismos. Pero al ver funciones con más de 300 líneas, no invertiría demasiado tiempo buscando una "razón técnica oculta" por la que estas funciones son demasiado grandes. La razón por la cual las funciones se vuelven demasiado largas son siempre las mismas, y no son técnicas.
Doc Brown

8
@DocBrown El hecho de que no sean técnicos no significa que no sean razones. Es importante que los desarrolladores recuerden que son una parte de una máquina más grande. (No puedo contar la cantidad de veces que tuve que volver a aprender esa lección)
Cort Ammon

44
@DocBrown De cualquier manera, es con los desarrolladores senior con los que uno debería estar hablando. Elegí el ejemplo que hice porque es fácil encontrar innumerables argumentos de por qué el código estúpido es estúpido. Encontrar los argumentos de por qué el código que parece estúpido en realidad no es estúpido es más difícil.
Cort Ammon

3
@DocBrown De sus comentarios y respuestas, creo que puedo decir que la diferencia de nuestras opiniones es que usted parte de la suposición de que el código ya es "malo", en función de la evidencia que se le haya proporcionado, aunque preferiría tome caminos que exploren si el código es o no "malo" primero.
Cort Ammon

84

Honestamente, ¿crees que tener funciones que son difíciles de usar, con 300 líneas, es solo una cuestión de estilo? Entonces, ¿seguir el mal ejemplo podría mantener el programa general en un mejor estado debido a la consistencia? Supongo que no lo crees, de lo contrario no hubieras hecho esta pregunta aquí.

Supongo que estas funciones son tan largas porque en nuestro negocio hay muchos programadores mediocres que simplemente agrupan características sobre características, sin preocuparse por la legibilidad, la calidad del código, el nombre adecuado, las pruebas unitarias, la refactorización, y nunca han aprendido a crear abstracciones adecuadas. . Tienes que decidir por ti mismo si quieres seguir a ese rebaño o si quieres ser un mejor programador.

Addendum, debido a los comentarios: "300 líneas" y "difícil de usar" son, en mi humilde opinión, fuertes indicaciones de código incorrecto. Según mi experiencia, es muy poco probable que haya alguna "razón técnica oculta" por la cual dicho código no se puede implementar de una manera más legible, comparable al ejemplo de la respuesta de Cort Ammon. Sin embargo, estoy de acuerdo con Cort en que debe discutir esto con los responsables del equipo, no para encontrar razones oscuras por las que el código o este "tipo de estilo" no se pueden cambiar, sino para descubrir cómo se puede refactorizar el código de manera segura sin romper las cosas. .


127
Incluso los programadores competentes cometen estos crímenes cuando se encuentran bajo plazos ajustados.
cabeza de jardín

13
@gardenhead, puedo entender que no refactorice una función de 300 líneas para ahorrar tiempo, pero no hay forma posible de que escribir una función de 300 líneas le ahorre tiempo.
Dangph

39
@gardenhead: cuando voy al cirujano porque necesito ayuda urgente, todavía espero que se tome el tiempo para lavarse las manos antes de comenzar a actuar conmigo. Esto es algo que mucha gente tiene que aprender en nuestro negocio para lograr una competencia real : siempre deje el código en un mejor estado que antes, y eso también mejorará la capacidad de cumplir con los plazos. Las funciones de 300 líneas suelen crecer día a día, por personas a las que no les importa, y siempre usarán "la fecha límite" como excusa.
Doc Brown

17
@Dangph ahorra tiempo cuando solo agrega 5 líneas a la función en lugar de refactorizarla. Esos generalmente crecen cuando la función inicial es larga (más de 30 líneas) y el siguiente programador piensa "este no es mi código, no refactorizaré para no romperlo, solo agregue algunas líneas aquí y allá".
Džuris

77
@Juris, según tengo entendido, la cuestión es crear una nueva función, no refactorizar las existentes. Si está escribiendo una nueva función, no ahorrará tiempo convirtiéndola en una sola función de monstruo.
Dangph

42

No.

En el libro Programador pragmático, el autor habla sobre la teoría de la ventana rota .

Esta teoría dice:

Considere un edificio con algunas ventanas rotas. Si las ventanas no se reparan, la tendencia es que los vándalos rompan algunas ventanas más. Eventualmente, incluso pueden irrumpir en el edificio, y si está desocupado, tal vez se conviertan en ocupantes ilegales o enciendan incendios en el interior.

O considere un pavimento. Se acumula algo de basura. Pronto, se acumula más basura. Eventualmente, la gente incluso comienza a dejar bolsas de basura de restaurantes para llevar allí o incluso irrumpir en automóviles.

En el libro, el autor escribe un paralelo entre esta teoría y el código. Una vez que encuentra un código como este, se detiene y se pregunta esa misma pregunta.

Y la respuesta es no.

Una vez que salga de esta ventana rota, en nuestro caso, código incorrecto, esto creará el efecto de que todos dejarán ventanas rotas.

Y un día el código colapsará.

Entregue una copia de Clean Code y Clean Coder a todos.

Y mientras está en el tema, una copia de TDD también es buena.


66
¿Qué pasa si la base de código es un invernadero con nada más que ventanas rotas?
Alan Shutko

8
@AlanShutko Entonces, ¿asegúrate de que tu currículum esté actualizado? Encuentre un empleador diferente ahora .
David Montgomery

12
El código rara vez "colapsa". Se está volviendo cada vez más difícil agregar nuevas funciones, lleva cada vez más tiempo y las estimaciones para limpiar el código aumentarán, lo que significa que es aún más difícil obtener un presupuesto de tiempo para la limpieza necesaria.
Doc Brown

8
Vaya, qué analogía arbitraria parece ser la teoría de la "ventana rota".
Samthere

44
TDD no tiene nada que ver con eso. Ya sea que vaya a un diseño de controlador de negocios / dominio / prueba / nada que no cambie nada, siga los principios básicos del código limpio. Lo siento, pero es realmente agotador ver 'TDD' citado en todas partes donde ni siquiera en el tema
Walfrat

25

Sí, adelante. Estructura! = Estilo

Estás hablando de estructura, no de estilo. Las pautas de estilo no prescriben (generalmente) la estructura, ya que la estructura generalmente se elige por su idoneidad para un problema específico, no por la idoneidad de una organización.

Ten cuidado

Solo tenga la seguridad de que no está causando consecuencias negativas en otras áreas que quizás no se le hayan ocurrido. Por ejemplo,

  • Asegúrese de no complicar las diferencias o las fusiones de código porque ha borrado cualquier parecido con el código existente.
  • Asegúrese de que los flujos de excepción burbujeen correctamente y que los rastros de la pila no estén contaminados con un montón de tonterías ilegibles.
  • Asegúrese de no exponer accidentalmente los puntos de entrada públicos que podrían causar problemas si se les llama directamente (no los coloque en el mapa y / o no los exporte).
  • No abarrote el espacio de nombres global, por ejemplo, si sus funciones más pequeñas requieren algún tipo de contexto global que se haya declarado previamente en el ámbito local de funciones.
  • Asegúrese de mirar los registros y pregúntese si estaba en el equipo de soporte si los registros generados por su código serían confusos cuando se ven entretejidos con los registros de cualquier código que no toque.
  • Asegúrese de que no se adhieren a estilo existente, por ejemplo, incluso si están utilizando la vieja escuela notación húngara y hace que sus ojos sangran, se mantienen consistentes con la base de código en general. Lo único más doloroso que leer la notación húngara es leer el código que usa una docena de diferentes tipos de notación dependiendo de quién escribió qué.

Sé gentil

Recuerde que usted es parte de un equipo, y si bien un buen código es importante, también es muy importante que los miembros de su equipo puedan mantener las cosas que escribió cuando se va de vacaciones. Trate de mantener un flujo que tenga sentido para las personas que están acostumbradas al viejo estilo. ¡Solo porque eres el tipo más inteligente de la sala no significa que debas hablar por encima de la cabeza de todos!


"Trate de mantener un flujo que tenga sentido para las personas que están acostumbradas al viejo estilo". - Entonces, ¿es su consejo programar de la misma manera que cualquier payaso incompetente que haya hecho antes? Agregar la función de 300 líneas no va a facilitarlo.
Bћовић

11
No le dije que se apegara a un flujo similar. Dije atenerse a un flujo que ellos entenderán.
John Wu

2
Buen consejo. Cuando refactoricé un solo comando en 5 funciones en esta respuesta, cambié sutilmente la semántica precalculando valores dentro de una expresión lógica que originalmente solo se computaba condicionalmente. Sin embargo, los críticos lo entendieron ;-). El consejo serio es revisar y probar a fondo. Cada cambio puede introducir errores, y esa puede ser la razón principal por la que nadie los ha cometido.
Peter A. Schneider

6

No veo esto como una convención de código. Veo esto como alguien que no comprende cómo escribir código que se pueda mantener y que sea fácil de entender. Desglosaría su código en diferentes funciones a medida que sugiera y eduque a su equipo sobre los beneficios de hacer esto mientras trato de entender por qué consideran que las funciones de 300 líneas son aceptables. Estaría muy interesado en escuchar su razonamiento.


1
" No hay razón, es solo nuestra política "

5

La respuesta está en la revisión del código.

La verdadera pregunta es si entregas un código bien factorizado, ¿vas a ser el único dispuesto a trabajar con él?

Yo, como la mayoría de las personas aquí, creo que 300 funciones de línea son una abominación. Sin embargo, llevar Windex a un vertedero no va a hacer mucho bien. El problema no es el código, son los codificadores.

Solo tener razón no es suficiente. Necesitas vender personas en este estilo. Al menos al leerlo. Si no lo haces, terminas como este pobre tipo: despedido porque tus habilidades están muy por encima de tus compañeros de trabajo

Empieza pequeño. Pregunte y descubra si alguien más favorece las funciones más pequeñas. Mejor aún, husmee en la base del código y vea si puede descubrir quién escribe los más pequeños (puede encontrar que el código más feo es el código más antiguo y los codificadores actuales están escribiendo un código mejor). Hable con ellos sobre esto y vea si tiene un aliado. Pregúnteles si conocen a alguien más que sienta lo mismo. Pregúnteles si conocen a alguien que odie las funciones pequeñas.

Reúna a este pequeño grupo y hable acerca de hacer cambios. Muéstreles el tipo de código que le gustaría escribir. Asegúrese de que puedan leerlo. Tome cualquier objeción en serio. Haz los cambios. Obtenga su código aprobado. Ahora tiene el poder de una reunión detrás de usted. Un poco más de estos y puede producir un documento de una página que acepte explícitamente el nuevo estilo que ha introducido.

Las reuniones son cosas sorprendentemente poderosas. Pueden producir influencia. La influencia es lo que usarás para luchar contra aquellos que se oponen a este movimiento. Y eso es lo que es esto en este momento. Un movimiento. Estás luchando por el derecho a mejorar el status quo. La gente teme al cambio. Tendrás que hablar dulcemente, engatusar y pinchar. Pero con un poco de suerte, serás aceptado y aceptado.


55
Si se necesita tanta socialización y múltiples reuniones para convencer a los desarrolladores de que un método de 300 líneas es demasiado largo, entonces no creo que hablar ayude. El problema con el enfoque anterior es que si solicita permiso para escribir un buen código, está a la defensiva. Pero si solo escribe un buen código y se toma el tiempo de refactorizar el código existente, cualquier persona que se oponga está a la defensiva para explicar por qué un método de 300 líneas es bueno y para justificar pasar el tiempo volviendo a ponerlo.
Brandon

3
Puedo decirle que si me invitaron a una serie de reuniones para discutir líneas de código por límites de función, encontraría una manera de escapar de tales reuniones. No hay un número correcto y nunca conseguirás que la gente esté de acuerdo. A veces, las personas necesitan que se les muestre una mejor manera.
Brandon

A veces, dividir una función enorme (y nombrar mejor las cosas y agregar comentarios y documentación como lo descubro es el primer paso necesario antes de realizar un cambio de forma segura.)
JDługosz

@ Brandon Probablemente no quieras que suene de esta manera, pero lo que escucho es que tienes razón y todos los demás pueden lidiar con eso. Mientras su código funcione, no importa si el resto del equipo no lo entiende. Ciertamente no vale la pena molestarse en enseñarles nada. Está perfectamente feliz de verlos continuar creando funciones de 300 líneas mientras escribe código a su manera.
candied_orange

1
@CandiedOrange Ciertamente no quise decir ir en contra del equipo. Lo que quise decir es que algunos temas se aprenden mejor al verlos en acción, pero tratar de lograr que un equipo tome una decisión democrática sobre el estilo no será productivo. He visto la consistencia utilizada como una excusa para escribir código ilegible. ¿Resultado? Código más ilegible. Podría organizar una serie de reuniones para hablar sobre ello, o podría arreglarlo y luego mostrarle a la gente los resultados.
Brandon

3

A veces tienes que ir con la corriente.

Como dijiste, te encargaron implementar una función en una base de código de trabajo existente.

Independientemente del desorden, y entiendo que es tentador limpiarlo. pero en el mundo de los negocios no siempre tienes la oportunidad de refactorizar el código.

Yo diría que solo haga lo que se le ha pedido que haga y siga adelante.

Si cree que vale la pena refactorizar o reescribir, entonces debe mencionarlo para discutirlo con el equipo.


2
Si solicita permiso para cada pequeña refactorización, siempre tendrá un código que no se puede mantener, lo cual es peligroso para un negocio. Los gerentes solo observan el costo de un cambio, pero rara vez analizan el costo de no cambiar.
Brandon

55
Se le ha pedido a OP que escriba una función que no modifique cientos de líneas de código
meda

2
@meda exactamente! Estoy en la misma situación. Estoy desarrollando nuevos módulos para la intranet de la compañía y encuentro lo que podría describirse como "años de negligencia más allá de la reparación", con el software del servidor y las bibliotecas que no se actualizan en absoluto desde 2006. Se supone que no debo limpiar este desastre. , pero me lleva más tiempo codificar debido a las limitaciones. (Imagine MySQl 5.2, MySQL 5.0). No puedo actualizar nada porque probablemente el código existente no se ejecutará en versiones más nuevas debido a un código obsoleto.
roetnig

3
"Si no está roto, no lo arregles". Tengo un auto de 20 años que gotea un poco de aceite. ¿Vale la pena gastar dinero? No. ¿confiable? Si.

3

Antes de hacer la declaración de que las prácticas son malas, primero daría un paso hacia la comprensión de la razón de los grandes métodos y otras prácticas que podrían parecer malas.

Luego, deberá asegurarse de que la cobertura de la prueba sea bastante alta o muy alta (en la medida de lo posible sin una refactorización importante). Si no es así, trabajaría para hacer que la cobertura sea realmente alta aunque no haya escrito el código. Esto ayuda a construir una buena relación y el nuevo equipo tuyo te tomará más en serio.

Una vez que tenga estas bases cubiertas, nadie en su sano juicio lo desafiará. Como elemento de bonificación, haga algunos micro-benchmarking y eso realmente se agregará a su caso.

A menudo, la forma en que lo redactas contribuye en gran medida a cambiar la cultura del código. Predicar con el ejemplo. O mejor aún, espere un código que pueda escribir (refactor y prueba unitaria y viola) se le escuchará.


No estoy refactorizando el código actual, solo estoy escribiendo una nueva función, no estoy seguro de si debería seguir la 'convención' y codificarla en una monstruosidad de más de 300 líneas o dividirla en fragmentos lógicos como lo haría normalmente, pero tiene no se ha hecho en esta parte de la base del código.
Justin

1
¿Tienen reglas para asegurarse de escribir nuevos métodos en más de 300 líneas? si no, lo escribiría de la manera correcta. pero haría todo lo posible para asegurarme de probarlos, incluidas las ramas. He pasado por experiencias similares y generalmente las ganas. El truco es hacerlo con el tiempo y construir una buena relación.
skipy

3

Este tipo de pregunta es básicamente " lee por favor a mis compañeros de equipo ". Las personas aleatorias en Internet no pueden hacer eso, por lo que todas las respuestas que obtendrá son solo opiniones personales de las personas sobre el estilo de codificación. El consenso es que los métodos más cortos son preferibles, pero parece que ya lo crees, así que no es necesario que lo repitas.

Entonces, la base de código actual parece usar un estilo de codificación diferente al que usted prefiere. Que deberias hacer Primero necesitas descubrir:

  1. ¿Es esta una decisión de diseño deliberada respaldada por su equipo actual?
  2. ¿Quieren que sigas este estilo?

Solo hay una manera de descubrirlo. Preguntar .

Podría haber múltiples razones para tener funciones largas. Podría ser porque el equipo cree que las funciones largas son mejores que las funciones cortas múltiples. También podría deberse a que es un código heredado, y el equipo prefiere que el nuevo código siga un diseño más limpio. Por lo tanto, cualquiera de las dos opciones podría ocasionarle problemas como desarrollador, si no habla con el equipo y comprende su razonamiento.


1
Estoy completamente de acuerdo y agrego: "¿Podría ser despedido o tener problemas por no seguir lo que otros han hecho?" ¡Entonces la respuesta es sí! Después de cada cosa mala que la compañía requiere que hagas y lidies con ella.
Rob

1

Hay diferentes niveles de "estilo".

En un nivel, generalmente parte de las convenciones de codificación, esto significa dónde colocar espacios en blanco, líneas en blanco, corchetes y cómo nombrar cosas (mayúsculas y minúsculas, guiones bajos, etc.).

En otro nivel está el modelo de programación, a veces cosas como evitar la estática, o usar interfaces sobre clases abstractas, cómo exponer dependencias, tal vez incluso evitar algunas características del lenguaje esotérico.

Luego están las bibliotecas y los marcos en uso por el proyecto.

A veces habrá un límite máximo en el tamaño de la función. ¡Pero rara vez hay un límite mínimo! Por lo tanto, debe averiguar cuáles de estas cosas los poderes que se consideran importantes, y tratar de respetar eso.

Debe averiguar si el equipo es adverso a la refactorización del código existente, lo que debe hacerse independientemente de agregar un nuevo código cuando sea posible.

Sin embargo, incluso si no quieren refactorizar el código existente, es posible que pueda introducir algunas capas en abstracciones para el nuevo código que agregue, lo que significa que con el tiempo puede desarrollar una mejor base de código y tal vez migrar el código antiguo como mantenimiento de lo que requiere.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.