(Вредные) советы для разработки на Flutter

Недавно я наткнулся на статью Tips for Coding with Flutter. И не просто где-то в самом темном закоулке Интернета, а прямо Medium мне прислал ее в подборке, в качестве рекомендации. Т.е. статья весьма популярна и её прочитает много разработчиков, в том числе и начинающих.

Я начал читать и то, что я увидел — мне совсем не понравилось. Некоторые советы действительно хорошие, но некоторые — весьма спорные. Давайте пойдем по порядку.

Именование

Naming Convention

Libraries, packages, directories, and source files should be in lowercase with underscores in between words like this:

library dart_dynamic_links;
import 'socket/socket_manager.art';

Classes, enums, extension names, and typedefs should start in uppercase like this :

class MainSection {...}
enum ItemSelectionTemp {...}
extension MyList<F> on List<F> {...}
typedef Definition<D> = bool function(D value);

Constants, variables, parameters, and named parameters should start with lowercase then the other words start with uppercase just like this example:

const magazinePrice = 4.20;
var itemsOfSchools;
final urlPlacement = RegExp(‘^([a-z]+):');
void magSum(int magazinePrice) {...}

Здесь лучше всего просто придерживаться официальных рекомендаций 

https://dart.dev/guides/language/effective-dart/style 

https://dart.dev/guides/language/effective-dart/design#names

Там описание более полное, с корректными примерами и пояснениями. В отличие от того, что мы видим в статье.

Следующий совет: «Указывайте тип для членов класса»

Specify Types for Classes Members

It’s important that you always specify the type of member when the values are known. You should avoid using var when possible.

int days = 22;
final vehichle car = vehichle();
String name = 'Kevin';
const int timeUntilEnd = 120;

С приведенными примерами указание типа не имеет смыла, об этом и говорится в Effective Dart. Тип нужно указывать когда он не очевиден, а что хорошего в дублировании одного и того же слова в строчке final Vehichle car = Vehichle();  – решительно не понятно.

Совет «Используйте относительные импорты»

User Relative Imports

To avoid confusion and problems down the line it’s best practice to use the relative method of importing libraries in lib/ folder.

Don’t do this:

import 'package:demo/src/utilis/firebase_utilis.dart';

Instead, do this:

import '../../../utilis/firebase_utilis.dart';

Этот совет я бы вообще расценил как пример плохой практики. Относительные импорты можно использовать и они удобны для связанного функционала, например в рамках одной директории, но не как в указанном примере import '../../../utilis/firebase_utilis.dart';. Здесь мы обращаемся к явно другой части программы, которая может быть легко перемещена, а т.к. IDE до сих пор не очень с рефакторингом относительных путей — то мы просто получим кучу проблем из-за этого. Не говоря уж о том, что читается и понимается такой импорт гораздо хуже.

Используйте операторы ?? и ? 

Use ?? and, ? Operators

You should use ?? (if null) and ?. (null aware) operators instead of the null checks in conditional expressions.

Don’t do these:

v = x == null ? y : x;
v = x == null ? null :x.y;

Instead do these:

v = x ?? y;
v = x?.y;

Тут вопросов нет, всё так.

Избегайте использования as

Avoid Using the ‘as’ Operator

Generally, the ‘as’ operator throws an exception if the cast is not possible, to avoid that you can use the ‘is’ operator.

Don’t do this:

(item as Vehichle).name = 'BMW';

Instead, do this:

if (item is Vehichle)
item.name = 'BMW';

Я согласен с автором, и лишний раз действительно не стоит его использовать, но зависит от того, что вам требуется. Если вам нужно именно исключение, если тип не тот, что ожидается, то as  — ваш вариант.

Совет «Используйте условие if вместо условного выражения»

Use the ‘if’ Condition Instead of Conditional Expression

Several times we need to render a widget based on some condition in Row and Column. If conditional expression return null in any case then we should use it if condition only.

Don’t do this:

Instead, do this:

Тут правильная идея и посыл (да, пользуйтесь if  и for  в списках, это круто и очень облегчает чтение кода), но неправильный пример. Приведенные примеры просто возвращают разные результаты. Я понял идею, и возможно это просто придирка, но новичков может запутать, примеры должны быть корректнее.

Используйте каскадный оператор

Use The Cascades Operator

If you don’t intend on performing a sequence of operations on the same object then you should use the Cascades(..) operator.

Согласен.

Используйте raw строки

Use Raw Strings

You should use raw strings to avoid escaping backlashes and the dollar signs.

Don’t do this:

Instead, do this:

Тут не совсем согласен. Про raw строки конечно надо знать и применять когда удобно, но не всегда (естественно за исключением случаев когда нужны параметры в строке). Хотя возможно я неправильно понял посыл и именно это и имелось ввиду.

Используйте spread оператор

Use Spread Collections

Using spread collections will simplify the code for you when the existing items are already stored in another collection.

Don’t do this:

Instead, do this:

Да, очень удобная штука, используйте, но опять же — почему пример некорректный?

Последние три совета

Не инициализируйте переменную значением null («Don’t Initialize Variables as Null»), избегайте вызовов print() («Avoid ‘print()’ Calls») и используйте ListView.builder для длинных списков («Use ‘ListView.builder’ for a Long List») достаточно очевидны и верны.

В заключение

В заключение добавлю, что хотелось бы видеть больше качественного материала по Dart/Flutter. Потому что когда популярность набирают такие статьи, то это немного грустно и в целом для сообщества вредно.

Не согласны? Есть что добавить? Просто хотите пообщаться? Оставляйте комментарии или приходите ко мне в Twitter.

Добавить комментарий