Tu Framework, tus reglas: Por qué uso Extends para todo

A continuación encontrarás traducido al castellano el artículo escrito por Gabriel Ludosanu y publicado originalmente en el Blog oficial de Xojo.

Durante el fin de semana estuve trabajando en un proyecto en el que se procesaba un volcado extenso correspondiente al logado de un servidor. Las String estaban por todas partes: las marcas de tiempo estaban incorrectas, los blob JSON corrompidos… Estuve escribiendo diversas llamadas de utilidad, anidando funciones en funciones… mi código se estaba convirtiendo en una pirámide de paréntesis.

Entonces recordé que existen los Extends.

Es una de esas características que permanecen silenciosas en el lenguaje. Pero una vez que haces la conexión cambia por completo la forma en la que piensas sobre el código de utilidades. Mediante el uso de Extends, y en poco más de veinte minutos, mi lío anidado se convirtió en algo más legible.

Métodos Extends en la práctica

Conoces la sensación. Estás escribiendo ParseLogEntry( rawLine ) por centésima vez y tienes la sensación de que algo no cuadra. La función funciona. Está en tu módulo de Utilidades (¿quizá parte de una Librería?); pero cada vez que la llamas hay una pequeña fricción. ¿Por qué la String no sabe cómo procesarse a sí misma en esa entrada del log? Eso es lo que soluciona Extends.

Te permite añadir nueva funcionalidad a clases ya existentes. Escribes un método en un módulo, etiquetas el primer parámetro con Extends y, de repente, String, DateTime, Dictionary (lo que necesites) se comporta como si siempre hubiese contado con ese método. No hay necesidad de crear subclases o clases adicionales; simplemente el Framework ampliado para que encaje con tus necesidades.

Leyendo el Código

El código se lee más veces de las que se escribe. Ya lo sabemos. Pero aun así escribimos código que se lee al revés.

// El viejo modo
Var result As DateTime = ExtractTimestamp(CleanLogEntry(rawLine))
 
// Con Extends
Var result As DateTime = rawLine.CleanLogEntry.ExtractTimestamp

Cuando estás depurando a las 2 de la madrugada, trazar la lógica a través de llamadas a funciones anidadas es lo último que deseas. Los métodos de extensión de clases convierte ese escaneo horizontal en un uno vertical.

Cuando Extends supone la mejor opción

No utilizo Extends para todo; no supone un reemplazo de la herencia o composición de clases. Pero hay momentos específicos en los que es exactamente lo más conveniente.

  • Los tipos incluidos que necesitan un método adicional. En el caso de mi procesador de logados, necesitaba extraer las marcas de tiempo, limpiar algunos caracteres y convertirlo a fechas ISO. Por tanto, extendí la clase String con mis utilidades personalizadas para que tuviese un aspecto más nativo.
  • Clases del Framework que no puedes modificar. No es posible crear subclases de todo, pero Extends puede funcionar con cosas como plugins de terceros o código heredado.
  • APIS que hubieses deseado. He perdido la cuenta de cuantas veces he querido una propiedad o método en una clase del framework que simplemente no existía. Extends me permite hacer justo eso.

Si buscas algunos ejemplos prácticos, como validación de emails, validación de URLs y ayudas de diccionario, consulta este artículo en el que se guía a través de implementaciones reales. Si quieres código que sólo tengas que copiar y pegar en tu proyecto, es un buen sitio por el que empezar.

Algunas cosas a tener en cuenta

  • Nil no perdona. Llama a una extensión sobre un objeto Nil y obtendrás una NilObjectException antes de que el método llegue a ejecutarse. La extensión está a la derecha del punto; y ese objeto ha de existir.
  • Sin sobrecargas. No puedes sustituir a métodos ya existentes. Si intentas crear una extensión con el mismo nombre de un método ya existente, el compilador utilizará el original. Es una buena cosa; significa que no podrás romper accidentalmente la funcionalidad del framework.
  • Sin propiedades. Las extensiones añaden comportamiento, no estado. Si necesitas almacenar datos, tendrás que utilizar una subclase o un wrapper.
  • Organización ante todo. Ubica las extensiones en módulos con nombre significativos como LogParsingExtensions o StringHelpers. Seis meses más tarde querrás saber de donde procede ese método .ExtractTimestamp.
  • Dependencias ocultas. Los métodos de extensión de clase están en los módulos y se comportan como métodos nativos, de modo que no siempre resulta obvio de qué clase o módulo depende. La elección y uso de buenos nombres ayuda.

Probando Extends

Si nunca antes has escrito un método de extensión de clase, dedícale cinco minutos. Añade un módulo a tu proyecto y crea un método como este:

Public Function ExtractFirstISODate(Extends source As String) As DateTime
  Var rx As New RegEx
  rx.SearchPattern = "(\d{4}-\d{2}-\d{2})[Tt]?(\d{2}:\d{2}:\d{2})"
  
  Var match As RegExMatch = rx.Search(source)
  If match <> Nil And match.SubExpressionCount > 1 Then
    Var datePart As String = match.SubExpressionString(1)
    Var timePart As String = match.SubExpressionString(2)
    Var isoString As String = datePart + " " + timePart
    
    Try
      Return DateTime.FromString(isoString)
    Catch err As RuntimeException
      Return Nil
    End Try
  End If
  Return Nil
End Function

Ahora, llama al método directamente sobre cualquier cadena:

Var logLine As String = "[2025-08-14T14:32:15] ERROR: Connection timeout"
 
Var timestamp As DateTime = logLine.ExtractFirstISODate
 
If timestamp <> Nil Then
  MessageBox("Found timestamp: " + timestamp.ToString)
Else
  MessageBox("No valid timestamp found")
End If

¡Eso es todo! No hay necesidad de utilizar clases utilitarias que debas de instanciar, ni nombres de módulos que recordar; simplemente stringVar.ExtractFirstISODate.

Para ver ejemplos más completos, comprueba la sección dedicada a los métodos de extensión de clase en la documentación de Xojo.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *