La tua soluzione attuale suona come un hack, per due motivi:
-
Stai chiedendo all'agente per alcune informazioni, ma per farlo devi anche emettere comandi come "gira a sinistra". In genere è meglio praticare la separazione tra richieste e query poiché ciò rende più chiaro quando una chiamata al metodo cambia lo stato dell'oggetto.
Di per sé, cambiare lo stato dell'agente per sondare in direzioni diverse non è problematico in quanto l'agente si troverà nella stessa direzione prima e dopo la chiamata al metodo. Tuttavia, la modifica dello stato dell'oggetto introduce in modo intermittente fragilità: cosa accade quando un'eccezione viene lanciata prima che l'agente sia tornato al loro orientamento originale? Tieni anche la post-condizione "l'agente affronta nella direzione originale"? Cosa succede se il numero di turni è associato ad un certo costo o è tracciato? Per esempio. se questo è un gioco di puzzle, il punteggio del gioco potrebbe prendere in considerazione il numero di turni. L'implementazione del controllo bloccato in termini di rotazione dell'agente potrebbe influenzare direttamente il punteggio del gioco.
Si noti che in Python, l'impostazione di un campo di istanza può avere effetti collaterali sconosciuti se tale campo di istanza è implementato come proprietà. Al contrario, l'impostazione di un campo membro è sempre "sicura" in un linguaggio come Java.
-
Le operazioni fornite dall'agente e le operazioni richieste nel programma non corrispondono. Vuoi sapere se un agente è bloccato, quindi dovrebbe avere un metodo agent.is_stuck() -> bool
. Poiché tale metodo è interno all'agente, può utilizzare direttamente la stessa logica di agent.can_move_in_facing_direction()
senza la necessità di modificare lo stato dell'oggetto. Probabilmente estrai la logica comune in un metodo di supporto come self.__can_move_in_direction(d)
.
Come problema di progettazione generale, non è una buona idea usare qualsiasi cosa tranne i parametri di funzione per passare i parametri di funzione. L'utilizzo dei campi di istanza non è fondamentalmente diverso dall'uso di variabili globali per comunicare i parametri. È l'equivalente morale di:
# params for add
x = None
y = None
result = None
def add():
result = x + y
# invoke add
x = 40
y = 2
add()
print(result) #=> 42
Questo ha i suoi usi? Sì, nella programmazione di assembly con spazio limitato in cui è necessario impedire le allocazioni dello stack. Ma nelle lingue di alto livello? Non proprio.
Il problema con le variabili globali (o, in realtà, qualsiasi variabile con un ambito di grandi dimensioni) è che è sempre più difficile tenere traccia di come viene utilizzata tale variabile. Se uso una variabile ish globale e chiamo una funzione, ho bisogno di sapere se la funzione chiamata modifica direttamente o indirettamente quella variabile. Tenere traccia del comportamento esatto di tutte quelle funzioni va da difficile (se ci sono molte funzioni che potrebbero influenzare quelle variabili) a impossibile (se infinite funzioni potrebbero essere aggiunte ereditando la tua classe). È difficile capire il comportamento di queste funzioni poiché non dipendono solo dai loro parametri espliciti, ma implicitamente anche dallo stato del mondo che li circonda.
Lo stato di muting è il meno possibile e mantenere uno stato mutabile incapsulato e diviso in piccoli pezzi coesivi non è solo una questione di "codice pulito", è fondamentale per mantenere comprensibile un grande code base.