Лучшие практики для разработки приложений AIR с использованием SQLite - PullRequest
2 голосов
/ 17 августа 2011

Я собираюсь приступить к выполнению нескольких проектов Adobe AIR, которые будут использовать функцию SQLite, предоставляемую AIR.Поскольку я пытаюсь это сделать впервые, я был бы признателен за некоторые советы, советы и рекомендации по разработке.

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

Как следует проектировать мое приложение, если я использую инфраструктуру MVC, такую ​​как Mate или Cairngorm?

Должен ли я создать некоторый класс-оболочку для выполненияоперации БД, чтобы я мог использовать это в каком-то другом проекте?Ждем некоторой ценной информации ...

1 Ответ

5 голосов
/ 17 августа 2011

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

Синхронный

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

Хорошо для небольших приложений

Асинхронный

  • более сложная архитектура
  • труднее читать
  • длительные операции не замораживают пользовательский интерфейс
  • если вам нужно синхронизировать с серверной БД, вы можете создать интерфейс для локальных и удаленных служб БД (например, класс LocalUserService и RemoteUserService оба реализуют интерфейс, который заставляет их иметь метод saveUser() )

Подходит для более масштабных приложений и синхронизации локальных и удаленных данных.

Я склонен почти всегда выбирать асинхронный подход - поскольку он более гибкий - и абстрагироваться от сложности в ... классе-оболочке. Так что это отвечает на ту часть вашего вопроса.

Архитектура

Мне не нравятся фреймворки, поэтому я не могу ответить на ваш вопрос о Mate или -shudder- Cairngorm. Но вот что я считаю довольно хорошим подходом:

  • для каждой сущности в вашей модели создайте объект доступа к данным (DAO), который будет возвращать только необработанные результаты запроса (например, UserDAO для запроса пользователей). Этот класс должен содержать только запросы.
  • в соответствии с каждым DAO создайте Builder / Factory, который может принимать эти результаты запроса и объекты модели появления (например, UserBuilder)
  • Обычно этого достаточно для меня, но вы также можете объединить их в сервисный уровень (например, UserService). Этот уровень обслуживания также может помочь сопоставить существующий уровень удаленного обслуживания с вашими локальными службами.

Что касается сохранения соединения открытым. Я всегда так делал и у меня никогда не было с этим проблем. Я точно не знаю, что происходит, когда происходит сбой приложения и соединение не было должным образом закрыто, но речь идет не о Oracle или SQL Server. Я не думаю, что SQLite будет держать открытые указатели или что-то в этом роде, так как это простой файл, но я могу ошибаться.

Редактировать: некоторые дополнительные сведения о шаблоне DAO / Factory (согласно запросу OP).

Пример UserDAO с одной функцией:

public class PupilDAO extends AsynchronousDAO {

    public function getUserById(id:int, handleResult:Function):Responder {
        return getResults(
            "SELECT * FROM user WHERE user_id = ?", 
            handleResult, [id]
        );
    }

}

Как видите, я абстрагировал сложность от базового класса AsynchronousDAO, поэтому мы можем видеть только необходимую информацию в UserDAO. Функция handleResult - это обратный вызов, который будет вызываться всякий раз, когда запрос готов, передавая набор результатов в качестве аргумента. Обычно мы передаем этот набор результатов в класс factory / builder.

Пример UserBuilder:

public class UserBuilder {

    public function buildUser(record:*):User {
        var user:User = new User();
        user.id = record.user_id;
        user.firstname = record.firstname;
        user.lastname = record.lastname;
        return user;
    }

}

Это, очевидно, простой пример, но вы можете создавать более сложные структуры данных в компоновщике. Для получения информации о разнице между шаблонами Factory и Builder я рекомендую Google.

Теперь давайте свяжем это вместе в классе обслуживания:

public class UserService {
    private var dao:UsetDAO;
    private var builder:UserBuilder;

    public UserService(dao:UserDAO, builder:UserBuilder) {
        this.dao = dao;
        this.builder = builder;
    }

    public function getUserById(id:int, handleResult):void {
        var handleResultSet:Function = function(resultSet:SQLResult):void {
            var user:User = builder.buildUser(resultSet.data[0]);
            if (handleResult!= null) handleResult(user);
        }

        dao.getUserById(id, handleResultSet);            
    }

}

Наконец, давайте используем трио:

var userService = new UserService(new UserDAO(), new UserBuilder());
userService.getUserById(1, handleUser);

function handleUser(user:User):void {
    trace(user);
}

Для примера я сконструировал классы с помощью new и передал дао и конструктор в качестве аргументов конструктора, но вы можете использовать инъекцию или синглтоны или любой другой фреймворк, который вам нравится делать для вас.

...