На цьому тижні ми мали дуже приємний досвід спіокування з клієнтом, який потребував допомоги для оцінки свого junior Flutter розробника: настав час для нього отримати підвищення до більш високої ролі, але в команді нікого немає, хто мав би достадній досвід з Flutter, для того, щоб переглянути його код і зробити висновок, чи заслуговує він цього підвищення або буде навчатися та практикувати більше, щоб отримати його.
І це проливає світло на проблему, яка здається досить поширеною: як зрозуміти за якими ознаками код Flutter розробника "добрий" або "поганий". Щоб дати деякі натяки на це, ми збираємося зібрати у цій статті що "робити" та "не робити" у Flutter розробці. Залишайтесь з нами, якщо вам цікава така тема, ми плануємо час від часу оновлювати її новими кейсами. Давайте почнемо з:
Робити:
Хороший зразок коду #1: Використовуйте централізований метод для ініціювання мережевих викликів:
@override | |
Future<dynamic> fetch(String url) async { | |
try { | |
final Response response = await dio.get(Uri.encodeFull(url)); | |
debugPrint(response.data.toString()); | |
return response.data; | |
} catch (e) { | |
debugPrint('Error while fetching data $e'); | |
rethrow; | |
} | |
} |
Приклад #3: Використовуйте інтерфейс, а не ім'я класу для звернення до методів служб:
abstract class IVerificationService { | |
Future<VerificationInfo> fetchVerificationData(String url); | |
} | |
class VerificationService extends IVerificationService { | |
IRepository repository = Repository(DomainType.identity); | |
@override | |
Future<VerificationInfo> fetchVerificationData(String url) async { | |
return VerificationInfo.fromJson(await repository.fetch(url) as Map<String, dynamic>); | |
} | |
} |
class VerificationBloc extends Bloc<VerificationEvent, VerificationState> { | |
VerificationInfo verification; | |
IVerificationService verificationService = VerificationService(); | |
@override | |
VerificationState get initialState => VerificationInitial(); | |
@override | |
Stream<VerificationState> mapEventToState( | |
VerificationEvent event, | |
) async* { | |
if(event is FeatchVerificationDataEvent){ | |
if(verification == null){ | |
verification = await verificationService.fetchVerificationData(verificationsUrl); | |
yield VerificationDataResponseState(verificationData: verification); | |
} | |
} | |
} | |
} |
class _MainScreenState extends State<MainScreen> { | |
/// Key to show snack bars | |
final _scaffoldKey = GlobalKey<ScaffoldState>(); | |
... |
@override | |
Widget build(BuildContext context) { | |
return Scaffold( | |
key: _scaffoldKey, |
_showSnackBar(String message) => _scaffoldKey.currentState.showSnackBar(SnackBar( | |
duration: Duration(milliseconds: 1500), | |
content: Text( | |
message, | |
textAlign: TextAlign.center, | |
), | |
)); |
Приклад #5: Використовуйте властивості для їх змін, щоб реагувати на оновлення: Розширення класів PropertyChangeNotifier Екземпляр цього класу в допоміжному класі: І нарешті використання в UI віджеті:
NetworkHelper.user.addListener(_avatarUrlListener, ['avatarUrl']); | |
void _avatarUrlListener() { | |
setState(() { | |
_avatarUrl = NetworkHelper.user.avatarUrl ?? ''; | |
}); | |
} |
а тепер давайте згадаємо деякі з них
Не робити:
Приклад #1: Використовуйте примусову затримку при роботі з ансихронними викликами, щоб "переконатися, що виклик виконаний":
await Future.delayed(Duration(seconds: 3)); |
Приклад #2: Відсутність unit ам UI тестів, введених в проект, безумовно свідчить про низький рівень навичок кодування або відстуність відношення до нього