This week we've had a very nice experience talking to a potential client who needs help for evaluating his junior Flutter developer: it is a time for him to get promoted to the more senior role but there is none in a team recently who are experienced in Flutter enough to review his code and make a conclusion, if he deserves to get this promotion or shall be learning and practicing more to get it.

And this brings light to a problem which seems to be pretty common: how you can get if the Flutter developer and the code he or she wrote is 'good' or 'bad'? To give some hints on this we're going to collect 'dos' and 'don'ts' of a Flutter development in this article. Stay tuned if you're interested on a topic, we plan to update it from time to time with more samples and cases. So, let's start with

Dos:

Good code sample #1: Use centralized method to initiate network calls:

@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;
}
}
view raw doesdonts1.dart hosted with ❤ by GitHub
In this sample above we see single wrapping method to execute a call and process response from it. #2 Here also see the ‘debugPrint’ used to get the prints to the console only in a debug mode. Some nubies use direct print method which bring a lot of a trash into production  build output as well.
Sample #3: Use the interface and not the class name to address services methods:
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>);
}
}
view raw doesdonts2.dart hosted with ❤ by GitHub
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);
}
}
}
}
view raw doesdonts3.dart hosted with ❤ by GitHub
Sample #4: Use keys to address the widget to update to when you need rebuild only it and not the whole widget tree: Introduce a key in a widget’s state:
class _MainScreenState extends State<MainScreen> {
/// Key to show snack bars
final _scaffoldKey = GlobalKey<ScaffoldState>();
...
view raw doesdonts4.dart hosted with ❤ by GitHub
And when widget created do it with the key:
@override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
view raw doesdonts5.dart hosted with ❤ by GitHub
Access to methods or fields of this particular widget done like
_showSnackBar(String message) => _scaffoldKey.currentState.showSnackBar(SnackBar(
duration: Duration(milliseconds: 1500),
content: Text(
message,
textAlign: TextAlign.center,
),
));
view raw doesdonts6.dart hosted with ❤ by GitHub

Sample #5: Use properties and listeners to their changes to react on updates: Classes extending PropertyChangeNotifier
class ForumUser with PropertyChangeNotifier<String> {
String _avatarUrl;
String get avatarUrl => _avatarUrl;
set avatarUrl(String value) {
_avatarUrl = value;
notifyListeners('avatarUrl');
}
view raw doesdonts7.dart hosted with ❤ by GitHub
Instance of this class in helper class:
class NetworkHelper {
static ForumUser user = new ForumUser();
}
view raw doesdonts7.dart hosted with ❤ by GitHub
And finally it’s usage in UI widget:
NetworkHelper.user.addListener(_avatarUrlListener, ['avatarUrl']);
void _avatarUrlListener() {
setState(() {
_avatarUrl = NetworkHelper.user.avatarUrl ?? '';
});
}
view raw doesdonts9.dart hosted with ❤ by GitHub
Here we also can find the good sample #6: usage of a null-aware ?? operator which gives a default value '' to the _avatarUrl variable in case of NetworkHelper.user.avatarUrl is null.

and now let's mention some

Donts:

Sample #1: Use forced delay working with async calls to  ‘ensure call is executed’:

await Future.delayed(Duration(seconds: 3));

Sample #2: No unit and UI tests introduced to the project is definitely an indication of a low coding skills or a lack of an attitude.

More like this

Get in touch

Get in touch

Frankfurt am Main, Germany (Sales)

60354

Eckenheimer Schulstraße, 20

+38 (098) 630-49-85

info@a5.ua

Kharkiv, Ukraine (Development)

61023

Trinklera street, 9

+38 (050) 908-31-07

info@a5.ua

Burgas, Bulgaria (Development)

8008

бул. „Транспортна“ 15, Northern Industrial Zone

+359 877 350129

info@a5.ua