1. Use meaningful and easy pronounceable variable names
//! BAD 

final yyyyMMddstring = DateFormat('yyyy/MM/dd').format(DateTime.now());

//* GOOD 

final currentDate = DateFormat('yyyy/MM/dd').format(DateTime.now());
  1. Use Future.wait to make concurrent API calls
//! BAD 

Future callMultipleApis() async { 
  await getUserInfo(); 
  await getLocations();
} 

//* GOOD 

Future callMultipleApis() async { 
  await Future.wait([
    getUserInfo(), 
    getLocations(), 
  ]);
}
  1. Use searchable names
//! BAD 

Future.delayed(const Duration(minutes: 30), () { 
  debugPrint('some logic here');
}); 

//* GOOD 

const MINUTES_DURATION = 30;

Future.delayed(const Duration(minutes: MINUTES_DURATION), () { 
  debugPrint('some logic');
}); 

//----OR---- 

const HALF_AN_HOUR = Duration(minutes: 30);

Future.delayed(HALF_AN_HOUR, () { 
  debugPrint('some logic');
});
  1. Use explanatory variables
const info = ['John', '31', '[email protected]'];

//! BAD 

final infoPerson = Person(fullName: info[0], age: info[1], email: info[2]);

infoPerson.saveInfo(); 

//* GOOD 

final fullName = info[0];
final age = info[1];
final email = info[2];
final infoPerson = Person(fullName: fullName, age: age, email: email)
..saveInfo();
  1. Avoid mental mapping

    1. We have a list that contains staff names
    const staffs = ['Holmes', 'Dane', 'Dyno', 'Maker'];
    

    b. and we perform some actions with this list

    //! BAD 
    
    for (final n in staffs) { 
      doSomething(); 
      //... 
      //... 
      //... 
      //... 
      //... 
      //... 
      //"n" is defined as what? 
      doStuff(n);
    } 
    
    //* GOOD 
    
    for (final staffName in staffs) { 
      doSomething(); 
      //... 
      //... 
      //... 
      //... 
      //... 
      //... 
      doStuff(staffName);
    }
    
  2. Prefer default parameters over short-circuiting or conditionals

//! BAD

void logErrorWithDefaultInternal({String? errorText}) { 
  print(errorText ?? 'Internal Server Error');
} 

//* GOOD

void logErrorWithDefaultInternal({String errorText = 'Internal Server Error'}){
   print(errorText);
}
  1. Single responsibility principle
const numbers = [33, 10, 99, 275, -100, 9000, -300];

//!BAD 

List getGenericNumbers() { 
  final result = numbers.where((number) { 
    if (number.isOdd && number > 0) { 
      return true; 
    } 
    return false; 
  }).toList(); 
  return result;
} 

//!GOOD 

bool checkNumberIsOddAndPositive(int number) { 
  return number.isOdd && number > 0;
} 

List getListPositiveOddNumbers() { 
  final result = numbers.where(checkNumberIsOddAndPositive).toList();
  return result;
}
  1. Don't make duplicate code: DRY and SOLID
// First, we have 3 classes Person, Student, Teacher.
// Student and Teacher both extend Person
class Person {}

class Student extends Person {
  //properties...
}

class Teacher extends Person {
  //properties...
}
//! BAD

Widget _buildAvatarStudent() {
  return Image.asset('assets/images/student.png');
}

Widget _buildAvatarTeacher() {
  return Image.asset('assets/images/teacher.png');
}

//! GOOD

Widget _buildAvatar(Person person) {
  String image = 'assets/images/placeholder.png';
  if (person is Student) {
    image = 'assets/images/student.png';
  } else if (person is Teacher) {
    image = 'assets/iamges/teacher.png';
  }
  return Image.asset(image);
}
  1. Use Final and Const
    1. Use final for variables that won't be reassigned.
    2. Use const for values that will not change during runtime.
  2. Avoid Deep Nesting
    1. Refactor code to avoid deep nesting, which can make the code harder to read.
    2. Consider breaking down complex functions into smaller, more manageable ones.