Irbisa · Cheatsheet
Live Coding Round in Dart
Debounce, Result types, LRU cache, backoff, concurrency limits, tries, stream transformers
Live task: write a reusable primary button with a label, an
onPressedcallback and a loading state. What does a good one look like?class PrimaryButton extends StatelessWidget { const PrimaryButton({ super.key, required this.label, required this.onPressed, this.loading = false,…Live task: write a widget that shows the current time and updates every second. How do you keep it accurate and leak-free?
class Clock extends StatefulWidget { const Clock({super.key}); @override State<Clock> createState() => _ClockState();}…This widget should show what the user types in the
Textunder the field, but theTextstays empty: what is wrong, and how do you fix it?class Echo extends StatelessWidget { const Echo({super.key}); @override Widget build(BuildContext context) { final controller = TextEditingController(); var typed = ''; return Column(children: [ TextField(controller: controller, onChanged: (v) => typed = v), Text(typed), ]); }}Users report they cannot sign up with addresses that work everywhere else: what does this email validator get wrong, and what would you ship instead?
final _email = RegExp(r'^[a-zA-Z0-9.]+@[a-zA-Z]+\.[a-zA-Z]{2,3}$'); String? validateEmail(String? value) { if (_email.hasMatch(value!)) return null; return 'Enter a valid email';}Live task: parse a JSON string holding an array of products into
List<Product>and back. How do you writefromJsonandtoJsonby hand?import 'dart:convert'; class Product { const Product({required this.id, required this.title, required this.price, this.note}); final int id;…Live task: build a TODO list screen with add, toggle and remove. How would you structure it in the time you have?
class Todo { const Todo(this.id, this.title, {this.done = false}); final String id, title; final bool done; Todo copyWith({bool? done}) => Todo(id, title, done: done ?? this.done);}…Find the bug: some users report that the Save button keeps spinning forever, and only reopening the screen helps.
bool _saving = false; Future<void> _save() async { setState(() => _saving = true); await widget.repo.saveName(_name.text); if (!mounted) return; setState(() => _saving = false); Navigator.of(context).pop();} @overrideWidget build(BuildContext context) => PrimaryButton(label: 'Save', loading: _saving, onPressed: _save);The API returns a flat list of transactions and the design wants them under date headers: how do you group them, and what makes the
DateTimekey betray you?DateTime dayOf(DateTime t) { final local = t.toLocal(); // the server sends UTC return DateTime(local.year, local.month, local.day); // time stripped} List<({DateTime day, List<Txn> items})> sections(List<Txn> txns) {…A search field fires a request per keystroke and you cannot add rxdart: how do you write debounce and throttle, and which one loses the last keystroke?
class Debouncer { Debouncer(this.delay); final Duration delay; Timer? _timer; void run(void Function() action) {…Every caller of your repository wraps it in try/catch and half of them forget: how would you write a
Result<T, E>withmap,mapErrorandfoldinstead?sealed class Result<T, E> { const Result(); R fold<R>(R Function(T value) onOk, R Function(E error) onErr) => switch (this) { Ok(:final value) => onOk(value), Err(:final error) => onErr(error),…This memoized pricing function should skip a 40 ms computation, yet it never gets faster and the map keeps growing: why does the cache never hit?
final _cache = <List<Object>, double>{}; double shippingCost(String zone, double kg) { final key = [zone, kg]; final hit = _cache[key]; if (hit != null) return hit; return _cache[key] = _computeShipping(zone, kg); // 40 ms}Write an in-memory cache whose entries expire after a TTL: where do you check expiry, and what stops it from growing forever?
import 'package:clock/clock.dart'; class TtlCache<K, V> { TtlCache({required this.ttl, this.maxEntries = 200}); final Duration ttl;…Find the bug: with this
LruCachebehind the avatar loader, the avatar a user has just changed is often the next entry evicted.class LruCache<K, V extends Object> { LruCache(this.capacity); final int capacity; final _map = <K, V>{}; // insertion order: first key = least recent V? get(K key) { final value = _map.remove(key); if (value != null) _map[key] = value; // move to the end: most recent return value; } void put(K key, V value) { _map[key] = value; if (_map.length > capacity) _map.remove(_map.keys.first); }}Your cache holds messages sorted by time and the server returns another sorted page: how do you merge them and drop duplicate ids in one pass?
List<Message> mergeSorted(List<Message> cached, List<Message> fresh) { final out = <Message>[]; final seen = <String>{}; var i = 0, j = 0; void take(Message m) {…A comment thread arrives as a nested tree and
ListView.builderneeds a flat list with indentation: how do you flatten it without recursion?class Comment { Comment(this.id, this.text, {this.children = const []}); final String id; final String text; final List<Comment> children;}…Write a typed event bus with subscribe and unsubscribe: what keeps a listener alive after the screen that registered it is gone?
class EventBus { final _ctrl = StreamController<Object>.broadcast(); void emit(Object event) => _ctrl.add(event); // where + cast: dart:async has no whereType on Stream…Write a function that deep-compares two decoded JSON values and returns the path of the first difference instead of a bool: what are the traps?
String? firstDiff(Object? expected, Object? actual, [String path = r'$']) { if (expected is Map && actual is Map) { final keys = <Object?>{...expected.keys, ...actual.keys}.toList() ..sort((a, b) => '$a'.compareTo('$b')); // insertion order would make "first" random for (final k in keys) { if (!expected.containsKey(k)) return '$path.$k: unexpected (${actual[k]})';…Write a limiter that lets at most five uploads start per rolling minute and queues the rest: why is a counter that resets every minute the wrong answer?
import 'package:clock/clock.dart'; class RateLimiter { RateLimiter({required this.max, required this.window}); final int max;…A GPS stream fires ten fixes a second: how do you write a transformer that emits at most one every five seconds and skips fixes within ten metres of the last one kept?
class Fix { const Fix(this.lat, this.lon, this.at); final double lat, lon; final DateTime at; // the fix's own timestamp, not DateTime.now()}…