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
ICollectioncome 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 ogniICollectionha.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
collaSortedListoSortedSetnella firma del metodo anzichéICollection. Quindi sarei sicuro che sia ordinato, ma ora un utente non può inserire il suoIListanche se lo ha già ordinato, e dato che il suoIListfornisce tutti i metodi di cui avrà bisogno l'algoritmo (AddeRemovee iterando su di esso), potrebbe essere deluso di non poterlo usare. Inoltre, non conosco un modo per dire al compilatore "questo input può essereSortedSetoSortedList", 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 ?