Reputation: 4620
I have a very large class called DatabaseService
that fetches, caches, and updates various streams of data. I'm now attempting to separate each logical block of data into individual files to make it easier to manage. However, I'd like to keep all the methods and streams accessible by providing just the one DatabaseService
file.
My DatabaseService
has these various groups of methods and streams of data that I'm separating into individual files:
The difficulty is that each group of data depends on streams from the other groups of data. For example, comments require the stories feed, and so on: Comments < stories < feed < user
My first iteration looked like this:
class DatabaseService {
// Here, i expose the various streams from each subclass
Stream<User> userStream = UserService.instance.userStream;
Stream<Feed> feedStream = FeedService.instance.feedStream;
Stream<Stories> storiesStream = StoriesService.instance.storiesStream;
Stream<Comments> commentsStream = CommentsService.instance.commentsStream;
...
DatabaseService() {
}
Things quickly become messy when I have to push data to each sub-service and expose multiple methods, or if i need to access methods from one another.
I've looked into using mixins, which look great, but I can't access streams from one sub-class to another.
Is there a better way to do this?
Upvotes: 2
Views: 954
Reputation: 4620
The trick is to make a Base abstract Class which lays out the blueprints for the class. Then have each of the subclasses implement the base class so that they are aware of each other property of the class across each one. Finally the DatabaseService implements the base class and uses each of the subclasses as mixins.
See below for an example:
BaseDatabase:
abstract class BaseDatabase {
final firestore = FirestoreService.instance;
final functions = FunctionsService.instance;
ValueStream<User> userStream;
Future<void> setUser(User user);
Stream<Feed> feedStream;
Stream<Story> storiesStream;
Stream<List<Comment>> commentsStream;
Stream<Location> locationStream(String locationId);
}
DatabaseService:
part 'parts/feed.dart';
class DatabaseService extends BaseDatabase
with
UserService,
LocationService,
FeedService,
CommentsService,
... {
DatabaseService({authService}) {
// Any other required initialization code here, for example something like this.
authService.uid().listen((uid) => userId.add(uid));
}
}
FeedService:
part of '../database_service.dart';
mixin FeedService implements BaseDatabase {
ValueStream<Feed> get feedStream => _getFeedStream().shareValue();
Stream<Feed> _getFeedStream() =>
// userStream is from the UserService.. Winning!
userStream
.distinct((oldUser, newUser) => oldUser.id == newUser.id)
.switchMap((user) => firestore.get(...)
.where((feeds) => feeds.length > 0)
.map((feeds) => feeds[0]));
Upvotes: 1