데이터베이스를 사용하던 아니든 데이터를 저장하는 역할을 하는 인터페이스와 클래스를 만드세요. 우선은 메모리에만 데이터를 저장하도록 구현을 하시고 추후에 데이터베이스를 사용하게 되면 데이터베이스를 이용하는 클래스를 구현해서 고체하세요. 인터페이스이니까 아무 문제 없이 이게 가능합니다.
기본적인 아이디어를 보여 드릴게요.
// Review 클래스 정의.
public class Review {
private final float score;
private final String comment;
private final User user;
//필요한 필드 정의
// constructor, getter, setter 생략
}
public class User {
//필요한 필드 정의
// constructor, getter, setter 생략
}
// 데이터 조작에 필요한 동작을 정의하는 인터페이스 정의
public interface ReviewDataSource {
List<Review> getReviews();
Reivew getReviewById(String id);
void addReview(Review review);
void updateReview(Review review);
void deleteReviewById9String id);
}
//.메모리를 사용하는 클래스 구현
public class ReviewMemoryDataSource implements ReviewDataSource {
private List<Review> store = new ArrayList<>();
@Override
public List<Review> getReviews() {
return store;
}
// 다른 메소드들도 구현.
}
이런 식으로 만드시고 사용하는 곳에서는 , 아래처럼 ReviewDataSource를 가져오는 팩토리를 하나만들고 ReviewDataSource 를 Singleton으로 만듧니다. ReviewDataSource 가 필요한 곳에서는 DataSorceFactory.getReviewDataSource()를 호출해서 사용합니다.
public class DataSorceFactory {
private static ReviewDataSource reviewDataSource;
public static ReviewDataSource getReviewDataSource() {
if (reviewDataSource == null) {
reviewDataSource = new ReviewMemoryDataSource();
}
return reviewDataSource;
}
}
public class MainActivity extends AppCompatActivity {
private ReviewDataSource reviewDataSource;
public void create(Bundle saveInstance) {
super.create(saveInstance);
this.reviewDataSource = DataSorceFactory.getReviewDataSource();
}
}
추후에 데이터베이스로 전환하신다면 ReviewDataSource의 구현 클래스를 새로 만드시고 DataSourceFactory의 코드를 변경하시면 됩니다.
// DB를 사용하는 클래스 구현
public class ReviewDBDataSource implements ReviewDataSource {
private SQLiteDatabase db = ...
@Override
public List<Review> getReviews() {
...
}
// 다른 메소드들도 구현.
}
public class DataSorceFactory {
...
public static ReviewDataSource getReviewDataSource() {
..
reviewDataSource = new ReviewDBDataSource();
...
}
}
이렇게 하면, ReviewDataSource를 사용하는 곳의 코드 변경없이 마이그레션이 가능합니다.
위의 예제에서는MainActivity의 DataSource, DataSource에 들어가는 ArrayList나 SQLite를 내부에서 생성했는데, 이 부분은 Dendency Injection이란 기법을 사용하는 것이 더 좋고, Dagger와 같은 라이브리러를 많이 사용합니다.
한가지 염두에 두실 점은 DataSource에서 사용하는 데이터의 구조와 화면에 필요한 데이터의 구조가 다르기 쉽다는 것입니다. 이건 DataSource에 있는 클래스의 인스턴스에 화면에 필요한 필드를 추가하지 마시고 화면용 클래스를 별도로 정의하셔서 화면에만 필요한 필드를 추가하세요. 그리고 데이터소스에서 가져온 데이터를 화면에 필요한 데이터로 매핑해서 상요하시기를 권장들려요. 이게 당장은 귀찮은 작업처럼 보이지만, 프로젝트가 진행이 되면 될 수록 얻는게 훨씬 많은 더 좋은 접근방법입니다. UI와 DataSource는 데이터든 클래스든 최대한 서로 분리하는게 좋습니다.
그리고 MainActivity 에제에서 DataSource를 바로 가져다 사용했는데, 이 부분도 중간에 DataSource와 뷰를 중계해줄 수 있는 중계클래스를 두는 것이 일반적입니다.(MVC, MVP, MVVM, MVI 패턴 중 하나 사용) 개발자라면, 반드시 그렇게 하시라고 말씀드리고 싶네요. (안 그러면 팀웤이 불가능할 수 있어요.)