Quiero preguntar: estoy aprendiendo lentamente jQuery.
Lo que veo es un ejemplo exacto de un antipatrón de objeto de Dios . Básicamente, todo va a la $
función, sea lo que sea.
¿Estoy en lo cierto y es jQuery realmente un ejemplo de este antipatrón?
jquery
anti-patterns
Karel Bílek
fuente
fuente
$
función o unjQuery
objeto?Respuestas:
Para responder a esa pregunta, le haré una pregunta retórica sobre otra estructura que tiene una propiedad similar a los elementos DOM que manipula jQuery, ese es el viejo iterador. La pregunta es:
¿Cuántas operaciones necesitas en un iterador simple?
La pregunta se puede responder fácilmente mirando cualquier API Iterator en un idioma determinado. Necesitas 3 métodos:
Eso es todo lo que necesitas. Si puede realizar esas 3 operaciones, puede atravesar cualquier secuencia de elementos.
Pero eso no es solo lo que normalmente quieres hacer con una secuencia de elementos, ¿verdad? Usualmente tienes un objetivo de nivel mucho más alto que alcanzar. Es posible que desee hacer algo con cada elemento, puede que desee filtrarlos de acuerdo con alguna condición, o uno de varios otros métodos. Consulte la interfaz IEnumerable en la biblioteca LINQ en .NET para obtener más ejemplos.
¿Ves cuántos hay? Y eso es solo un subconjunto de todos los métodos que podrían haber puesto en la interfaz IEnumerable, porque generalmente los combinas para lograr objetivos aún más altos.
Pero aquí está el giro. Esos métodos no están en la interfaz IEnumerable. Son métodos de utilidad simples que realmente toman un IEnumerable como entrada y hacen algo con él. Entonces, si bien en el lenguaje C # parece que hay un gran número de métodos en la interfaz IEnumerable, IEnumerable no es un objeto divino.
Ahora de vuelta a jQuery. Hagamos esa pregunta nuevamente, esta vez con un elemento DOM.
¿Cuántas operaciones necesitas en un elemento DOM?
Nuevamente, la respuesta es bastante sencilla. Todos los métodos que necesita son métodos para leer / modificar los atributos y los elementos secundarios. Eso es todo. Todo lo demás es solo una combinación de esas operaciones básicas.
Pero, ¿cuánto material de nivel superior te gustaría hacer con elementos DOM? Bueno, igual que un iterador: un billón de cosas diferentes. Y ahí es donde entra jQuery. JQuery, en esencia, proporciona dos cosas:
Si saca la forma azucarada, se da cuenta de que jQuery podría haberse escrito fácilmente como un conjunto de funciones que seleccionan / modifican elementos DOM. Por ejemplo:
... podría haber sido escrito como:
Semánticamente es exactamente lo mismo. Sin embargo, la primera forma tiene la gran ventaja de que el orden de izquierda a derecha de las declaraciones sigue el orden en que se ejecutarán las operaciones. El segundo comienza en el medio, lo que hace que el código sea muy difícil de leer si combina muchas operaciones juntas.
Entonces, ¿qué significa todo ésto? Ese jQuery (como LINQ) no es el antipatrón del objeto de Dios. En cambio, se trata de un patrón muy respetado llamado Decorador .
Pero, de nuevo, ¿qué pasa con la anulación de
$
hacer todas esas cosas diferentes? Bueno, eso es solo azúcar sintáctico realmente. Todas las llamadas$
y sus derivados$.getJson()
son cosas completamente diferentes que simplemente comparten nombres similares para que pueda sentir de inmediato que pertenecen a jQuery.$
realiza una y solo una tarea: le permite tener un punto de partida fácilmente reconocible para usar jQuery. Y todos esos métodos que puede invocar en un objeto jQuery no son un síntoma de un objeto dios. Son simplemente funciones de utilidad diferentes que cada una realiza una única cosa en un elemento DOM pasado como argumento. La notación .dot solo está aquí porque facilita la escritura de código.fuente
No, la
$
función en realidad solo está sobrecargada para tres tareas . Todo lo demás son funciones secundarias que solo lo usan como un espacio de nombres .fuente
Math
. Como no hay un espacio de nombres incorporado en JS, solo usan un objeto para eso. ¿Aunque no estoy seguro de cuál sería la alternativa? ¿Poner todas las funciones y propiedades en el espacio de nombres global?La función principal de jQuery (p
$("div a")
. Ej. ) Es esencialmente un método de fábrica que devuelve una instancia del tipo jQuery que representa una colección de elementos DOM.Estas instancias del tipo jQuery tienen una gran cantidad de métodos de manipulación DOM disponibles que operan en los elementos DOM representados por la instancia. Si bien esto podría considerarse una clase que ha crecido demasiado, realmente no se ajusta al patrón del Objeto de Dios.
Finalmente, como menciona Michael Borgwardt, también hay una gran cantidad de funciones de utilidad que usan $ como espacio de nombres y solo están relacionadas tangencialmente con los objetos jQuery de la colección DOM.
fuente
$
No es un objeto, es un espacio de nombres.¿Llamarías a java.lang un objeto de dios debido a las muchas clases que contiene? Es una sintaxis absolutamente válida para llamar
java.lang.String.format(...)
, muy similar en forma a llamar a cualquier cosa en jQuery.Un objeto, para ser un objeto de dios, tiene que ser un objeto apropiado en primer lugar, que contenga tanto datos como inteligencia para actuar sobre los datos. jQuery solo contiene los métodos.
Otra forma de verlo: una buena medida de cuánto de un objeto de dios es un objeto es la cohesión; una cohesión más baja significa más de un objeto de dios. La cohesión dice que muchos de los datos son utilizados por cuántos de los métodos. Como no hay datos en jQuery, usted hace los cálculos: todos los métodos usan todos los datos, por lo que jQuery es muy coherente, por lo que no es un objeto divino.
fuente
Benjamin me pidió que aclarara mi posición, así que edité mi publicación anterior y agregué más pensamientos.
Bob Martin es autor de un gran libro titulado Clean Code. En ese libro hay un capítulo (Capítulo 6.) llamado Objetos y estructuras de datos, en el que analiza las diferencias más importantes entre objetos y estructuras de datos y afirma que tenemos que elegir entre ellos, porque mezclarlos es una muy mala idea.
Creo que DOM es un ejemplo de estos híbridos de estructura de datos y objetos. Por ejemplo, por DOM escribimos códigos como este:
El DOM debería ser claramente una estructura de datos en lugar de un híbrido.
El marco jQuery es un conjunto de procedimientos, que pueden seleccionar y modificar una colección de nodos DOM y hacer muchas otras cosas. Como Laurent señaló en su publicación, jQuery es algo así debajo del capó:
Los desarrolladores de jQuery fusionaron todos estos procedimientos en una sola clase, que es responsable de todas las características enumeradas anteriormente. Por lo tanto, viola claramente el Principio de responsabilidad única y, por lo tanto, es un objeto de Dios. Lo único porque no rompe nada, porque es una sola clase independiente que funciona en una sola estructura de datos (la colección de nodos DOM). Si añadiéramos subclases de jQuery u otra estructura de datos, el proyecto colapsaría muy rápido. Por lo tanto, no creo que podamos hablar de oo con jQuery, es más bien procesal que oo a pesar del hecho de que define una clase.
Lo que Laurent afirma es un completo disparate:
El patrón Decorador consiste en agregar nuevas funcionalidades manteniendo la interfaz y no modificando las clases existentes. Por ejemplo:
Puede definir 2 clases que implementan la misma interfaz, pero con una implementación completamente diferente:
Si tiene métodos que usan solo la interfaz común, puede definir uno o más Decoradores en lugar de copiar y pegar el mismo código entre A y B. Puede usar estos decoradores incluso en una estructura anidada.
Por lo tanto, puede sustituir las instancias originales con las instancias del decorador en un código de nivel de abstracción superior.
La conclusión de que jQuery no es un Decorador de nada, porque no implementa la misma interfaz que Array, NodeList o cualquier otro objeto DOM. Implementa su propia interfaz. Los módulos tampoco se usan como decoradores, simplemente anulan el prototipo original. Por lo tanto, el patrón Decorator no se usa en toda la biblioteca jQuery. La clase jQuery es simplemente un gran adaptador que nos permite usar la misma API por muchos navegadores diferentes. Desde el punto de vista de la perspectiva, es un completo desastre, pero eso no importa, funciona bien y lo usamos.
fuente