¿Puede una función ser demasiado corta?

125

Cada vez que me encuentro escribiendo la misma lógica más de una vez, generalmente la incluyo en una función, por lo que solo hay un lugar en mi aplicación para mantener esa lógica. Un efecto secundario es que a veces termino con una o dos funciones de línea como:

function conditionMet(){
   return x == condition;
}

O

function runCallback(callback){
   if($.isFunction(callback))
     callback();
}

¿Es esto perezoso o una mala práctica? Solo pregunto porque esto da como resultado una mayor cantidad de llamadas a funciones para piezas muy pequeñas de lógica.

Mark Brown
fuente
3
No, no muy corto. En C #, haría 'condición cumplida' como una propiedad, que es elegante, y consideraría usarla Assert.AreEqual<int>(expected, actual, message, arg1, arg2, arg3, ...);. El segundo está bien como está. Potencialmente incluiría una bandera de bool opcional que dictaría si lanzar una excepción / etc. en caso de que la devolución de llamada no sea una función.
Trabajo
38
Sí, solo en un caso: function myFunction () {}
Spooks
55
def yes(): return 'yes'
dietbuddha
3
@Spooks: estoy dividiendo pelos aquí, pero las funciones vacías son válidas para al menos clases de adaptadores, por ejemplo, MouseMotionAdapter en download.oracle.com/javase/6/docs/api/java/awt/event/… . Por supuesto, esta es solo una forma de evitar las limitaciones del idioma.
Aleksi Yrttiaho
3
@dietbuddha: Los requisitos acaban de cambiar, ahora tiene que admitir dos idiomas para una demostración la próxima semana. El tipo que escribió "def yes ()" se sintió muy contento de haberlo hecho antes de cambiarlo a "def yes (: (IsFrench ()? 'Oui': 'Yes')"
Andrew Shepherd

Respuestas:

167

Jeje, señor Brown, si pudiera persuadir a todos los desarrolladores que conozco para que mantengan sus funciones tan pequeñas como esta, créanme, ¡el mundo del software sería un lugar mejor!

1) La legibilidad de su código aumenta diez veces.

2) Tan fácil de entender el proceso de su código debido a la legibilidad.

3) SECO - No te repitas - ¡Te estás ajustando muy bien a esto!

4) comprobable. Las funciones diminutas son un millón de veces más fáciles de probar que los métodos de 200 líneas que vemos con demasiada frecuencia.

Ah, y no te preocupes por el "salto de funciones" en términos de rendimiento. Las compilaciones "Release" y las optimizaciones del compilador se encargan de esto muy bien, y el rendimiento es el 99% del tiempo en algún otro lugar del diseño de sistemas.

¿Es esto perezoso? - Muy al contrario!

¿Es esta una mala práctica? - Absolutamente no. Es mejor utilizar esta forma de hacer métodos que las bolas de alquitrán o los "Objetos de Dios" que son tan comunes.

Sigan con el buen trabajo, mi compañero artesano;)

Martin Blore
fuente
40
No estás respondiendo la pregunta, solo estás predicando la regla cuyas aplicaciones más extremas se cuestionan aquí.
44
No es muy frecuente que encuentre frustrante la limitación de solo 1 voto a favor. Pero, para esta respuesta, +1 no parece hacerle justicia.
Bevan
44
+5 ... oh, solo puedo hacer +1, ¡bueno! Y para apoyar MeshMan, sugiero el siguiente libro de Robert C. Martin Clean code . Este libro realmente está cambiando la forma en que ahora programo.
Eric-Karl
10
Respuesta muy agradable, pero no estoy de acuerdo con la mayoría: 1) Las funciones extremadamente pequeñas dan como resultado más código en general, debido a todas las tuberías necesarias para cada función. Esto puede reducir la legibilidad, especialmente para un proyecto realmente grande. Además, depende del idioma. 2) Depende completamente del punto 1 y, por lo tanto, no tiene nada que ver con la pregunta. 3) ¿Qué? runCallback repite "callback" cuatro veces, y tres veces se refiere a la misma variable para ejecutar una sola función. 4) Los métodos de más de 200 líneas, por supuesto, no son verificables, pero hay un largo camino desde eso hasta una línea.
l0b0
10
-1: Lo más aterrador aquí es el número de votos positivos dados a esta respuesta.
Luca
64

Diría que un método refactorizado es demasiado corto si:

  • Duplica una operación primitiva, con el único propósito de convertirlo en un método:

Ex:

boolean isNotValue() {
   return !isValue();
}

o...

  • El código solo se usa una vez, y su intención es fácil de entender de un vistazo.

Ex:

void showDialog() {
    Dialog singleUseDialog = new ModalDialog();
    configureDialog(singleUseDialog);
    singleUseDialog.show();
}

void configureDialog(Dialog singleUseDialog) {
    singleUseDialog.setDimensions(400, 300);
}

Este podría ser un patrón válido, pero simplemente alinearía el método configureDialog (), en este ejemplo, a menos que tuviera la intención de anularlo o reutilizar este código en otro lugar.

RMorrisey
fuente
77
Separar un método de una sola línea en el segundo caso puede ser beneficioso para mantener el nivel de abstracción de los métodos de llamada consistente. El ejemplo proporcionado está en la cerca si se usa este razonamiento: ¿el ancho y la altura exactos del píxel son demasiados detalles para mostrar un diálogo?
Aleksi Yrttiaho
2
El método "isNotValue ()" tiene un nombre incorrecto y se debe refactorizar para nombrar la pregunta de dominio real.
44
@ Aleksi: no estoy de acuerdo; los detalles ya están ocultos dentro del método showDialog () en este ejemplo; no hay necesidad de refactorizarlo dos veces. El ejemplo pretende mostrar un caso de uso aislado; Si se necesita un patrón con diferentes configuraciones de diálogo en diferentes casos, tendría sentido volver y refactorizar una vez que se establece el patrón.
RMorrisey
1
@Thorbjorn: Podría ver un caso para ello, cuando responde una pregunta de dominio comercial cuya lógica podría no ser obvia. Solo estoy señalando que hay -algunos- casos en los que es excesivo.
RMorrisey
3
Tal vez esto sea un poco curioso, pero diría que en sus ejemplos el problema no es que la función sea demasiado corta, sino que no agregan valor descriptivo.
keppla
59

¿Puede una función ser demasiado corta? En general no.

De hecho, la única forma de garantizar que:

  1. Has encontrado todas las clases en tu diseño
  2. Sus funciones solo están haciendo una cosa.

Es mantener sus funciones lo más pequeñas posible. O, en otras palabras, extraiga funciones de sus funciones hasta que no pueda extraer más. Yo llamo a esto "Extraer hasta que te caigas".

Para explicar esto: Una función es un ámbito con fragmentos de funcionalidad que se comunican por variables. Una clase también es un ámbito con trozos de funcionalidad que se comunican por variables. Por lo tanto, una función larga siempre se puede reemplazar por una o más clases con un método pequeño.

Además, una función que es lo suficientemente grande como para permitirle extraer otra función de ella, está haciendo más de una cosa por definición . Entonces, si puede extraer una función de otra, debe extraer esa función.

Algunas personas temen que esto conduzca a una proliferación de funciones. Tienen razón Va a. Eso es realmente algo bueno. Es bueno porque las funciones tienen nombres. Si tiene cuidado al elegir buenos nombres, entonces estas funciones actúan como publicaciones de signos que dirigen a otras personas a través de su código. De hecho, las funciones bien nombradas dentro de clases bien nombradas dentro de espacios de nombres bien nombrados son una de las mejores formas de asegurarse de que sus lectores NO se pierdan.

Hay mucho más sobre esto en el Episodio III de Clean Code en cleancoders.com

Tío Bob.
fuente
55
¡Tío Bob! Es bueno verte a bordo aquí. Como era de esperar, un consejo fantástico. Nunca he escuchado el término "Extraer hasta que se caiga" antes y seguramente usaré este término en la oficina el lunes;).
Martin Blore
1
¿Estaría dispuesto a elaborar su punto # 1? Explicar que con el ejemplo sería genial.
Daniel Kaplan
53

Wow, la mayoría de estas respuestas no son de mucha ayuda.

No debe escribirse ninguna función cuya identidad sea su definición . Es decir, si el nombre de la función es simplemente el bloque de código de la función escrito en inglés, entonces no lo escriba como una función.

Considera tu función conditionMety esta otra función, addOne(perdóname por mi JavaScript oxidado):

function conditionMet() { return x == condition; }

function addOne(x) { return x + 1; }

conditionMetes una definición conceptual adecuada; addOneEs una tautología . conditionMetes bueno porque no sabes lo que conditionMetimplica simplemente diciendo "condición cumplida", pero puedes ver por qué addOnees tonto si lo lees en inglés:

"For the condition to be met is for x to equal condition" <-- explanatory! meaningful! useful!

"To add one to x is to take x and add one." <-- wtf!

Por amor a cualquier cosa que pueda ser sagrada, por favor, ¡no escribas funciones tautológicas!

(¡Y por la misma razón, no escriba comentarios para cada línea de código !)

Rei Miyasaka
fuente
Algunas de las construcciones de lenguaje más complejas pueden ser desconocidas o difíciles de leer, lo que hace que este sea un truco útil.
3
De acuerdo, lo que exactamente se debe convertir en una función dependerá en gran medida del idioma en el que se está escribiendo. Una función como addOne sería útil si estuviera en un lenguaje como VHDL, donde en realidad está definiendo el significado de agregar uno en un nivel de teoría binaria o numérica. Me gustaría pensar que ningún lenguaje es tan críptico que sea difícil de leer incluso para programadores experimentados (tal vez brainf # ck), pero si ese es el caso, la misma idea sería válida ya que la función es efectivamente una traducción del inglés a ese idioma, por lo que el nombre no es el mismo que la definición.
Rei Miyasaka
1
Estoy hablando de cosas función de la identidad de la librería estándar de Haskell - Creo que no se puede obtener más "tautológico", entonces eso :)
hugomg
1
@missingno Bah, eso es trampa: D
Rei Miyasaka
55
Si nombra las funciones por su propósito en lugar de por su contenido, inmediatamente dejarán de ser tontas. Por lo tanto, sus ejemplos pueden ser, por ejemplo, ser function nametoolong() { return name.size > 15; }o function successorIndex(x) { return x + 1; } Entonces, el problema con sus funciones es en realidad que su nombre es malo.
Hans-Peter Störr
14

Diría que si cree que la intención de algún código puede mejorarse agregando un comentario, en lugar de agregar ese comentario, extraiga el código en su propio método. No importa cuán pequeño sea el código.

Entonces, por ejemplo, si su código se vería así:

if x == 1 { ... } // is pixel on?

haz que se vea así en su lugar:

if pixelOn() { ... }

con

function pixelOn() { return x == 1; }

O, en otras palabras, no se trata de la longitud del método, sino del código autodocumentado.

Julio
fuente
55
Mi estimado colega señala que también podrías escribir if x == PIXEL_ON. Usar una constante puede ser tan descriptivo como usar un método, y es un poco más breve.
Tom Anderson
7

Creo que esto es exactamente lo que quieres hacer. En este momento, esa función podría ser solo una o dos líneas, pero con el tiempo podría crecer. También tener más llamadas a funciones le permite leer las llamadas a funciones y comprender lo que está sucediendo allí. Esto hace que su código sea muy SECO (no se repita), lo cual es mucho más fácil de mantener.

mpenrow
fuente
44
Entonces, ¿qué hay de malo en descifrarlo más tarde, cuando puedes demostrar que lo necesitas, en lugar de ahora, cuando es solo peso muerto?
dsimcha 02 de
Las funciones no crecen solas. En mi humilde opinión los ejemplos son pésimos. conditionMetes un nombre demasiado genérico y no toma argumentos, por lo que prueba algún estado? (x == xCondition) en la mayoría de los idiomas y situaciones es tan expresivo como 'xConditition'.
usuario desconocido
Sí, ¿y por eso quieres tener más del 75% de sobrecarga en tu código? El revestimiento de la chapa escrito como 3 líneas es en realidad 300%
Codificador
5

Estoy de acuerdo con todas las otras publicaciones que he visto. Este es un buen estilo.

La sobrecarga de un método tan pequeño puede ser nula, ya que el optimizador puede optimizar la llamada y alinear el código. Un código simple como este permite al optimizador hacer su mejor trabajo.

El código debe estar escrito para mayor claridad y simplicidad. Intento limitar un método a uno de dos roles: tomar decisiones; o realizando trabajos. Esto puede generar métodos de una línea. Cuanto mejor estoy haciendo esto, mejor encuentro mi código.

Un código como este tiende a tener alta cohesión y bajo acoplamiento, lo cual es una buena práctica de codificación.

EDITAR: una nota sobre los nombres de los métodos. Use un nombre de método que indique lo que el método no hace y cómo lo hace. Encuentro que verb_noun (_modifier) ​​es un buen esquema de nombres. Esto da nombres como Find_Customer_ByName en lugar de Select_Customer_Using_NameIdx. El segundo caso tiende a ser incorrecto cuando se modifica el método. En el primer caso, puede intercambiar toda la implementación de la base de datos del Cliente.

BillThor
fuente
+1 por mencionar la alineación, imo la consideración principal en rendimiento y funciones cortas.
Garet Claborn
4

Refactorizar una línea de código en una función parece excesivo. Puede haber casos excepcionales, como ver muuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu como por ver líneas o expresiones muy complejas, no haría esto a menos que sepa que la función crecerá en el futuro.

y su primer ejemplo sugiere el uso de globales (que pueden o no hablar de otros problemas en el código), lo refactorizaría aún más y convertiría esas dos variables como parámetros:

function conditionMet(x, condition){
   return x == condition;
}
....
conditionMet(1,(3-2));
conditionMet("abc","abc");

El conditionMetejemplo podría ser útil si la condición era larga y repetitiva, como por ejemplo:

function conditionMet(x, someObject){
   return x == ((someObject.valA + someObject.valB - 15.4) / /*...whole bunch of other stuff...*/);
}
FrustratedWithFormsDesigner
fuente
1
Su primer ejemplo no insinúa los globales. En todo caso, es un método cohesivo en una clase altamente cohesiva donde la mayoría de las variables están en el objeto.
Martin Blore
77
Esa conditionMetfunción es solo un ==operador detallado . Eso probablemente no sea útil.
1
Definitivamente no uso globals. @MeshMan, de ahí es exactamente el ejemplo ... un método en una clase.
Mark Brown
1
@ Marcos Brown: @MeshMan: Ok, supongo que el ejemplo de código es demasiado vaga para saber con seguridad ...
FrustratedWithFormsDesigner
Estoy oliendo un conditionMet (x, relation condition) {aquí, donde pasas x, '==' y relación. Entonces no necesita repetir el código para '<', '>', '<=', '! =' Y así sucesivamente. Por otro lado, la mayoría de los idiomas tienen estas construcciones incorporadas a medida que los operadores (condición x ==) hacen exactamente eso. Las funciones para las declaraciones atómicas están un paso demasiado lejos.
Usuario desconocido
3

Considera esto:

Una simple función de detección de colisión:

bool collide(OBJ a, OBJ b)
{
    return(pow(a.x - b.x, 2) + pow(a.y - b.y, 2) <= pow(a.radius + b.radius, 2));
}

Si escribiste ese delineador "simple" en tu código todo el tiempo, eventualmente podrías cometer un error. Además, sería realmente tortuoso escribir eso una y otra vez.

muntoo
fuente
Si estamos tratando con C aquí, podríamos abusar #define;)
Cole Johnson
Incluso puede que desee intercambiar esto para el más lento, pero a prueba de desbordamiento hypot si sus tamaños o distancias son muy grandes. Esto es, obviamente, mucho más fácil de hacer una vez.
Matt Krause,
2

No, y eso rara vez es un problema. Ahora, si alguien siente que ninguna función debería ser más larga que una línea de código (si tan solo pudiera ser así de simple), eso sería un problema y de alguna manera perezoso porque no está pensando en lo que es apropiado.

JeffO
fuente
No lo contaría en líneas de código, sino en expresiones. "(x == condición)" es atómico, por lo que lo pondría solo en un método / función, si se usa varias veces Y podría modificarse, function isAdult () = { age >= 18; }pero seguramente no isAtLeast18.
usuario desconocido
2

Diría que son demasiado cortos, pero esta es mi opinión subjetiva.

Porque:

  • No hay razón para crear una función si se usa solo una o dos veces. Saltar a defs apesta. Especialmente con código VS y C ++ increíblemente rápido.
  • Resumen de clase. Cuando tienes miles de pequeñas funciones, me enoja. Disfruto cuando puedo ver las definiciones de clase y ver rápidamente lo que hace, no cómo SetXToOne, SetYToVector3, MultiplyNumbers, + 100 setters / getters.
  • En la mayoría de los proyectos, estos ayudantes se convierten en peso muerto después de una o dos fases de refactorización, y luego "busca todo" -> eliminar para deshacerse del código obsoleto, generalmente ~ 25% + de él.

Las funciones que son largas son malas, pero las funciones que son más cortas que 3 líneas y realizan solo 1 cosa son igualmente malas en mi humilde opinión.

Entonces diría que solo escriba una función pequeña si es:

  • 3+ líneas de código
  • Hace cosas que los desarrolladores junior podrían perderse (no sé)
  • Hace validación extra
  • Se usa, o se usará al menos 3 veces
  • Simplifica la interfaz de uso frecuente.
  • No se convertirá en un peso muerto durante la próxima refactorización
  • Tiene algún significado especial, por ejemplo, especialización de plantilla o algo
  • Hace algún trabajo de aislamiento: referencias constantes, afecta a parámetros mutables, realiza la recuperación de miembros privados

Apuesto a que el próximo desarrollador (senior) tendrá mejores cosas que hacer que recordar todas sus funciones SetXToOne. Entonces se convertirán en peso muerto muy pronto de cualquier manera.

Descifrador
fuente
1

No me gusta el ejemplo no. 1, por el nombre genérico i.

conditionMetno parece ser genérico, por lo que representa una condición específica? Me gusta

isAdult () = { 
  age >= 18 
}

Esto estaría bien Es una diferencia semántica, mientras que

isAtLeast18 () { age >= 18; } 

No estaría bien para mí.

Tal vez se usa con frecuencia y puede estar sujeto a cambios posteriores:

getPreferredIcecream () { return List ("banana", "choclate", "vanilla", "walnut") }

está bien también Si lo usa varias veces, solo necesita cambiar un solo lugar, si es necesario, tal vez la crema batida sea posible mañana.

isXYZ (Foo foo) { foo.x > 15 && foo.y < foo.x * 2 }

no es atómico y debería darle una buena oportunidad de prueba.

Si necesita pasar una función, por supuesto, pase lo que quiera y escriba funciones que parezcan tontas.

Pero en general, veo muchas más funciones, que son demasiado largas, que funciones que son demasiado cortas.

Una última palabra: algunas funciones solo parecen apropiadas, porque están escritas demasiado detalladas:

function lessThan (a, b) {
  if (a < b) return true else return false; 
}

Si ves, es lo mismo que

return (a < b); 

no tendrás problemas con

localLessThan = (a < b); 

en lugar de

localLessThan = lessThan (a, b); 
usuario desconocido
fuente
0

¡No hay código como ningún código!

Hazlo simple y no compliques demasiado las cosas.

¡No es ser perezoso, está haciendo tu trabajo!

RDL
fuente
0

Sí, está bien tener una función de código corto. En el caso de métodos como "getters", "setters", "accesors" es muy común, como se mencionó en las respuestas anteriores.

A veces, esas funciones cortas de "accesores" son virtuales, porque cuando se reemplazan en subclases las funciones tendrán más código.

Si desea que su función no sea tan breve, bueno, en muchas funciones, ya sean globales o métodos, generalmente uso una variable de "resultado" (estilo pascal) en lugar de un retorno directo, es muy útil cuando utilizo un depurador.

function int CalculateSomething() {
  int Result = -1;

   // more code, maybe, maybe not

  return Result;
}
umlcat
fuente
0

Demasiado corto nunca es un problema. Algunas razones para las funciones cortas son:

Reusabilidad

Por ejemplo, si tiene una función, como un método establecido, puede afirmarla para asegurarse de que los parámetros son válidos. Esta comprobación debe realizarse en todas partes donde se establezca la variable.

Mantenibilidad

Puede usar alguna declaración que piense que en el futuro puede cambiar. Por ejemplo, ahora muestra un símbolo en una columna, pero más tarde eso podría cambiar a otra cosa (o incluso un pitido).

Uniformidad

Está utilizando, por ejemplo, el patrón de fachada y lo único que hace una función es pasar exactamente la función a otra sin cambiar los argumentos.

Michel Keijzers
fuente
0

Cuando le da un nombre a una sección de código, es esencialmente para darle un nombre . Esto puede ser por varias razones, pero el punto crucial es si puede darle un nombre significativo que se agregue a su programa. Nombres como "addOneToCounter" no agregarían nada, pero lo conditionMet()harían.

Si necesita una regla para averiguar si el fragmento es demasiado corto o demasiado largo, considere cuánto tiempo le lleva encontrar un nombre significativo para el fragmento. Si no puede hacerlo dentro de un período de tiempo razonable, entonces el fragmento no tiene un tamaño adecuado.

usuario1249
fuente
0

No, pero puede ser demasiado conciso.

Recuerde: el código se escribe una vez, pero se lee muchas veces.

No escriba código para el compilador. Escríbalo para futuros desarrolladores que tendrán que mantener su código.

Jim G.
fuente
-1

Sí, querida, la función podría ser cada vez más pequeña y si es buena o mala depende del idioma / marco que esté utilizando.

En mi opinión, trabajo principalmente en tecnologías front-end, las funciones pequeñas se usan principalmente como funciones auxiliares, seguramente las usará mucho cuando trabaje con filtros pequeños y use la misma lógica en su aplicación. Si su aplicación tiene demasiada lógica común, habrá muchas funciones pequeñas.

Pero en una aplicación donde no tiene una lógica común, no estará obligado a realizar pequeñas funciones, pero puede dividir su código en segmentos donde le resulte fácil de administrar y comprender.

En general, dividir su gran código en una función pequeña es un enfoque muy bueno. En marcos e idiomas modernos, seguramente lo hará, p. Ej.

data => initScroll(data)

es una función anónima en ES 2017 JavaScript y mecanografiado

getMarketSegments() {
 this.marketService.getAllSegments(this.project.id)
  .subscribe(data => this.segments = data, error => console.log(error.toString()));
}

en el código anterior puede ver 3 declaraciones de funciones y 2 llamadas a funciones, esta es una simple llamada de servicio en Angular 4 con Typecript. Puedes considerarlo como tus requisitos

([] 0)
([x] 1)
([x y] 2)

Las anteriores son 3 funciones anónimas en lenguaje clojure

(def hello (fn [] "Hello world"))

La anterior es una declaración funcional en clojure

Entonces sí, las FUNCIONES pueden ser más pequeñas pero si es bueno o malo si tiene funciones como:

incrementNumber(numb) { return ++numb; }

Bueno, no es una buena práctica hacerlo, pero ¿qué pasa si está usando esta función en una etiqueta HTML como lo hacemos en Angular Framework si no hubiera soporte para Incremento o Disminución en Plantillas Angulares de HTML? Entonces esta habría sido la solución para yo.

Tomemos otro ejemplo

insertInArray(array, newKey) {
 if (!array.includes(newKey)) {
   array.push(newKey);
 }
}

El ejemplo anterior es imprescindible cuando se juega cuando las matrices dentro de Plantillas HTML Angulares. Entonces a veces tendrás que crear pequeñas funciones

Anwaar Ulhaq
fuente
-2

No estoy de acuerdo con casi la respuesta dada en este momento.

Recientemente encontré un colega que escribe a todos los miembros de la clase de la siguiente manera:

 void setProperty(int value){ mValue=value; }
 int getProperty() const { return (mValue); }

Este podría ser un buen código en casos esporádicos, pero seguramente no si define muchas clases que tienen muchas y muchas propiedades. No quiero decir, con esto, que los métodos como los anteriores no se escribirán. Pero, si termina escribiendo la mayor parte del código como "envoltorio" de la lógica real, hay algo mal.

Probablemente, el programador pierde la lógica general, teme los cambios futuros y la refactorización del código.

La definición de la interfaz se debe a una necesidad real; de hecho, si necesita establecer y obtener una propiedad simple (sin mucha lógica, lo que hace que el miembro sea más corto), será posible. Pero, si la necesidad real podría analizarse de una manera diferente, ¿por qué no definir una interfaz más intuitiva?

Para responder realmente a la pregunta, por supuesto que no, y la razón es muy obvia: el método / propiedad / whatelse se definirá para lo que necesita. Incluso una función virtual vacía tiene una razón para existir.

Luca
fuente
66
Hay una buena razón para agregar métodos de acceso / mutadores, que insinúa bajo "miedo al futuro ... refactorización". Pero también tiene razón en que no agrega valor al código. Ni reduciendo el tamaño (local o globalmente) ni aumentando la legibilidad. En mi opinión, esto habla de un diseño de lenguaje deficiente tanto en Java como en la convención JavaBeans. Esta es un área (de muchas) donde C # mejoró con éxito el lenguaje para abordar ambas preocupaciones con la sintaxis de propiedad automática . Como programador de Java, estoy de acuerdo con su estilo sin formato para las clases básicas de estructura.
Anm 01 de
1
Las funciones getter / setter son buenas incluso si todo lo que hacen ahora es leer o escribir una variable. Como cuestión práctica, puede imaginar un escenario en el que más tarde decide imprimir un valor en la pantalla cada vez que cambia el campo, o verificar si ese valor es válido o no. (Tal vez es un denominador para una fracción, y desea verificar para asegurarse de que no sea cero.)
Rei Miyasaka
2
getters y setters son horribles, a pesar de su uso válido. Si es necesario usarlos, considero que es una falla del lenguaje.
Carson Myers
@Rei: ¿por qué una clase externa necesitaría verificar el valor de los denominadores? Eso debería hacerse mediante la función divide () de la clase Fraction o la clase Fraction debería proporcionar un isDivisible () para verificar los denominadores nulos. Necesitar captadores / establecedores generalmente es un olor a código que su clase tiene un alto acoplamiento y / o baja cohesión (es decir, malo).
Lie Ryan
@Lie ¿Qué? Nunca dije que se debería usar una clase externa para verificar los denominadores. Estoy diciendo que una clase externa podría establecer un denominador en 0 por accidente. El propósito de que se realicen verificaciones de validez en los instaladores es alentar cualquier error en el código del consumidor que se encuentre antes. Proporcionar una función isDivisible () a la que se pueda llamar o no también no funciona para ese fin. ¿Y cómo exactamente la necesidad de getters / setters indica que hay un alto acoplamiento?
Rei Miyasaka