Sto cercando consigli su come gestire i vincoli sull'input di un metodo. Ho un metodo che funziona solo se gli argomenti di input soddisfano determinati vincoli. Se il metodo viene chiamato su input che non soddisfa i vincoli, il metodo fa qualcosa di dannoso.
Il problema concreto è questo. Ho una classe Interval
che rappresenta gli intervalli 1-dimensionale chiusi:
// code in C# or pseudo-code
class Interval
{
private double lb, ub; // lower bound and upper bound of the interval
public Interval(double lb, double ub)
{
if (lb > ub)
throw new ArgumentException("Lower bound cannot be larger than upper bound!");
this.lb = lb; this.ub = ub;
}
public bool Disjoint(Interval i)
{
return (ub < i.lb || i.ub < lb);
}
public void UniteWith(collection of Intervals)
{
...
}
}
Il metodo UniteWith
dovrebbe prendere una raccolta di% disgiunto Interval
come input e modificarlo in modo tale che, quando si pensa alla collezione come unione di insiemi, l'attuale Interval
sia unita a quell'insieme. Inoltre, la raccolta deve essere modificata in modo tale che, una volta unito, sia di nuovo disgiunto Interval
s.
Esempio:
collection is: [-3, 0], [2, 4], [5, 18], [21, 22]
current interval is: [3, 6]
resulting modified collection is: [-3, 0], [2, 18], [21, 22]
I metodi che ho assolutamente bisogno per la raccolta sono Add
e Remove
, quindi ICollection
sembra essere una scelta ragionevole per il tipo di input (ripensandoci in C #, ma probabilmente si applica anche a Java e ad altri linguaggi OOP) ).
Perché l'algoritmo funzioni correttamente, ho bisogno che l'input sia ordinato. Se non è ordinato, l'input verrà modificato in modo imprevedibile. E questo è il punto in cui non so cosa fare:
-
Potrei prendere
ICollection
come argomento, ma poi avrei bisogno di verificare da solo se l'input è ordinato. Se non è ordinato, lancio un'eccezione per dire al programmatore che usa il mio codice che il suo input è cattivo. Credo di poterlo fare utilizzando l'enumeratore che ogniICollection
ha.public void UniteWith(ICollection<Interval> coll) { IEnumerator enumerator = coll.GetEnumerator(); enumerator.MoveNext(); Interval fst = enumerator.Current; while (enumerator.MoveNext()) { Interval snd = enumerator.Current; if (fst.ub >= snd.lb) throw new ArgumentException("coll must be sorted ascendingly!"); fst = snd; } // if we get here, we can start the actual algorithm ... }
-
Potrei rendere
coll
aSortedList
oSortedSet
nella firma del metodo anzichéICollection
. Quindi sarei sicuro che sia ordinato, ma ora un utente non può inserire il suoIList
anche se lo ha già ordinato, e dato che il suoIList
fornisce tutti i metodi di cui avrà bisogno l'algoritmo (Add
eRemove
e iterando su di esso), potrebbe essere deluso di non poterlo usare. Inoltre, non conosco un modo per dire al compilatore "questo input può essereSortedSet
oSortedList
", e se non esiste un modo simile, è ancora più restrittivo. Ok, potrei scrivere due metodi per questo. Poi ho dovuto occuparmi di due commenti di documentazione (sto commentando OGNI metodo che ho) e le modifiche di copia e incolla sono sempre. È possibile, ma non mi sembra molto attraente. -
Potrei mantenere il tipo di input
ICollection
, non eseguire alcun controllo sulla selezione dell'ingresso e consigliare nel commento della documentazione di non inserire alcuna raccolta non ordinata e spiegare le conseguenze di ciò. Quindi consegno la responsabilità all'utente del mio codice. Anche questo non mi sembra molto pulito, perché questo è esattamente ciò che fa C / C ++ (e ciò che non mi piace): ti lasciano accendere il computer; dicono che ti hanno lasciato perché non possono essere sicuri di non volerlo, ma in realtà non lo volevi - hai fatto un errore.
In attesa di suggerimenti, non solo per questo scenario concreto, ma anche per il caso generale - se esiste una cosa come un "caso generale". (Potrebbe anche essere che dipende sempre.)
EDIT:
Ho appena notato che per la prima e la terza opzione potrebbe essere meglio consentire solo input con un concetto di ordine. Anche se HashSet
ha un enumeratore e come tale un ordine, è più una caratteristica interna. Dal suo concetto, non ha ordine (può cambiare quando aggiungi / rimuovi elementi). Quindi quale interfaccia posso inserire? C'è qualcosa come IOrderable
?