Access
 sql >> Base de Dados >  >> RDS >> Access

Cuidado com o que você observa


Encontrei esta resposta no StackOverflow outro dia e queria chamar atenção para isso (ênfase minha):
O problema se manifestou durante a depuração quando teve um relógio que tentou retornar o item da chave "ausente" . Na verdade, a depuração ainda mais frustrada teve o mesmo problema quando eu literalmente observei o [scriptingdictonaryObject].exists() condicional); Sugiro que a tecla "ausente" seja adicionada por causa do relógio . Quando removi o relógio e, em vez disso, criei uma planilha temporária para copiar a matriz durante a execução, as chaves indesejadas não foram mais adicionadas.
Objeto de dicionário adicionando itens antes de .add() ser chamado Estou usando um objeto de dicionário da biblioteca MS Scripting Runtime para armazenar uma série de matrizes e realizar operações nas células da matriz conforme necessário. Existe um loop for para percorrer o processo ... Stack Overflowriddley_w

O que está acontecendo aqui?


Um dos "recursos" de um objeto Dicionário é que ele implicitamente crie novos itens sem precisar chamar o método .Add explicitamente . Qual é a diferença entre implícito e explícito?

Observação:o uso com limite antecipado do objeto Dicionário requer uma referência ao "Microsoft Scripting Runtime" (detalhes aqui).
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")

Aqui está a parte relevante da documentação sobre implícito criação de chave:
Observações
Se chave não é encontrado ao alterar um item , uma nova chave é criado com o newitem especificado . Se chave não for encontrado ao tentar retornar um item existente, uma nova chave é criado e seu item correspondente é deixado em branco.

Reproduzindo o problema


Vamos reproduzir o problema para ver exatamente onde as coisas vão de lado.

Comportamento esperado


Crie a seguinte rotina de amostra:
Sub WatchOut()
    Dim MyDict As Dictionary
    Set MyDict = New Dictionary
    
    Debug.Print "KeyA exists? "; MyDict.Exists("KeyA")
End Sub

Execute a rotina acima na janela imediata e ela deve retornar False:
WatchOut
KeyA exists? False

Adicionar um relógio


Agora, vamos adicionar um relógio do item "KeyA":

Vamos tentar executar o WatchOut rotina novamente:
WatchOut
KeyA exists? False

Até agora tudo bem. Talvez isso não seja um problema, afinal.

Percorra o código


Vamos adicionar uma Parar instrução para forçar o código a quebrar:
Sub WatchOut()
    Dim MyDict As Dictionary
    Set MyDict = New Dictionary
    
    Stop
    Debug.Print "KeyA exists? "; MyDict.Exists("KeyA")
End Sub

Agora, vamos tentar executar o WatchOut rotina:
WatchOut
KeyA exists? True

Ah! A combinação do relógio e entrar no depurador é suficiente para forçar o "bug" a aparecer. coloquei bug entre aspas de susto porque é realmente o comportamento esperado para o depurador. Mas é quase certamente um comportamento inesperado para o desenvolvedor.

(Observe que não há nada de especial em Parar comando que causa esse comportamento. Você pode remover a Parar linha e defina um ponto de interrupção no código e o mesmo comportamento ocorrerá.)

Você pode ver onde esse tipo de coisa pode fazer com que você puxe o cabelo durante a depuração. Sempre que o comportamento do seu programa for diferente durante a execução normal e durante a depuração, você terá uma sessão de depuração agravante.

Resumo


Etapas para reproduzir o problema:
  1. Crie um relógio para um item específico do Dicionário
  2. Entre no depurador enquanto executa o código

Isso provavelmente só ajudará um ou dois desenvolvedores. Mas isso potencialmente economizará horas desses desenvolvedores de frustração. E, se estou sendo honesto, sou tão provável quanto qualquer um de ser um desses desenvolvedores;-).