Dart
Putting it together
Combine all layers into a working mini service.
Integration with the App class
In the final step we bring all parts together. The App class takes a TaskService and returns a summary of all services with the summary() method. This is the last link of dependency injection.
Example: class App { final TaskService svc; App(this.svc); String summary() { return 'Integration: ${svc.list().length} task, fib(10): ${fib(10)}'; } }. App brings the service and the computation function together. In main it is created with App(InMemoryTaskService()). In this project chain we gathered the Shelf API, the sqflite database and the Isolate computation under the same interface; each part was added on top of the previous one.
The summary method
The summary() method returns the application state as a single string. It combines the task count with svc.list().length and the computation result with fib(10). This is where the integration is verified.
Example: String summary() { return 'Integration: ${svc.list().length} task, fib(10): ${fib(10)}'; }. In main it is printed with print(app.summary()). The output is Integration: 1 task, fib(10): 55. This is deterministic; it gives the same result every run. The layers we built throughout the project (model, service, API, database, isolate) merge into a single summary here.
Exercise The App class and integration
Write class App with a final TaskService svc field, an App(this.svc) constructor and a String summary() method. Inside summary do return 'Integration: ${svc.list().length} task, fib(10): ${fib(10)}';. In main add final app = App(InMemoryTaskService()); and print(app.summary()).
Show example solution
import 'package:shelf/shelf.dart';
import 'package:shelf_router/shelf_router.dart';
import 'package:sqflite/sqflite.dart';
import 'dart:isolate';
class Task {
final int id;
final String title;
Task({required this.id, required this.title});
}
abstract class TaskService {
List<Task> list();
}
class InMemoryTaskService implements TaskService {
@override
List<Task> list() => [Task(id: 1, title: 'task 1')];
}
Response taskHandler(Request req, TaskService svc) {
return Response.ok('tasks: ${svc.list().length}');
}
class SqliteTaskService {
final Database db;
SqliteTaskService(this.db);
Future<List<Task>> all() async {
final rows = await db.query('tasks');
return rows.map((r) => Task(id: r['id'] as int, title: r['title'] as String)).toList();
}
}
int fib(int n) {
if (n < 2) return n;
return fib(n - 1) + fib(n - 2);
}
Future<int> heavyCompute(int n) {
return Isolate.run(() => fib(n));
}
class App {
final TaskService svc;
App(this.svc);
String summary() {
return 'Integration: ${svc.list().length} task, fib(10): ${fib(10)}';
}
}
void main() {
final app = App(InMemoryTaskService());
print(app.summary());
}
Test yourself
-
The App service field
class App {
final ____ svc;
App(this.svc);
}
Show answer
class App {
final TaskService svc;
App(this.svc);
}
-
Match the integration parts
- App
- Application
- summary
- Summary
- TaskService
- Service
- fib
- Fibonacci
-
What does App.summary do?
- Encrypts
- Compresses
- Returns a summary
- Serializes
Show answer
Returns a summary — App.summary returns a summary of the application.
Next lesson: Advanced section exam