Diciamo che ho un metodo DoTheThing()
che richiede il precondizionamento-controllo CanTheThingBeDone()
per restituire true. Il secondo metodo richiede molto tempo poiché accede al database.
Sto trovando difficile trovare un modo perfetto per eseguire in modo efficace il controllo di precondizione (cioè una volta ) pur mantenendo la leggibilità e l'integrità dell'API. Osserva questi esempi:
Esempio 1:
class System() {
public void DoTheThing() {
if (!CanTheThingBeDone()) throw new Exception(...);
// Do it
}
public bool CanTheThingBeDone() {
// Some time consuming code
}
}
class Consumer() {
public void SomeLargerOperation() {
try {
system.DoTheThing();
}
catch (Exception) {
// Error handling
}
}
}
Esempio 2:
class System() {
public void DoTheThing() {
// Do it
}
public bool CanTheThingBeDone() {
// Some time consuming code
}
}
class Consumer() {
public void SomeLargerOperation() {
if (system.CanTheThingBeDone()) {
system.DoIt();
}
}
}
Entrambi gli approcci sono ok, ma entrambi hanno degli svantaggi. In Esempio 1 , impongo al consumatore di avvolgere il codice in un try-catch per stati difettosi. Questi stati possono essere attivati dall'utente in modo da richiedere una gestione aggraziata. Non sono sicuro che try-catch per la gestione degli errori degli utenti sia un buon approccio.
In Esempio 2 mi sto affidando la responsabilità del controllo dello stato sul consumatore, aprendo per errori di runtime non descrittivi. Nell'esempio questo , CanTheThingBeDone () è selezionato, ma quando Jimmy entra nel team a 1 anno da ora per sviluppare il modulo 2, potrebbe cambiare.
Esempio 3:
class System() {
public bool DoTheThing() {
if (!CanTheThingBeDone()) return false;
// Do it
return true;
}
public bool CanTheThingBeDone() {
// Some time consuming code
}
}
class Consumer() {
public void SomeLargerOperation() {
if (!system.DoTheThing()) ProduceSomeErrorMessage();
}
}
In questo esempio, evito try-catch per gli errori degli utenti e impedisco l'esecuzione del Do-code effettivo se lo stato non è valido, assicurando che il codice di controllo venga eseguito una sola volta. Ma sento di infrangere qualche principio di denominazione / codifica quando il metodo sta eseguendo sia il controllo che la modifica dello stato della classe (sono abbastanza sicuro che abbia persino un nome).
Come quarto esempio, potrei immaginare una combinazione di # 1 e amp; # 2 dove sia il consumatore che DoTheThing
chiamano CanTheThingBeDone
, ma poi stiamo facendo il lavoro due volte.
Per riassumere, non riesco a trovare un approccio migliore. Qualcuno ha un'idea migliore della mia o dei suggerimenti su come modificare uno di questi approcci per ottenere un risultato migliore?