Swift-style-guide: El sombreado variable puede conducir a un código más difícil de leer.

Creado en 15 dic. 2014  ·  22Comentarios  ·  Fuente: raywenderlich/swift-style-guide

Creo que deberíamos reconsiderar nuestra posición sobre el uso de variables de sombra al desenvolver. Nuestro argumento actual es que el compilador lo corregirá si intenta usar la variable incorrecta. Creo que hay una falla fundamental en ese argumento que hemos pasado por alto: hace que el código sea significativamente más difícil de leer cuando en realidad no está compilado.

Veo tres lugares principales donde leer código como este fuera de un compilador causa problemas:

  1. Principiantes rápidos . Es muy confuso que dos cosas con el mismo nombre tengan un comportamiento tan fundamentalmente diferente. Esto es particularmente cierto para aquellos de nosotros que venimos de Objective-C, donde intentar definir dos cosas con el mismo nombre provoca una advertencia del compilador.
  2. Revisiones de código . Para cualquiera que tenga que revisar el código antes de que se fusione, se requiere un nivel adicional de escrutinio para asegurarse de que "espere, ¿esta persona está tratando de asignar el valor opcional o no envuelto?"
  3. Edición de libros . ¿Esperamos que todos nuestros editores de libros tomen no solo el código de muestra sino cualquier código escrito en el libro y se aseguren de que se compile?

Toma este ejemplo:

func createNewPerson(name: String?) -> Person {
  let person = Person()
  if let name = name {
    person.name = name
  }
 return person
}

Sin compilar ese código, ¿cómo sé que la variable name que se establece es la que no está empaquetada en lugar de la que se pasa como opcional?

Esto es lo que he estado haciendo en mi código Swift en una situación similar:

func createNewPerson(name: String?) -> Person {
  let person = Person()
  if let unwrappedName = name {
    person.name = unwrappedName
  }
 return person
}

Para mí, simplemente agregar unwrapped al nombre de la variable sin envolver hace que el flujo del código sea significativamente más claro. No tenemos que usar esa sintaxis exacta (especialmente porque hace que los nombres de las variables sean mucho más largos), pero creo que deberíamos reconsiderar el sombreado de variables por este motivo.

OK, ahora que he hecho mi caso: ¡LUCHA LUCHA LUCHA LUCHA LUCHA!

1tpffru

Todos 22 comentarios

Para mí, ver ! durante la revisión del código es una señal de alerta. Ahí es cuando empiezo a preguntar "¿Por qué no vinculamos opcionalmente esta cosa?"

Me preocupa que "desenvuelto" sea un prefijo demasiado largo para los libros, es muy difícil mantener el ajuste de línea al mínimo, y eso es mucho espacio horizontal utilizado. Podría decirse que el ajuste de línea del código en los libros es peor en lo que respecta a la legibilidad en mi opinión. Por supuesto, este ejemplo no sufriría el ajuste de línea, pero agregue una llamada a la API de Cocoa y sería una historia diferente.

Sin embargo, mi postura sobre el seguimiento probablemente variará caso por caso y día a día:]

Sin compilar ese código, ¿cómo sé que la variable de nombre que se establece es la que no está empaquetada en lugar de la que se pasa como opcional?

Porque así es como funciona Swift. Si está dentro de un alcance if let , utiliza la versión sin encapsular. No hay ambigüedad aquí.

@hollance : no hay ambigüedad para alguien que conoce bien a Swift, y no hay ambigüedad cuando se compila. Para alguien que lo conoce menos (por ejemplo: yo) y está tratando de leer el código sin revisarlo y compilarlo, el sombreado variable hace que el flujo sea significativamente menos obvio.

@cwagdev ¿ Quizás el prefijo con solo u en lugar de sin envolver? En el trabajo, nuestros estándares de código de Android requieren que cualquier variable pasada como argumento tenga a como prefijo, y este ha sido un compromiso bastante sólido entre claridad y longitud variable.

Supongo que aquí es donde el resaltado de código semántico resulta útil. ;-)

Por cierto, ¿sabías que if var también sirve para desenvolver?

  if var name = name {
    name += ", Esq."
    person.name = name
  }

@hollance Ciertamente ayuda si el opcional que está desenvolviendo es una propiedad local, pero no hace mucho si es un argumento pasado.

En cuanto a if var : https://www.youtube.com/watch?v=Cd7tEsAuspA - ¡gracias!

Lo que pasa con el resaltado semántico frente al resaltado de sintaxis regular es que le da a cada variable su propio color. Por lo tanto, podrá ver de un vistazo que el name es diferente del parámetro name .

Hay un complemento de Xcode para esto, pero no sé si funciona con Swift. https://github.com/kolinkrewinkel/policromático

Me opongo firmemente a la introducción de nuevos prefijos variables o constantes. La notación húngara casi se ha extinguido, ¡no hay una buena razón para revivirla!

Estoy de acuerdo en que debemos confiar en las herramientas de desarrollo para dar pistas sobre el alcance y el contexto.

Ciertamente entiendo el argumento de que dentro de un entorno compilado, esto no es necesario; es por eso que se adoptó esta regla en primer lugar.

El problema es que nuestro código a menudo se lee fuera de un entorno compilado, ya sea en el sitio web o en los libros. Este proceso se vuelve _significativamente_ menos obvio sin la ayuda del vomitado del compilador si intenta usar el var o let incorrecto no opcional vs. opcional.

@ColinEberhardt y @hollance : ¿Tiene alguna otra sugerencia sobre cómo podemos dar un mejor contexto a estas cosas en un entorno de solo lectura sin recurrir a un prefijo variable? ¿O deberíamos simplemente decir: "Al diablo, escríbelo en un patio de recreo si no lo entiendes"?

+1 por usar el mismo nombre. En general, me opondría al sombreado variable, pero en este caso creo que tiene sentido. Simplifica las cosas, ya que no es necesario utilizar nombres o prefijos de creatividades. Además, la variable sombreada realmente se refiere a la misma variable, solo a la versión no envuelta de la misma, es decir, en realidad no sombrea a ninguna otra variable, se sombrea a sí misma.

Me gusta la explicación de @jawwad de que el sombreado realmente se "sombrea a sí mismo", por lo que tiene sentido usar el mismo nombre.

También podría argumentar el otro lado: si tuviera foo y unwrappedFoo y luego llamara a algún método en unwrappedFoo , es posible que las personas se confundan de que se trata de dos cosas diferentes. y ese foo no fue tocado. Eventualmente lo entenderán cuando entiendan los opcionales, pero ese también es el caso de la forma de sombra.

De cualquier manera, necesitaremos confiar en que las personas "lo comprendan" eventualmente y, si ese es el caso, prefiero optimizar para la eventualidad de que las personas entiendan las opciones.

Sin embargo, ¡sigamos con la discusión! ¡Tal vez podamos superar el recuento de publicaciones para la discusión de la guía de estilo de Objective-C sobre ivars vs propiedades!

Una tormenta potencial que se está gestando del mismo Dios, https://devforums.apple.com/message/1127586#1127586

Creo que esa publicación trata más sobre si el sombreado variable debe lanzar una advertencia: Laettener dice que no y que no hay una guía específica sobre si debe sombrear estilísticamente o no.

Desde que comencé este incendio, permítame darle una actualización: he estado trabajando más en Swift en un prototipo, y todavía siento que me cuesta mucho más leer el código sin las sombras.

Lo que se reduce a mí es esta vieja castaña :

Programs must be written for people to read, 
and only incidentally for machines to execute.

Sí, el compilador te dirá cuándo te estás equivocando cuando en realidad estás escribiendo el código. Pero leer el código de otros (o incluso el mío) se vuelve significativamente más difícil para mí con el sombreado variable. Me resulta mucho más difícil intuir dónde alguien accede al valor no envuelto frente al valor envuelto cuando estoy leyendo código sombreado.

También he estado trabajando con programadores más nuevos que tienen muchos problemas para comprender el alcance (lo cual ciertamente hice cuando estaba comenzando), y solo veo que este problema empeora mil veces con el sombreado variable. ¿Cómo puede un programador más nuevo saber que en realidad está accediendo a una constante sin encapsular en un ámbito particular en lugar de a la variable opcional original?

Tener una delimitación clara entre lo que está desenvolviendo y lo que está desenvuelto que es fácilmente legible hará que sea mucho más fácil para los novatos saber a cuál de los dos están accediendo.

Y sé que @ColinEberhardt se pondrá muy triste de escuchar, pero adopté el prefijo u en mi código personal y descubrí que es de gran ayuda.

No creo que Laettener dé consejos de una forma u otra aquí... simplemente dice que no habrá una advertencia.

Parece que me está diciendo "hazlo si realmente quieres"... :]

De acuerdo, principalmente estaba siendo sarcástico y el hilo me recordó esto :smile:

Todavía estoy en el campo de la sombra, pero puedo ver el punto de @designatednerd .

@designatednerd Shadowing es simplemente más ordenado. Es un hecho fácilmente deducible que dentro del alcance de if let, se está refiriendo a la versión sin envolver. El desenvolvimiento explícito es tan común que cualquier persona que valga unos días de experiencia con Swift probablemente ya lo sepa.

@annehiro No estoy de acuerdo con la evaluación "cualquiera que valga unos días de experiencia con Swift probablemente ya lo sepa". Cualquiera con algunos días de experiencia con swift _y_ mucha otra experiencia en programación probablemente lo entenderá, porque entiende el alcance. Anteriormente entré en detalles sobre por qué creo que esto hace que sea más difícil de entender para los n00bs que realmente no entienden el alcance.

Sin embargo, @gregheo , no sé si vale la pena dejar abierto este problema. Si bien todavía me siento exactamente como dice el título de este problema (y sigo usando variables no sombreadas en mi propio código), hacer este cambio a nivel del sitio requeriría una cantidad increíble de trabajo para actualizar el sitio y los libros en este momento.

Este conjunto de estándares de código se usa como referencia para muchos lugares de trabajo que aún están desarrollando sus propios estándares de código Swift (incluido el mío), pero en última instancia, estos son para nuestro sitio y libros. Y creo que el caballo ha salido del establo y ha corrido por medio país a estas alturas cambiando de tutoriales y libros. :las carreras de caballos:

FWIW, he escrito bastante sobre Swift desde que esto sucedió y diría que sombreo el 90% del tiempo, omito el sombreado cuando la variable es extremadamente detallada.

Esta es una pregunta difícil ya que hay buenos puntos en ambos lados del argumento. Personalmente, no me gusta el término "sombreado", ya que realmente es una transformación de tipo estático de opcional a no opcional. Nunca he tenido problemas para leer el código, ya que es fácil saber si algo es opcional o no opcional en el sitio de la llamada. Pensar en ello como una transformación de tipo también encaja bien con el uso guard para satisfacer las condiciones previas antes y salir si no se cumplen. Espero que algún día en el futuro obtengamos azúcar sintáctico que se parezca a esto:

func compute(a: Int?, b: Int?) -> {
   unwrap a, b else { return }
   // compute with a and b Ints
}

Unwrap también funcionaría con el mítico tipo Result .

A menudo, hay momentos en los que tiene sentido no usar el mismo nombre sino una forma abreviada. Por ejemplo, viniendo del framework Siesta (que considero un código realmente genial en cuanto a su divertido espacio en blanco):

guard let cache = config.persistentCache else { return }

Otras veces solo sombras.

Creo que @cwagdev está llegando. Algunos otros proyectos que revisé usaban una combinación de sombreado y no sombreado, incluido Almofire, y la implementación de Foundation de código abierto de Apple. Sin embargo, ninguno de estos proyectos utilizó la notación húngara.

Con base en estos hallazgos y en mi propio instinto personal, voy a dictaminar que, por ahora, no se debe hacer ningún estándar sobre sombra o no sombra. Cerrando este problema, pero podemos volver a visitarlo si el panorama cambia.

@rayfix 👍 Yo también estoy por cerrar este tema.

Sin embargo, con respecto

Voy a dictaminar que por ahora no se debe hacer ningún estándar sobre sombrear o no sombrear.

De hecho, la guía de estilo ya tiene una sentencia al respecto:

Para el enlace opcional, sombree el nombre original cuando corresponda en lugar de usar nombres como unwrappedView o actualLabel.

Cuando se abrió este problema, _no_ había mucho de nuestro código o tutoriales que usaran "sombreado".

Ahora, sin embargo, es una historia diferente:

  • Lo hemos usado en muchos tutoriales escritos y en video.
  • Lo usamos y explicamos en RWDevCon 2015 y 2016.
  • En general, hemos respaldado esencialmente la idea de "sombrear" el nombre original.

En este punto, creo que estamos comprometidos con eso... Personalmente, también me ha gustado...

Como bien 🍷, te crece? 😉

Para mí, eso dice, "no use la notación húngara", con lo que estoy totalmente de acuerdo. El "cuando sea apropiado" da un pequeño margen de maniobra para cosas como:

guard let json = content as? NSDictionary else { throw InvalidJSON }

FWIW, dejé de usar u y terminé usando diferentes nombres de variables, pero me doy cuenta de que perdí esta batalla. :sonreír:

@designatednerd como alguien nuevo en Swift, creo que tenías toda la razón en esto. Es confuso para los principiantes. Estaba realmente confundido sobre cómo funcionaba el alcance con esto.

¿Fue útil esta página
0 / 5 - 0 calificaciones

Temas relacionados

icanzilb picture icanzilb  ·  6Comentarios

jackwu95 picture jackwu95  ·  6Comentarios

samkim102 picture samkim102  ·  4Comentarios

Lweek picture Lweek  ·  5Comentarios

aramezk picture aramezk  ·  9Comentarios