sql >> Database >  >> RDS >> Access

Optionele afhankelijkheden creëren

In mijn artikel van gisteren heb ik het concept "Dependency Train" geïntroduceerd. Dat is wat er gebeurt als je een functie uit je codebibliotheek importeert, maar je uiteindelijk meerdere extra modules moet importeren om aan alle afhankelijkheden te voldoen. Je blijft zitten met een hele "trein" codemodules terwijl je alleen maar een enkele "stoel" (functie) nodig had.

Je komt in deze situatie terecht als je modules nauw aan elkaar zijn gekoppeld. Dus wat kun je eraan doen? Er zijn een paar manieren om met deze situatie om te gaan.

Overtreding "herhaal jezelf niet"

Een manier om losse koppeling te behouden - wat resulteert in meer "op zichzelf staande" modules - is om privé-kopieën van de functies van de bronmodule in de aanroepende module te maken. Dit elimineert de afhankelijkheid tussen de twee modules, maar het resulteert wel in herhalende code.

Het concept is eenvoudig. U kopieert de functie van de primaire codemodule. Je plakt het vervolgens in de oproepmodule, maar markeert het als privé om dubbelzinnigheid te voorkomen.

Dit is zinvol in de volgende situaties:

  • Eenvoudige methoden zonder complexe logica.
  • Procedures die waarschijnlijk niet zullen veranderen.
  • Als de routine deel uitmaakt van een veel grotere module en je geen van de andere functies in de module nodig hebt. Het kopiëren van de ene functie vermijdt een opgeblazen gevoel.

Deze aanpak heeft de volgende nadelen:

  • Als er is een bug in de gekopieerde functie, je zult deze op veel plaatsen moeten repareren.
  • Je hebt codeduplicatie als je de bronmodule toch importeert.

Kies je gevechten

Ik deed er altijd alles aan om al mijn standaard codebibliotheekmodules volledig zelfstandig te houden. Het probleem was dat het resulteerde in veel codeduplicatie. De reden is dat de meeste functies die ik voor privégebruik naar andere modules kopieerde, afkomstig waren van modules die ik toch in mijn applicatie importeerde.

Een goed voorbeeld hiervan was mijn StringFunctions module. Die module heeft verschillende eenvoudige methoden die grotendeels bestaan ​​om mijn code leesbaarder te maken. Ik heb bijvoorbeeld een Conc() functie die ik als privéfunctie in meer dan de helft van mijn codebibliotheekmodules opnam.

Na verloop van tijd realiseerde ik me dat ik die StringFunctions . had toegevoegd module in al mijn projecten. Ik introduceerde nooit een nieuwe afhankelijkheid toen ik een functie uit die module aanriep. Ik verspilde tijd en introduceerde dubbele code voor weinig of geen voordeel.

Er waren een paar codemodules waarvan ik veilig kon aannemen dat ze in elke toepassing zouden zitten. Dat waren de modules met functies die ik het vaakst gebruikte. Wat betekende dat veel van deze afhankelijkheden in wezen konden worden genegeerd.

Ik onderhoud nu een "Standaardbibliotheek" van codemodules die ik vanaf het begin in elk nieuw project importeer. Ik roep vrijelijk functies van die modules aan, nu veilig in de wetenschap dat ik geen nieuwe afhankelijkheden zal introduceren.

Gebruik een unieke reactie-token

Een van de modules in mijn "Standaardbibliotheek" is een klassenmodule (clsApp ) die eigenschappen en methoden op toepassingsniveau bevat, zoals de huidige gebruikersnaam en de titelbalktekst. Ik stel ook andere klassenmodules bloot vanuit clsApp , zoals clsStatus en clsRegistry , die een beter leesbare toegang bieden tot respectievelijk de Access-statusbalk en het Windows-register.

Ik heb echter niet in elk project toegang nodig tot de statusbalk of het Windows-register. Dus, om te voorkomen dat er een afhankelijkheid ontstaat van de clsStatus of clsRegistry klassen, zou ik commentaar geven op de code die naar die klassen verwijst met behulp van een uniek "opmerkingstoken".

Dit is het gemakkelijkst aan te tonen met een voorbeeld:

' 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

Als ik de Status . wil inschakelen eigenschap van de bovenstaande klasse, kan ik een globale zoekopdracht uitvoeren en vervangen op '$$ .

Dit werkte een tijdje prima, maar het voelde altijd als een kludge voor mij. Waarschijnlijk omdat het zo was. Het andere om op te merken is dat de commentaartokens wereldwijd uniek moeten zijn in mijn hele codebibliotheek. Dit zou een onderhoudsnachtmerrie zijn geweest als ik deze aanpak lang zou volhouden.

Voorwaardelijke compilatie gebruiken

Een veel schonere benadering is om te profiteren van voorwaardelijke compilatie. Dat zijn de regels in VBA die beginnen met een hekje/hashtag-teken ("#"). Regels die met dat teken beginnen, zijn onderhevig aan "voorbewerking".

Wat is voorbewerken? Dat is een stap die programmeertalen nemen voorafgaand aan de compilatie. Dus voordat enige controle op de compilatietijd plaatsvindt, worden de voorverwerkingsregels geëvalueerd. Dit stelt ons in staat om code te plaatsen die anders niet zou compileren in onze projecten.

Hoe kunnen we hiervan profiteren met onze codebibliotheken? Nogmaals, dit is het eenvoudigst aan te tonen met een voorbeeld:

' 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

Het beste van twee werelden

Zoals u kunt zien, is dit een zeer schone manier om het probleem van de "afhankelijkheidstrein" te vermijden.

Het stelt ons in staat om optionele afhankelijkheden te creëren . Elk stukje code dat afhankelijk is van een andere codebibliotheekmodule wordt verpakt in een voorwaardelijke compilatie #If ... Then-instructie. De voorwaardelijke compilatieconstante(n) worden allemaal bovenaan de codemodule vermeld.

Als we nu een bijgewerkte versie van onze codebibliotheekmodule opnieuw importeren, hoeven we alleen maar door te gaan en de voorwaardelijke compilatievlaggen in te stellen op veel van wat er eerder was. Als we ons niet herinneren hoe de vlaggen zijn ingesteld, zouden we vlaggen moeten kunnen blijven compileren en aanpassen totdat het project volledig is gecompileerd.

En als we versiebeheer gebruiken, hoeven we ons geen zorgen te maken dat we vergeten wat er eerder was.


  1. Trage zoekopdracht bij gebruik van ORDER BY

  2. Hoe ELT() werkt in MariaDB

  3. Python 3.4.0 met MySQL-database

  4. Een Python datetime.datetime-object invoegen in MySQL