Access
 sql >> Database >  >> RDS >> Access

Attento a cosa guardi

L'altro giorno mi sono imbattuto in questa risposta su StackOverflow e volevo attirare l'attenzione su di essa (enfasi mia):

Ho manifestato questo problema durante il debug quando avevo un orologio che tentava di restituire l'elemento della chiave "mancante" . In realtà, un ulteriore debug frustrato ha avuto lo stesso problema quando ho letteralmente tenuto d'occhio il [scriptingdictonaryObject].exists() condizionale); Suggerisco di aggiungere la chiave "mancante" a causa dell'orologio . Quando ho rimosso l'orologio e ho invece creato un foglio di lavoro temporaneo in cui copiare l'array durante l'esecuzione, le chiavi indesiderate non sono state più aggiunte.
Oggetto dizionario che aggiunge elementi prima che venga chiamato .add() Sto usando un oggetto dizionario dalla libreria MS Scripting Runtime per memorizzare una serie di array ed eseguire operazioni sulle celle dell'array secondo necessità. C'è un ciclo for per seguire il processo... Stack Overflowriddley_w

Cosa sta succedendo qui?

Una delle "caratteristiche" di un oggetto Dictionary è che sarà implicitamente creare nuovi elementi senza dover chiamare il metodo .Add esplicitamente . Qual è la differenza tra implicito ed esplicito?

Nota:l'utilizzo anticipato dell'oggetto Dictionary richiede un riferimento a "Microsoft Scripting Runtime" (dettagli qui).

Dim MyDict As New Dictionary

'Explicit add
MyDict.Add "KeyA", "Item A"

'Implicit add
MyDict.Item("KeyB") = "Item B"

Debug.Print MyDict("KeyA"); vbNewLine; MyDict("KeyB")

Ecco la parte rilevante della documentazione relativa a implicita creazione della chiave:

Osservazioni
Se chiave non viene trovato durante la modifica di un elemento , una nuova chiave viene creato con il newitem specificato . Se chiave non viene trovato quando si tenta di restituire un articolo esistente, una nuova chiave viene creato e l'elemento corrispondente viene lasciato vuoto.

Riproduzione del problema

Riproduciamo il problema per vedere esattamente dove vanno le cose di lato.

Comportamento previsto

Crea la seguente routine di esempio:

Sub WatchOut()
    Dim MyDict As Dictionary
    Set MyDict = New Dictionary
    
    Debug.Print "KeyA exists? "; MyDict.Exists("KeyA")
End Sub

Esegui la routine sopra dalla finestra immediata e dovrebbe restituire False:

WatchOut
KeyA exists? False

Aggiungi un orologio

Ora aggiungiamo un orologio dell'elemento "KeyA":

Proviamo a eseguire WatchOut di nuovo la routine:

WatchOut
KeyA exists? False

Fin qui tutto bene. Forse questo non è un problema, dopotutto.

Scorri il codice

Aggiungiamo uno Stop istruzione per forzare la rottura del codice:

Sub WatchOut()
    Dim MyDict As Dictionary
    Set MyDict = New Dictionary
    
    Stop
    Debug.Print "KeyA exists? "; MyDict.Exists("KeyA")
End Sub

Ora, proviamo a eseguire WatchOut routine:

WatchOut
KeyA exists? True

Ah! La combinazione dell'orologio e dell'irruzione nel debugger è sufficiente per forzare la comparsa del "bug". Ho messo bug tra virgolette spaventose perché in realtà è il comportamento previsto per il debugger. Ma è quasi certamente un comportamento inaspettato per lo sviluppatore.

(Nota che non c'è niente di speciale nello Stop comando che causa questo comportamento. Puoi rimuovere lo Stop riga e imposta un punto di interruzione sul codice e si verificherà lo stesso comportamento.)

Puoi vedere dove questo genere di cose potrebbe farti strappare i capelli durante il debug. Ogni volta che il comportamento del tuo programma è diverso durante l'esecuzione normale rispetto a durante il debug, hai la stoffa di una sessione di debug aggravante.

Riepilogo

Passaggi per riprodurre il problema:

  1. Crea un orologio per un elemento del dizionario specifico
  2. Entra nel debugger durante l'esecuzione del codice

Questo probabilmente aiuterà sempre e solo uno o due sviluppatori. Ma potenzialmente farà risparmiare ore a quegli sviluppatori di frustrazione. E, se devo essere onesto, è probabile che sia uno di quegli sviluppatori come chiunque altro;-).