Nel precedente post, abbiamo descritto eventuali strategie per evitare null reference exception. L'ultima scelta è ricaduta sulla seguente forma:
repository.UseStudentFoundByCode(1234,new Output());
Ovvero passiamo al metodo che recupera le informazioni dello studente, un oggetto con la responsabilità di notificare i dati dello studente in un qualche formato. Vediamo come è stato implementato UseStudentFoundByCode:
public void UseStudentFoundByCode(int code,
IStudentSubstitute substitute)
{
var
student = studentsDatabase.GetByCode(code);
if
(student == null)
return;
substitute.Perform(student);
}
Ora vorrei illustrare una scelta leggermente più elegante per rendere la sintassi un po' più zuccherina:
repository
.StudentFoundByCode(1234)
.Perform(new
Output().Write);
Modifichiamo la classe Repository come segue:
public
class Repository
{
private
StudentsDatabase studentsDatabase;
public
IStudentSubstitute StudentFoundByCode(int
code)
{
var
student = studentsDatabase.GetByCode(code);
if
(student == null)
return
new
NullStudentSubstitute();
return
new StudentSubstitute(student);
}
}
La scelta ricade sul restituire un oggetto che può o non può eseguire operazioni sull'oggetto Student, quindi se GetByCode restituisce un'istanza valida, StudentFoundByCode deciderà a chi delegare le operazioni sull'oggetto Student.
Creiamo l'interfaccia comune:
public
interface IStudentSubstitute
{
void
Perform(Action<Student>
student);
}
Implementiamo le due strategie per eseguire operazioni sull'oggetto Student:
public
class StudentSubstitute : IStudentSubstitute
{
private
readonly
Student
student;
public StudentSubstitute(Student
student)
{
this.student
= student;
}
public
void
Perform(Action<Student>
action)
{
action(student);
}
}
public
class
NullStudentSubstitute : IStudentSubstitute
{
public
void
Perform(Action<Student>
action)
{
}
}
Con questa soluzione centraliziamo le azioni che vogliamo svolgere sull'oggetto studente, ignari se l'oggetto student è stato creato.