sql >> Base de Datos >  >> RDS >> Access

Creación de dependencias opcionales

En mi artículo de ayer, introduje el concepto de "Tren de la Dependencia". Eso es lo que sucede cuando importa una función de su biblioteca de código, pero termina teniendo que importar varios módulos adicionales solo para satisfacer todas las dependencias. Te queda todo un "tren" de módulos de código cuando todo lo que necesitabas era un único "asiento" (función).

Terminas en esta situación cuando tus módulos están estrechamente acoplados. Entonces, ¿qué puede hacer usted al respecto? Hay algunas formas de manejar esta situación.

Viola "no te repitas"

Una forma de preservar el acoplamiento débil, lo que da como resultado más módulos "independientes", es crear copias privadas de las funciones del módulo de origen en el módulo de llamada. Esto elimina la dependencia entre los dos módulos, pero da como resultado un código repetitivo.

El concepto es simple. Copie la función de su módulo de código principal. Luego, péguelo en el módulo de llamada, pero márquelo como privado para evitar ambigüedades.

Esto tiene sentido en las siguientes situaciones:

  • Métodos simples sin lógica compleja.
  • Procedimientos que es poco probable que cambien.
  • Cuando la rutina es parte de un módulo mucho más grande y no necesita ninguna de las otras funciones del módulo. Copiar la función única evita la hinchazón.

Este enfoque tiene las siguientes desventajas:

  • Si hay hay un error en la función copiada, tendrá que corregirlo en muchos lugares.
  • Tiene duplicación de código si termina importando el módulo fuente de todos modos.

Elige tus batallas

Solía ​​hacer todo lo posible para mantener todos mis módulos de biblioteca de código estándar completamente independientes. El problema fue que resultó en una gran cantidad de duplicación de código. La razón es que la mayoría de las funciones que estaba copiando a otros módulos para uso privado provenían de módulos que estaba importando a mi aplicación de todos modos.

Un buen ejemplo de esto fue mi StringFunctions módulo. Ese módulo tiene varios métodos simples que existen en gran parte para hacer que mi código sea más legible. Por ejemplo, tengo un Conc() función que estaba incluyendo como una función privada en más de la mitad de mis módulos de biblioteca de código.

Con el tiempo me di cuenta de que incluí que StringFunctions módulo en todos mis proyectos. Nunca introduje una nueva dependencia cuando llamé a una función desde ese módulo. Estaba perdiendo el tiempo e introduciendo un código duplicado con poco o ningún beneficio.

Había algunos módulos de código que podía suponer con seguridad que estarían en todas las aplicaciones. Esos fueron los módulos con funciones que usé con más frecuencia. Lo que significaba que muchas de estas dependencias básicamente podían ignorarse.

Ahora mantengo una "Biblioteca estándar" de módulos de código que importo en cada nuevo proyecto desde el principio. Llamo libremente a las funciones de esos módulos ahora con la certeza de que no introduciré nuevas dependencias.

Utilice un token de comentario único

Uno de los módulos en mi "Biblioteca estándar" es un módulo de clase (clsApp ) que incluye propiedades y métodos a nivel de aplicación, como el nombre de usuario actual y el texto de la barra de título. También expongo otros módulos de clase desde dentro de clsApp , como clsStatus y clsRegistry , que proporcionan un acceso más legible a la barra de estado de Access y al registro de Windows, respectivamente.

Sin embargo, no necesito acceso a la barra de estado o al registro de Windows en todos los proyectos. Entonces, para evitar crear una dependencia en clsStatus o clsRegistry clases, comentaría el código que hace referencia a esas clases usando un "token de comentario" único.

Esto es más fácil de demostrar con un ejemplo:

' Notes     
' - Find and replace '$$ with blank to enable Status property (requires clsStatus)
' - Find and replace '&& with blank to enable Reg property (requires clsRegistry)

'$$Private m_objStatus As clsStatus
'&&Private m_objReg As clsRegistry

'$$Public Property Get Status() As clsStatus
'$$    Set Status = m_objStatus
'$$End Property

'&&Public Property Get Reg() As clsRegistry
'&&    Set Reg = m_objReg
'&&End Property

Private Sub Class_Initialize()
    '$$    Set m_objStatus = New clsStatus
    '&&    Set m_objReg = New clsRegistry
End Sub

Si quisiera habilitar el Status propiedad de la clase anterior, podría realizar una búsqueda y reemplazo global en '$$ .

Esto funcionó bien por un tiempo, pero siempre me pareció torpe. Probablemente porque lo era. La otra cosa a tener en cuenta es que los tokens de comentarios deberían ser únicos a nivel mundial en toda mi biblioteca de códigos. Esto habría sido una pesadilla de mantenimiento si me hubiera quedado con este enfoque por mucho tiempo.

Usar compilación condicional

Un enfoque mucho más limpio es aprovechar la compilación condicional. Esas son las líneas en VBA que comienzan con un signo de almohadilla/hashtag ("#"). Las líneas que comienzan con ese carácter están sujetas a "preprocesamiento".

¿Qué es el preprocesamiento? Ese es un paso que dan los lenguajes de programación antes de la compilación. Entonces, antes de que ocurra cualquier verificación de tiempo de compilación, se evalúan las líneas de preprocesamiento. Esto nos permite colocar código que de otro modo no se compilaría en nuestros proyectos.

¿Cómo podemos aprovechar esto con nuestras bibliotecas de código? Nuevamente, esto es más simple de demostrar con un ejemplo:

' Notes 
' - Replace the '$$ and '&& kludges with conditional compilation

#Const EnableStatusProperty = True  'If True, requires import of clsStatus class
#Const EnableRegProperty = False  'If True, requires import of clsRegistry class

#If EnableStatusProperty Then
Private m_objStatus As clsStatus
#End If
#If EnableRegProperty Then
Private m_objReg As clsRegistry
#End If

#If EnableStatusProperty Then
Public Property Get Status() As clsStatus
    Set Status = m_objStatus
End Property
#End If

#If EnableRegProperty Then
Public Property Get Reg() As clsRegistry
    Set Reg = m_objReg
End Property
#End If

Private Sub Class_Initialize()
#If EnableStatusProperty Then
    Set m_objStatus = New clsStatus
#End If
#If EnableRegProperty Then
    Set m_objReg = New clsRegistry
#End If
End Sub

Lo mejor de ambos mundos

Como puede ver, esta es una forma muy limpia de evitar el problema del "Tren de dependencia".

Nos permite crear dependencias opcionales . Cada pieza de código que se basa en otro módulo de biblioteca de código se envuelve dentro de una declaración de compilación condicional #If ... Then. Las constantes de compilación condicional se enumeran en la parte superior del módulo de código.

Ahora, cuando volvemos a importar una versión actualizada de nuestro módulo de biblioteca de código, simplemente tenemos que pasar y configurar los indicadores de compilación condicional en gran parte de lo que había antes. Si no recordamos cómo se establecieron las banderas, deberíamos poder seguir compilando y ajustando las banderas hasta que el proyecto se compile por completo.

Y si usamos el control de versiones, no tenemos que preocuparnos por olvidar lo que había antes.