uqbar-project / wollok

Wollok Programming Language
GNU General Public License v3.0
60 stars 16 forks source link

Métodos abstractos deberían ser opcionales #1861

Open PalumboN opened 5 years ago

PalumboN commented 5 years ago

La falta de métodos abstractos ahora se marcan como ERROR: image

Pero con unos profes decíamos que debería ser WARN, ya que se puede ejecutar, y tendría el mismo nivel que NO marcar el método como override: image

Yyyyy, ya que estamos, para estos casos donde le envío un mensaje a self que no tiene el método, PERO que aparece en todas las subclases, podríamos agregar un quick fix para implementar el método abstracto directamente (y que sea la primera opción! :P).


También salió una propuesta de no necesitar los métodos abstractos y directamente marcar la clase como abstracta. Había un doc con eso, pero entre las cosas que me convencieron era que:

PalumboN commented 5 years ago

@lspigariol @asanzo

asanzo commented 5 years ago

HOLA TE QUIERO

Más allá de mi amor por el Rasta, me gustaría agregar que esta discusión se tuvo en algún momento y no recuerdo honestamente los pormenores. Busqué en las listas y en los issues pero no encontré. Lo que veo es que los abstract methods están acá hace rato, y yo siempre me sentí un poco incómodo.

Así que todo sí a este feature, salvo la pequeña aclaración de que el abstract también lo haría opcional.

Para mí los override method, los abstract class y los métodos abstractos son ejemplos de cosas que aclaramos en el código no porque no funcione de otra forma, sino porque nos interesa documentar. Podemos tener discusiones sobre qué de todo eso nos interesa documentar y cómo también, pero empezar por ponerlos opcional es cheto.

Pero es cierto que desde la perspectiva de un alumno ninguna de esas cosas son necesarias, y son boilerplate. Bah, salvo la honrosa excepción de los métodos abstractos, aman ponerlos en las superclases para documentar que todas abajo lo deben implementar. Lo ví mil veces, y aunque me molesta, veo el punto. Quieren una interfaz, tienen los tipos en la sangre.

Y si quieren puedo levelear la discusión a ¿Qué pasa con otra info como las interfaces? ¿No quiero también interfaces opcionales?

:bomb:

:running_man:

fdodino commented 5 years ago

Me gusta que se plantee la discusión, no tengo opiniones muy fuertes... los sigo. Esto tiene que hablarse para el ROADMAP 2020, porfi recuérdenmelo para el sábado.

fdodino commented 4 years ago

Definiciones

Validaciones

abstract class Ave {
  method vivirUnDia() {
    self.comer()
    self.volar()
  }

}

class Golondrina inherits Ave {
    method volar() { …}
    method comer() { …}
}
asanzo commented 4 years ago

Y qué va a pasar con todo el código viejo? Estalla, ¿verdad?. No me jode, pero antes que esto implementemos lo de poner la versión al root/package, así podemos hacer cosas inteligentes como las q mencionaba NicoS.

asanzo commented 4 years ago

Por cierto, les amé, me sientro ultra cómodo con esto que se decidió

nscarcella commented 3 years ago

Bueno, entro a comentar en esto traido por un comentario de @asanzo en la discusión de qué hacer con el override del initialize y otras yerbas. Me gustaría bajar a escrito algunas cosas que se discutieron que no encontré salvadas en ningún lado y de paso pensar un poco en voz alta:

De entrada, me gustaría que en estas decisiones no nos olvidemos de considerar a los Mixines, que no pueden instanciarse y pueden tener métodos abstractos y sobreescritos, y del sistema de tipos que, si no entiendo mal, se nutre de las definiciones de métodos abstractos. En principio nada de lo que se dijo choca con esto, pero hay algunas afirmaciones que pueden hacer un poco de ruido:

Poner la palabra abstract para hacer referencia al concepto (que hasta ahora no aparece en el lenguaje).

Poner la palabra abstract en la Clase pero no en el Mixin (porque no la vas a poner en el Mixin porque tendrías que ponerlo siempre) medio que trastorna un poco la idea de que la palabra materializa el concepto.

Que el concepto se centra en la clase, y los métodos abstractos quedan en segundo lugar. Podríamos tener clases abstractas sin métodos abstractos, simplemente porque el dominio conlleva a no querer instanciarla.

Para mi el concepto de clase abstracta tiene más sentido cuando no puedo instanciar la clase más que cuando elijo no instanciarla. No se me ocurre una buena razón para marcar una clase como "NO INSTANCIABLE" si ya tiene todo lo que le hace falta tener para funcionar, me suena al mismo tipo de capricho que marcar las clases como final y lleva a situaciones como tener "hojas" sin código porque "la superclase es para poner el código común". Meh... En todo caso, cuando te falta un método que necesitás no hay nada que hacer: esa clase tiene que ser abstracta te guste o no. Por eso yo creo que el peso de la abstractez (¿?) lo carga el método, no la clase.

Marcando la clase como abstracta, podríamos decir que cualquier mensaje a self (sin método asociado) en una clase abstracta es porque se referencia a un método abstracto, sin necesidad de escribirlo.

Este me parece el punto más interesante para rumiar. Por un lado te ahorra definir mensajes abstractos, pero por otro asume que nunca tipeas mal por accidente. No sé de que astucias es capaz el sistema de tipos acá pero estoy seguro de que si hacés opcional el método abstracto el alumno promedio al que el método abstracto ayudaría no lo va a escribir. No es ni bueno ni malo, pero habrá que aprender a vivir con ello.

Por otro lado está bueno notar que toda sintaxis para denotar que una clase o método es abstract u override le sirve solamente a los humanos. El compilador ya sabe si estás sobreescribiendo o si podés o no instanciar o llamar a un método. El punto, entiendo yo, es cuidar al programador de si mismo. Los errores que se pueden detectar con cada término son:

En fin, ninguno de estos casos me parece un aporte sustancioso. Vale hacer dos aclaraciones más:

La primera es que hacer estas keywords opcionales les quita, para mi, la poca utilidad que traen a la mesa. Si no te obligo a poner override no lo vas a poner, entonces no te va a servir para detectar nada. Si no te obligo, y además te pongo un warning, vas aprender a convivir con el amarillo y el override habrá hecho más daño que un bug.

La segunda es que, yo que soy un vago sin estudios, no comparto la idea de que una palabra clave es importante (o siquiera útil) para resaltar un concepto del lenguaje. De hecho, las palabras más importantes del paradigma son mensaje, polimorfismo, delegación y encapsulamiento y ninguna de ellas es una palabra clave en Wollok. Obviamente es importante que las palabras que sí son necesarias para la sintáxis sean elegidas con cuidado y representen correctamente la idea que hay atrás (el mejor ejemplo es que method > function), pero no creo que tener más palabras en la sintáxis sea mejor que tener menos. Cuanto más verbosa sea una definición más rápido se convierte en algo a lo que le pasan los ojos por encima sin leerlo.

Por eso mi propuesta sigue siendo que volemos a la mierda todas estas palabras clave y las reemplacemos con luces y colores en el IDE. Tenés un método que overridea otro? Flechita verde para arriba en el margen. Tenés un método overrideado? Flechita para abajo. Tenés un método abstracto? Te lo escribo en gris. Tenés una clase abstracta? Te la pinto de amarillo patito y te la subrayo con la palabra "abstracta" escrita en hebreo (esta podemos pensarla mejor).

El eclipse de java ya hacía todas estas cosas (y hasta te dejaba configurarlas), dan la misma información y alertas sin necesidad de ensuciar la sintáxis o agregar redundancias innecesarias y, más importante, no agregan más sintáxis que el alumno tiene que saber.

Tal vez el comentario kilométrico sugiere que estoy parado arriba de una mesa, gritando como un demente y flameando una bandera de Smalltalk, pero en realidad no tengo una postura fuerte sobre todo esto. Si deciden ir por el lado de las keywords no me opongo, pero llevo un rato largo tratando de empujar por mover complejidad de los lenguajes al IDE (de hecho, todo esto ya lo había planteado en Thin) y no quería dejar pasar la oportunidad de tirarlo de nuevo.

asanzo commented 3 years ago

¡¡Holaaaa!! (gran imagen la de Nico flameando la bandera de Smalltalk, yo creo que además debería aprovechar y tatuarse en la cabeza el globo del logo).

En el ejercicio de Dr House Enfermedad es una clase abstracta y no tiene ningún template method. Y no me sirve instanciarla aunque pueda, porque le faltan métodos que son necesarios para que sea usada polimórficamente por la Persona. Para que no se tengan que ir a leer el código, rápidamente un ejemplo mínimo:

class Persona {
    var enfermedades = []
    method viviUnDia() {
         enfermedades.forEach { enf => enf.rompeA(self) }
    }
}

class Enfermedad { // abstracta, pero no tiene métodos abstractos.
    var cantCelulas = 2000
    method estaActiva() = cantCelulas > 0
}

class Infecciosa inherits Enfermedad {
    method rompeA(persona) { persona.subiTemperatura(cantCelulas / 1000) } 
}

class Autoinmune inherits Enfermedad {
    method rompeA(persona) { persona.perdeCelulas(cantCelulas) }
}

Enfermedad es abstracta porque yo la concibo abstracta, como algo que es incompleto, que no me sirve para instanciar, que está ahí para no repetir código. En este caso sí querría la palabra abstract, porque el IDE no tiene forma de saber que en mi cabeza es abstracta. Lo que me molestaba en clase es que hablábamos de clases abstractas y de instanciación y no hablábamos de métodos abstractos, pero en Wollok no había clases abstractas y sí había métodos abstractos. Igual coincido en que es una distinción demasiado fina, y me tienta el modo simple Smalltalkero.

P.D.: Yo te levanto al hombro mientras flameás la bandera.

nscarcella commented 3 years ago

Respondo cosas que dijo @asanzo que me parecieron interesantes:

Entonces si detectamos problemas reales (onda varios dicen "che, a mí el abstract me parece central"), podemos no estar de acuerdo pero sí aceptar ponerlo opcional.

Absolutamente a favor de considerar una visión amplia de las necesidades de todos los docentes. Creo que lo que quiero marcar es que la opcionalidad, que puede parecer un punto medio conciliador, a veces no lo es tanto. Bah, habría que ver exactamente qué entendemos por opcionalidad, pero si un docente cree central la idea de identificar una clase como abstracta entonces hacerla opcional es medio pobre. O sea, si a mi me decís que vas a hacer opcional definir los atributos de los objetos (y que si accedés a un campo no definido lo creas dinámico, como en Ruby) te mando a la mierda. Ahora, si opcionalidad es que cada docente puede configurarlo como obligatorio si él quiere capaz es otra historia...

Me parece que la diferencia semántica entre method blah() y method blah(){} es grande, pero la diferencia sintáctica no lo es.

Sí, este es un punto excelente. Si no me queda otra que denotarlo en la sintaxis, entonces puedo comprar la idea de que el required puede resultar más fácil de ver en un lenguaje didáctico. Ahora, para un lenguaje para uso cotidiano no me gusta tanto, porque en la variante con required el método tampoco tiene cuerpo, con lo cual el required es redundante. No sé, a mi me gusta el minimalismo, pero respeto si no es la visión de todos.

Eso no quita que creo que pintarte la firma de un color y ponerle un badge es una forma mucho más capa de decirte "Eu! Mirá que este método lo tenés que implementar, eh?".

Me molesta tener que marcar con override las redefiniciones de un método abstracto (¡¡no estoy redefiniendo!!).

Je, comparto que la palabra sugiere otra cosa y se siente un poco rara. Si me permitís jugar al abogado del diablo, podría plantear que estás redefiniendo porque en tu superclase tiene una definición de ese método, sólo que no es concreta, pero veo como ese razonamiento puede tener gusto a poco.

Dejando la semiótica a un lado, yo creo, como dije arriba, que el valor del override está en declarar que tu definición debería matchear algo que viene de arriba, y eso permite alertarte cuando le pifias a un nombre y cuando pisas por accidente. Desde ese punto de vista es solamente cuestión de decidir de qué cosas querés proteger al programador. Si no te preocupa tanto que el pibe pifie escribiendo el nombre cuando está tratando de implementar un método abstracto entonces capaz no suma tanto.

Podría pasar que no tenés un template method, por lo tanto no necesitás un método abstracto, pero aún así tenés un método que forma parte de la interfaz.

No, bueno, acá tenemos una diferencia de definición. Tu visión de método abstracto parece derivar de las mécanicas del lenguaje (o sea, ponés un método abstracto cuándo lo tenés que definir porque sino no podés llamar a self). Mi opinión es que Enfermedad sí amerita tener un método abstracto rompeA(persona), no solo porque evita con mecánica que puedas instanciarla, sino porque obliga a que todas las enfermedades tengan que entender ese mensaje. Enfermedad ES abstracta; no porque no quieras instanciarla, sino porque una instancia de esa clase no podría cumplir con tu definición de lo que es una enfermedad.

En definitiva, el método abstracto atiende a esa necesidad que mencionas de que un mensaje esté en la interfaz de un tipo. Que Wollok no te obligue a definirlo es otra cosa, pero yo encuentro que es una buena práctica. Pero bueno, yo soy pro-tipado. Habrá quien difiera.

Esto me trae al tema de la interfaz. ¿Qué tanto los métodos abstractos son una forma de definir una interfaz y qué tanto son un requisito técnico del sistema de tipos? Que varies alumnes los usen como una forma de definir una interfaz me hace pensar que no es tan loco pensarlo así.

Claro, esto es lo que decía arriba: El método es la manera de materializar la interfaz y comprometerte por escrito a respetarla. Un Miixín con sólo métodos abstractos es absolutamente indistinguible de una interface de cualquier otro lenguaje. En mis clases yo uso mucho encarar un problema pensando a quién darle cuál responsabilidad antes de bajar a tierra los detalles, entonces sale mucho de poner métodos abstractos primero para tener a la vista a quién le vas a pedir qué cosa, y después el IDE solito te lleva a concretar esos métodos o definirlos en las subclases.

fdodino commented 3 years ago

Muy bueno el thread. Tenía algunas cosas que me quedé pensando pero lo que me preocupa respecto a la no obligatoriedad de escribir el método abstracto es lo siguiente:

class Abstracta {
  method zaraza() {
    self.internalZaraza()
    self.secondZaraza()
  }

  method secondZaraza() { ... implementación ... }
}

En este caso el validador te marcaría la llamada a internalZaraza() con error y te sugeriría como quick fixes:

  1. marcar la clase como abstracta
  2. marcar la clase como abstracta y generar el método abstracto
  3. generar el método (implementación vacía)

Ahora qué pasa si tenés

abstract class Abstracta {
  method zaraza() {
    self.internalZaraza()
    self.secondZaraza()
  }

  method secondZaraza() { ... implementación ... }
}

class Concreta inherits Abstracta {
   method otroMetodo() { ... implementación ... }
}

Esto va a tirar error en runtime y ya lo sabemos, entonces la clase Concreta debería implementar el método internalZaraza(). El tema es cómo puedo detectar qué métodos abstractos no está implementando:

Considerando que la propuesta dice que los métodos abstractos son opcionales, pienso ir por la opción del Rasta. No obstante, si hacemos que el IDE te genere el código para los métodos abstractos, quería ponerlo sobre la mesa. Entiendo que hay un IDE que puede hacer cosas por nosotros, el tema es que ser explícitos también ayuda al alumno a serlo (un punto que marcaba NicoS más arriba respecto a los métodos abstractos opcionales) y cuando tenés formatos que se salen del IDE (ej. imprimís el parcial para corregirlo en papel) eso también puede ayudar.

Respecto a la propuesta del override coincido con NIcoS en que marcarlo como opcional es empezar a transitar el camino del olvido...

npasserini commented 3 years ago

Bueno, se picó. Pucha, pensé que teníamos un acuerdo, ¿qué pasó?

En primer lugar habría que aclarar qué entendemos por opcional. Para mí opcional no puede ser marcarlo como warning en lugar de cómo error... eso da para toda otra charla pero en principio opcional sería que el IDE no se queje si no lo ponés. Bonus point si se puede configurar que sí de error... aunque para eso tenga sentido deberíamos poder tener un mecanismo para que une docente comparta su configuración con sus estudiantis.

En ese contexto, "ser amplio" implicaría permitir todas las variantes de clases abstractas? A saber:

Y nada de todo esto da error nunca, salvo el new de alguna clase que por algún criterio de los anteriores es abstracta. No sé, me da miedo que esa hiperflexibilidad hace que los errores no se detecten bien.

Ese lenguaje amplio, dejaría los controles a cargo del IDE, módulo que uno tenga una configuración de errores razonable... y que se pueda compartir. Si tenemos ese control de errores que está fuera del lenguaje, creo yo que es lo más moderno. Pero hay que tener ese mecanismo.


Por otro lado está la discusión de "qué es una clase abstracta", es decir, si es como dice Nico una clase que no se puede instanciar porque mecánicamente es imposible (porque le falta un pedazo) o si tiene sentido como herramienta conceptual. Croe que debemos darnos esa respuesta.


Más fácil me parece la discusión del required, porque esa yo sí la vi fallar. Es una cuestión bien técnica de la gramática del lenguaje, más que confusión de alumno por la sintaxis parecida => el que se confunde es el parser!!!! Obvio, si escribís bien el parser no se confunde, pero cuando escribís mal, el parser matchea tu método mal escrito con otra regla de la gramática y entonces en lugar de decirte "te olvidaste las llaves nabo" te dice "tu clase es abstracta" y además en la versión hiperlaxa smaltallkera, te lo dice en el lugar en que hacés new y es super confuso, no entendés por qué no la podés instanciar... y resulta que es porque te olvidaste un par de llaves.

Ese error yo lo vi muchas veces y por eso creo que es mandatorio modificar la sintaxis. El required jode poco y desambigua mucho.


Sobre el override yo tengo mis dudas, pero en tren de ser amplio ya acepté que lo hagamos opcional... es decir, si yo quiero lo escribo, si no lo escribo el compilador no se queja (con los bonus points por configurabilidad como decía arriba, pero el default es ignorar).

Si lo escribo obviamente se controla la existencia de la super clase.

Y obviamente más bonus points para las marquitas del IDE como decía NicoS.

Me parece que no vale la pena tener dos keywords distintos para cuando sobreescribo y cuando implemento un método abstracto... me parece una paja mental discutir que en realidad no estoy overrideando. El objetivo de la marca "override" es la misma en ambos casos, si querés no la pongas, si se te ocurre otra keyword mejor le damos, pero tener dos criterios distintos según si en la superclase el método es concreto o abstracto me parece mucho.

nscarcella commented 3 years ago

@fdodino

si los métodos abstractos no están definidos, tenemos dos opciones: recorrer la superclase en busca de llamadas a self, o la propuesta del Rasta de chequear que todas las subclases concretas implementen ese mensaje, que me parece más simple.

No entendí la segunda alternativa. ¿Cómo sabés qué mensaje tienen que implementar las subclases concretas si no está marcado como required y no buscás los envíos de mensaje a self?

@npasserini

Para mí opcional no puede ser marcarlo como warning en lugar de cómo error... Esto. El amarillo tiene que ser malo o no ser. Dónde empezas a entrenarlos para ignorar warnings se va todo a la mierda.

Por otro lado está la discusión de "qué es una clase abstracta", es decir, si es como dice Nico una clase que no se puede instanciar porque mecánicamente es imposible (porque le falta un pedazo) o si tiene sentido como herramienta conceptual. Croe que debemos darnos esa respuesta.

Mi propuesta concreta es que está bueno que cuando identificás que tu clase es conceptualmente abstracta la vuelvas mecánicamente abstracta, independientemente de si el lenguaje te obliga o no. Creo que se gana mucho y no cuesta tanto, pero bueno, eso va por el lado de tener los required obligatorios...

Obvio, si escribís bien el parser no se confunde, pero cuando escribís mal, el parser matchea tu método mal escrito con otra regla de la gramática y entonces en lugar de decirte "te olvidaste las llaves nabo" te dice "tu clase es abstracta" y además en la versión hiperlaxa smaltallkera, te lo dice en el lugar en que hacés new y es super confuso, no entendés por qué no la podés instanciar... y resulta que es porque te olvidaste un par de llaves.

asdasdasd a mi no me convence mucho este argumento. O sea, sí, ese error es una mierda, pero no es la única forma posible de reportarlo. Si en ese new que no te compila te pongo un error que dice "No podés instanciar esta clase porque es abstracta, porque el método XXX no tiene una implementación. No te habrás olvidado las llaves, no?" no te podés perder. Además, como vos decís: ¿Qué pasa si no pone el required? Qué le va a decir el error? "Se esperaba { o required ? No sé si eso hace que te pierdas menos. Y no es solamente que se olvidó las llaves: se olvidó todo el cuerpo del método! O estaba creando un método vacío, que no te digo que no pasa nunca pero es bastante infrecuente... Qué se yo? Para mi un pibe que no entiende lo que es una clase abstracta tampoco va a entender que tiene que escribir required.

De todos modos reitero que agregar el required no me jode si el corazón se los pide, pero no creo que vaya a causar un gran impacto.

Más me intriga el tema de la opcionalidad. Me gustaría escuchar los argumentos a favor de omitir los required methods. Mas allá de ahorrarte una o dos lineas no le veo ninguna ventaja y si varias complicaciones.

Lo mismo sobre marcar la clase como abstract. Si tiene métodos required no tenés alternativa. Ya me hiciste escribir el required, para qué querés que te diga también abstract. Si le faltan métodos pero no los pusiste como required porque te molesta, no te molesta también tener que poner abstract? Y si no le falta nada y la marcás como abstract para que no la instancien es de puro policía. Todo opcional y justo en eso te vas a poner policía? Qué se yo... Me hace ruido. Sobre todo la opcionalidad del overrides. Ponganse una mano en el corazón y diganme si creen que sus pibes usarían overrides si no fuera obligatorio...

Ahí es donde, para mi, volar la keyword y mostrar luces en el IDE le gana a opcionalidad. Yo te doy el feedback con colores SIEMPRE y vos no tenés que escribir nada. Entonces no dependo de tu cooperación para contarte lo que pasa. Mientras no te interese no le des bola, pero cuando hayas roto algo los colores van a estar ahí pero va a ser tarde para ponerte a escribir los overrides.

Mierda, estoy muy verborrágico. Les juro que con todo esto estoy re en plan "hagamos lo que más les guste", pero los extraño y lo canalizo mal.

fdodino commented 3 years ago

Bueno, solo vengo a contestar que

Fer decía: si los métodos abstractos no están definidos, tenemos dos opciones: recorrer la superclase en busca de llamadas a self, o la propuesta del Rasta de chequear que todas las subclases concretas implementen ese mensaje, que me parece más simple.

NicoS: No entendí la segunda alternativa. ¿Cómo sabés qué mensaje tienen que implementar las subclases concretas si no está marcado como required y no buscás los envíos de mensaje a self?

El tema de no escribir el método abstracto a mí me preocupa para cosas como ésta:

class A {
  method template() {
    self.operationA() // abstracto
    self.operationB()
  }

  method operationB() {}
}

class B inherits A {
   method operationC() {} // originalmente tenía un typo
}

es decir, cómo valido que operationA no está implementado en B. Una solución es que la validación se pare en envíos de mensajes del tipo self.operationA(), con lo cual se podría validar que

Esto para no tener que detectar los métodos abstractos haciendo un análisis del código. No se, en un par de días voy a armar la especificación de lo que escribí en este ticket más arriba, a mí tampoco me termina de convencer no escribir los métodos abstractos: por motivos didácticos porque les alumnes así bajan a tierra una decisión de diseño y porque eso facilita validar muchas más cosas.

Lo segundo que podemos hacer en febrero es retomar las reuniones para ayudar a consensuar esas especificaciones.

lspigariol commented 3 years ago

en febrero los leo y comento... aunque mi punto de vista sobre el tema ya está escrito por allí...

El mar, 19 de ene. de 2021 a la(s) 09:01, Fernando Dodino ( notifications@github.com) escribió:

Bueno, solo vengo a contestar que

Fer decía: si los métodos abstractos no están definidos, tenemos dos opciones: recorrer la superclase en busca de llamadas a self, o la propuesta del Rasta de chequear que todas las subclases concretas implementen ese mensaje, que me parece más simple.

NicoS: No entendí la segunda alternativa. ¿Cómo sabés qué mensaje tienen que implementar las subclases concretas si no está marcado como required y no buscás los envíos de mensaje a self?

El tema de no escribir el método abstracto a mí me preocupa para cosas como ésta:

class A {

method template() {

self.operationA() // abstracto

self.operationB()

}

method operationB() {}

}

class B inherits A {

override method operationC() {}

}

es decir, cómo valido que operationA no está implementado en B. Una solución es que la validación se pare en envíos de mensajes del tipo self.operationA(), con lo cual se podría validar que

  • el método exista
  • o la clase sea abstracta (y como chiche, que todas las subclases implementen ese nombre del método)

Esto para no tener que detectar los métodos abstractos haciendo un análisis del código. No se, en un par de días voy a armar la especificación de lo que escribí en este ticket más arriba, a mí tampoco me termina de convencer no escribir los métodos abstractos: por motivos didácticos porque les alumnes así bajan a tierra una decisión de diseño y porque eso facilita validar muchas más cosas.

Lo segundo que podemos hacer en febrero es retomar las reuniones para ayudar a consensuar esas especificaciones.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/uqbar-project/wollok/issues/1861#issuecomment-762797488, or unsubscribe https://github.com/notifications/unsubscribe-auth/ACZRXG2QUCN2P22JCCDN3KDS2VYAJANCNFSM4JGQZMZQ .

fdodino commented 3 years ago

TODO: Armar un documento donde especifiquemos la definición (basarnos en https://github.com/uqbar-project/wollok/issues/1861#issuecomment-674606998)

fdodino commented 3 years ago

Decidimos en la reunión de hoy