[Nota: El siguiente es un poco C # pesado en su sintaxis y convenciones, como citar las reglas de FxCop, porque este es mi fondo, pero la intención de esta discusión es ser independiente del lenguaje y los ejemplos de código utilizados generalmente deben considerarse como pseudocódigo. - Miguel]
Creo que todos estaríamos de acuerdo en que las clases generalmente deben diseñarse de modo que sus instancias de objeto sean inmutables siempre que sea práctico, y los resultados de llamar a los miembros de la clase deben estar libres de efectos secundarios, tanto como sea posible.
Sin embargo, las convenciones de nomenclatura históricas tienden a usar la voz activa: 'GetSomething', 'DoSomehing', etc. y esto es bueno porque establece claramente qué acción tomará el miembro de la clase.
Ahora estoy empezando a pensar, sin embargo, que los miembros a veces (o posiblemente a menudo) se benefician al ser nombrados en tiempo pasado para connotar que se devuelve un valor sin afectar el objeto referenciado.
Por ejemplo, para un método que transpone una matriz, los estilos de nomenclatura actuales probablemente lo llamarían 'Array.Transpose', pero si este miembro devuelve una nueva matriz, sin transponer el objeto al que se hace referencia, entonces creo que llamarlo 'Array.Transposed 'sería más preciso y lo hace más claro para el programador.
Cuando se trabaja con un método 'Array.Transpose ()', uno podría intentar accidentalmente usar código como el siguiente:
Array myArray = new Array();
myArray.Transpose();
Pero si el método 'Transponer' devuelve una nueva matriz sin afectar el objeto referenciado, entonces este código no hace nada, es decir, 'myArray' no se transpondría silenciosamente . (Supongo que si 'Transponer' fuera una propiedad, entonces el compilador entendería que lo anterior no es legal, pero las pautas de FxCop establecen que un miembro que realiza una conversión debería ser un método).
Pero si el método se nombrara en tiempo pasado como 'Array.Transposed', sería más claro para el usuario que se requiere la siguiente sintaxis:
Array myArray = new Array();
Array transposedArray = myArray.Transposed();
Otros nombres que creo que encajarían en esta categoría serían miembros denominados 'Resized' vs. 'Resize', 'Shifted' vs. 'Shift', etc. El tiempo presente se usaría para los miembros que afectaron el objeto referenciado, mientras que el el tiempo pasado se usaría para los miembros que devolvieron un nuevo valor sin afectar el objeto referenciado.
Otro enfoque que es más común actualmente es prefijar cada nombre con "Obtener" o "Para", pero creo que esto agrega un peso innecesario, mientras que el cambio al tiempo pasado comunica el significado de manera efectiva.
¿Tiene sentido para otros programadores aquí, o esta idea en tiempo pasado suena demasiado incómoda al leerla?
Editar:
Grandes discusiones a continuación, agradezco mucho a todos. A continuación, detallo algunos puntos que me gustaría resumir en base a sus comentarios y mi propio pensamiento revisado sobre esto.
Método de encadenamiento de sintaxis "fluidas"
Basado en las discusiones a continuación, el uso del tiempo pasado es probablemente de algún valor cuando se usa en una clase mutable para dejar en claro qué miembros afectan o no el estado interno del objeto referenciado.
Sin embargo, para las clases inmutables, que deberían ser la mayoría de los casos (uno esperaría), creo que el uso del tiempo pasado puede hacer que la sintaxis sea innecesariamente incómoda.
Por ejemplo, con "sintaxis fluidas" como las creadas por el método de encadenamiento, el uso del tiempo pasado haría que el código fuera menos legible. Por ejemplo, cuando se utiliza LINQ a través de C #, una cadena de método típica podría tener el siguiente aspecto:
dataSource.Sort().Take(10).Select(x => x.ToString);
Si se cambia al tiempo pasado, esto se volvería incómodo:
dataSource.Sorted().Taken(10).Selected(x => x.ToString);
Eso sí, dataSource.Sorted () tiene un significado más claro que dataSource.Sort (), porque las expresiones LINQ siempre crean una nueva enumeración sin afectar la fuente. Sin embargo, dado que somos plenamente conscientes de esto cuando usamos este paradigma, el uso del tiempo pasado es redundante y hace que la "fluidez" de leerlo sea incómoda sin una ganancia real.
Uso de propiedades versus métodos
Una cuestión clave que se menciona a continuación se refiere a las pautas de FxCop para el uso de métodos "Get" frente a las propiedades de solo lectura. Por ejemplo, la regla FxCop CA1024 .
Aunque no se menciona explícitamente en esa regla FxCop, el uso de los métodos "To" parecería aplicarse también a esta razón, ya que los métodos ToXXXXXX () son métodos de conversión. Y en el caso de ToArray (), el método es tanto un método de conversión como un método que devuelve una matriz.
Uso del tiempo pasado para propiedades booleanas
Algunos sugirieron que el tiempo pasado puede connotar un valor booleano, por ejemplo, una propiedad 'Éxito' o 'Conectado'. Creo que las siguientes réplicas que enfatizan el uso de un 'Is', 'Has' o 'Are' para propiedades y campos booleanos son correctas. El tiempo pasado también puede ayudar a este respecto, pero no tanto como usar un prefijo 'Is'. Siéntase libre de usar el tiempo pasado para las propiedades y campos booleanos, ayuda, pero creo que es aún más importante prefijar el nombre con 'Is', 'Has' o 'Are'.
Conclusiones generales
Para el tema de Tranpose () vs. Transposed (), creo que 'skizzy' lo hizo bien, sugiriendo que debería ser Transpose () para una acción mutante vs. GetTransposed () para un resultado no mutante. Esto lo hace 100% claro. Pero, de nuevo, creo que esto solo podría aplicarse para una clase mutuable, como una matriz.
Para las clases inmutables, especialmente donde podría usarse una sintaxis fluida de encadenamiento de métodos, entonces creo que esta sintaxis se volvería innecesariamente incómoda. Por ejemplo, compare:
var v = myObject.Transpose().Resize(3,5).Shift(2);
a:
var v = myObject.GetTransposed().GetResized(3,5).GetShifted(2);
Hmmm ... en realidad, incluso aquí parece dejar 100% claro que el resultado no afecta la fuente, pero no estoy seguro.
Supongo que para un paradigma como LINQ donde es bien conocido, el uso de "Get" y / o el tiempo pasado no es necesario, pero para una nueva API, puede tener algún valor, ¡al principio! Si la API contiene solo objetos inmutables, una vez que el usuario comprende esto, el uso de "Get" y / o el tiempo pasado solo reduce la legibilidad.
Así que creo que no hay respuestas fáciles aquí. ¡Supongo que uno debe pensar en la totalidad de su API y elegir con cuidado!
-- Miguel
Respuestas:
El tiempo pasado suena un poco incómodo. Creo que pretendías que la palabra fuera un adjetivo.
Aquí está mi sugerencia para el problema que solicitó: en lugar de
Transpose()
, llámeloGetTransposed()
. De esa manera, sabes que estás recibiendo algo y no estás modificando el objeto.fuente
Transpose()
, todavía se puede interpretar como el ajuste del objeto dado. Quizás esto debería ser una construcción del lenguaje. :)object.Transpose()
vsobject:Transpose()
.AsTransposed
lugar de losGetTransposed
casos en que las llamadas repetidas consecutivas, sin efectos secundarios, produzcan resultados semánticamente idénticos (que pueden o no ser el mismo objeto, pero no se puede mostrar que sean objetos diferentes sin usar cosas comoReferenceEquals
o el equivalente) .Tiene sentido de hecho.
Lo que estás hablando, en mi opinión, debe tomarse como una regla general al diseñar una API o una biblioteca. Solo entonces ofrecería un beneficio tangible si el sistema es consistente en todas las clases.
Otro problema es que, en muchos casos, a los usuarios de las interfaces no les importa cómo se logra el resultado.
¿Transponer () transpondrá el objeto actual? ¿Transpose () creará una nueva instancia transpuesta y le devolverá la referencia? ¿O tal vez se transponga una vez, guarde en caché los resultados en una copia y lo devuelva en llamadas posteriores sin afectar el objeto actual?
Los usuarios a menudo solo quieren obtener el resultado transpuesto, por lo que no muchos se preocuparán por la convención de nomenclatura que está proponiendo.
Pero por derecho propio, es una propuesta válida.
fuente
Estoy totalmente en desacuerdo. El tiempo pasado es incómodo y no se usa comúnmente (lo cual es razón suficiente en sí mismo para no preferirlo).
Si el método modificó el objeto sobre el que fue llamado, no debería volver a aparecer, esto deja en claro que modifica el objeto.
Del mismo modo, si el método no modifica el objeto sobre el que se llamó y en su lugar construye un nuevo objeto, el método devolverá un objeto del mismo tipo. Esta es una convención clara y ya común.
La firma del método es, en mi opinión, una convención más clara y mucho más comúnmente utilizada para indicar si el método devuelve un nuevo objeto o modifica a la persona que llama.
fuente
Suena razonable, y hay precedentes: Python tiene ambos
list.sort()
ysorted(seq)
. El primero es un método, el otro es una función que actúa en cualquier iterable y devuelve una lista.fuente
En la biblioteca de colecciones Scala, hay algunos métodos que están en tiempo pasado:
grouped
devuelve un iterador que itera sobre los elementos de una secuencia en fragmentos den
elementossorted
devuelve una versión ordenada de la colecciónupdated
devuelve una nueva versión de la colección con un elemento cambiadoSin embargo, no estoy seguro de si fue una decisión consciente o si simplemente se quedaron sin nombres, porque la biblioteca de colección de Scala es muy rica. Por ejemplo, también hay
groupBy
ysortBy
métodos, y elupdate
método es especial, porque el compilador reescribe la asignacióndentro
Las versiones anteriores de Scala sí se utilizaron
update
para colecciones inmutables, peroupdate
devolver una nueva versión en lugar de mutar es muy incómodo, porque obviamente debe asignar el valor de retorno a algo, por ejemplo, "actualizar" una entrada en un mapa inmutable sería algo me gustaAhora es
En un lenguaje con un buen sistema de tipos, los tipos generalmente le dirán si la rutina muta o no sus argumentos. En Haskell, por ejemplo, el tipo de versión inmutable sería algo así como
mientras que una versión mutable sería
fuente
Cuando veo un método / propiedad en el tiempo pasado, inmediatamente asumo que devuelve un valor booleano. Su propuesta puede tener sentido lógicamente, pero parece extraño e incómodo. Si tengo que explicarle a alguien por qué tiene sentido, probablemente no sea una buena convención.
fuente
No soy un gran admirador de los nombres de variables en tiempo pasado para la inmutabilidad: es una convención algo inusual y creo que causaría confusión, especialmente para aquellas personas que no son particularmente fuertes en la gramática inglesa (y solo estoy bromeando a medias allí...)
Además, estas convenciones eliminan la oportunidad de usar el tiempo pasado para denotar algo más que creo que es más importante: una descripción del estado del objeto descrito, por ejemplo, "elementos procesados" le dice claramente que los elementos de una colección ya han sido procesado, que es información lógica importante para transmitir.
Una mejor idea: hacer que todo sea inmutable . Entonces no necesitas ninguna distinción lingüística elegante. Sabes que quieres :-)
fuente