Рекомендации по проектированию Objective-c для использования различных источников данных, переключения между тестовым и живым - PullRequest
7 голосов
/ 27 мая 2010

Я нахожусь в процессе разработки приложения, которое является частью большой части работы, в зависимости от других людей, чтобы создать API, который приложение может использовать для извлечения данных.

Пока я думал о том, как настроить этот проект и спроектировать архитектуру вокруг него, со мной что-то произошло, и я уверен, что многие люди были в подобных ситуациях.

Поскольку моя работа зависит от других людей, выполняющих свои задачи, и от тестового сервера, это замедляет работу с моей стороны.

Итак, вопрос: Какова лучшая практика для создания тестовых репозиториев и классов, их реализации и отсутствия необходимости зависеть от изменения нескольких мест в коде для переключения между тестовыми классами и реальными репозиториями / собственными вызовами API.

Создайте следующий сценарий:

GetDataFromApiCommand *getDataCommand = [[GetDataFromApiCommand alloc]init];
getDataCommand.delegate = self;
[getDataCommand getData];

Как только данные доступны через API, «GetDataFromApiCommand» может использовать фактический API, но до тех пор набор фиктивных данных может быть возвращен при вызове [getDataCommand getData]

Может быть несколько таких случаев в разных местах кода, поэтому замена всех из них, где бы они ни находились, является медленным и болезненным процессом, который неизбежно приводит к тому, что один или два игнорируются.

В строго типизированных языках мы могли бы использовать внедрение зависимостей и просто изменить одно место. В target-c можно реализовать фабричный шаблон, но разве это лучший путь для этого?

GetDataFromApiCommand *getDataCommand = [GetDataFromApiCommandFactory buildGetDataFromApiCommand];
getDataCommand.delegate = self;
[getDataCommand getData];

Какова наилучшая практика для достижения этого результата?

Поскольку это было бы наиболее полезно, даже если у вас есть действующий API, для запуска тестов или работы в автономном режиме, ApiCommands не обязательно должны быть заменены навсегда, но возможность выбрать «Хочу ли я использовать TestApiCommand или ApiCommand ".

Более интересно иметь возможность переключаться между: Все команды тестовые а также Все команды используют живой API, вместо того, чтобы выбирать их по одному, однако это также было бы полезно для тестирования одной или двух реальных команд API, смешивания их с тестовыми данными.


EDIT Способ, который я выбрал для этого, - использовать фабричный шаблон.

Я настроил фабрику следующим образом:

@implementation ApiCommandFactory
+ (ApiCommand *)newApiCommand
{
    // return [[ApiCommand alloc]init];
    return [[ApiCommandMock alloc]init];
}
@end

И везде, где я хочу использовать класс ApiCommand:

GetDataFromApiCommand *getDataCommand = [ApiCommandFactory newApiCommand];

Когда требуется фактический вызов API, комментарии могут быть удалены, а макет может быть закомментирован.

Использование new в имени сообщения означает, что тот, кто когда-либо использует фабрику для получения объекта, несет ответственность за его освобождение (поскольку мы хотим избежать автоматического выпуска на iPhone).

Если требуются дополнительные параметры, завод должен учитывать их то есть:

[ApiCommandFactory newSecondApiCommand:@"param1"];

Это будет очень хорошо работать и с репозиториями.

1 Ответ

1 голос
/ 27 мая 2010

Использование нового в имени сообщения означает, что тот, кто когда-либо использует фабрику для получения объекта, несет ответственность за его освобождение (поскольку мы хотим избежать автоматического выпуска на iPhone).

Вам не нужно быть навязчивым, чтобы не делать авто-релиз. Это действительно применимо только в том случае, если вы создаете много автоматически выпущенных объектов в течение одной итерации цикла событий. Если этот объект рассчитан на то, чтобы прожить достаточно долго, чтобы в противном случае вы сохранили его за пределами заводского метода, возвращение объекта с автоматическим освобождением будет стоить вам только ссылку в пуле автоматического выпуска.

Во всяком случае, чтобы ответить на ваш вопрос, ваш выбор в значительной степени именно то, что я бы сделал. Также рассмотрите возможность создания протокола Objective C, который соответствует API и которому должны соответствовать ваши APICommandMock и APICommand. Это документирует API и обеспечит некоторую дисциплину для вас и другой команды. Например, он будет включать такие вещи, как имена методов и типы параметров.

...