При разработке приложений / моделей предметной области в целом мне интересно, как лучше всего справиться с неполными или необязательными данными . Типизированные языки, такие как TypeScript и C # , дают нам возможность печатать наши модели . Иногда это мощно, так как накладывает ограничения на нашу модель и может заставить ее быть целочисленной. Однако, как правило, реальные данные неполны , и это, по-видимому, радикально снижает преимущества ограничений на типизацию.
Представьте простую модель данных в примере приложения (внешний интерфейс TypeScript и некоторый внутренний интерфейс)объекта с именем Project , который имеет id , имя и необязательное описание . Данные извлекаются из бэкэнда.
Модель данных определяется во внешнем интерфейсе с использованием интерфейсов:
export interface IProject {
id: number;
name: string;
description: string;
}
Данные извлекаются из бэкэнда следующим образом:
export class ProjectService {
public getProject(projectId: number): Observable<IProject> {
const url = 'http://server/api/project/' + projectId;
return this.httpClient.get<IProject>(url);
}
}
Пример ответа проекта, который на самом деле имеет описание.
{
"id": 1
"name": "My first project",
"description": "My first project is just a demo"
}
В приложении веб-интерфейса мы отображаем полученные данные. Например, давайте отобразим первые 10 символов описания проекта.
alert(project.description.substr(0,10));
Пока все отлично.
Но представьте, что наш пользователь создал «Проект второй», не заполнив необязательное описание. Теперь сервер может ответить:
{
"id": 2
"name": "Project two"
}
или
{
"id": 2
"name": "Project two",
"description" : null
}
Теперь мы получаем исключение нулевой ссылки во внешнем интерфейсе: Невозможно прочитать свойство 'substr' из null . Конечно, можно добавить оператор if, который проверяет, чтобы описание было нулевым:
if(project.description) {
alert(project.description.substr(0,10));
}
Это работает, но это означает добавление нулевых проверок во всем приложении. Вся база кода будет заполнена этими проверками, а также опасностями маскирования ошибок вместо их предотвращения. Мне это просто не подходит.
Возможным решением может быть всегда возвращать описание, следовательно, возвращать пустую строку, если ни одна не была заполнена.
{
"id": 2
"name": "Project two",
"description": ""
}
Теперь интерфейс делаетбольше не требуются нулевые проверки для описания, но больше невозможно провести различие между явно заполненным пустым описанием и not (-yet) заполненным описанием.
Как лучше всего решать подобные проблемы? Приведенный выше пример просто для иллюстрации, область действия довольно общая. Похоже, это мешает всем типизированным языкам, на которых определен типизированный контракт / интерфейс, который не всегда может быть выполнен.