Служба Dart — Snackbar — глобальная функция против функции статического класса против синглтона

#flutter #dart #service #wrapper

#flutter #dart #Обслуживание #оболочка

Вопрос:

Я хотел бы создать оболочку вокруг стороннего пакета Snackbar (сторонний Snackbar просто вызывается так: Get.snackbar(title, body, snackPosition: SnackPosition.BOTTOM); ), Чтобы отделить мое приложение от пакета и иметь возможность легко переключаться в другой реализации Snackbar.

Я полагаю, что это должен быть singleton по соображениям производительности. Я хотел бы назвать это как VpSnackBar(title, body); в идеале. Я нашел, как создать синглтон в dart (Vp — это мой префикс приложения, чтобы определить, что он был создан в моем приложении):

Здесь я создал этот синглтон

 class VpSnackBar {

  VpSnackBar._privateConstructor();

  static final VpSnackBar instance = VpSnackBar._privateConstructor();

  static void show(String title, String body) {
    Get.snackbar(title, body, snackPosition: SnackPosition.BOTTOM);
  }
  
}
  

Я должен был бы назвать это как VpSnackBar.show(title, body); . Но тогда я думаю, должен ли я просто создать простой класс со статическим методом, который будет делать то, что это делает, без создания экземпляра? Полезно ли создание экземпляра?

Другим вариантом является глобальная функция с именем в верхнем регистре, поэтому она используется как класс:

 void VpSnackBar(String title, String body) {
  Get.snackbar(title, body, snackPosition: SnackPosition.BOTTOM);
}
  

Это единственный способ, которым я знаю, как это назвать VpSnackBar(title, body); . Какой мой предпочтительный способ его вызвать. Однако является ли глобальная функция плохой практикой? Могу ли я добиться вызова его как VpSnackBar(title, body); без глобальной функции? Какой способ является наилучшей практикой?

Ответ №1:

Чтобы я мог быть в безопасности от любых потенциальных изменений в пакете

Вы не будете ни в коем случае.

  1. Если владелец пакета решит полностью изменить внутренние компоненты метода, не касаясь его прототипа, эти изменения все равно повлияют на вас.

  2. Если владелец пакета решит изменить прототип метода обратно несовместимым способом, который содержит критическое изменение, вы также будете затронуты этими изменениями.

Я полагаю, что это должен быть singleton по соображениям производительности.

Я вижу, что вы не запускаете никаких тяжелых процессов (например, ввода-вывода) при создании экземпляра вашего класса, поэтому я не понимаю, почему вы должны беспокоиться о производительности. Учтите, что для каждого build() вызова виджета, который происходит много раз за одну секунду, создаются экземпляры сотен классов, и они не влияют на производительность приложения.

Однако является ли глобальная функция плохой практикой?

Вовсе нет. Реальная проблема с вашим подходом заключается в написании первой буквы функции с заглавной буквы. Это плохая практика, поскольку она заставляет читателя поверить, что вызов вашей функции на самом деле является вызовом конструктора.

Какой способ является наилучшей практикой?

Как я уже говорил, я даже не вижу разумного мотива для переноса snackbar в первую очередь. Но, оставляя этот вопрос в стороне, каждое из ваших решений кажется мне одинаково справедливым (до тех пор, пока вы не капитализируете первую из функций). В такой ситуации вы можете использовать тот, с которым вам удобнее.

Комментарии:

1. Я оставлю это в качестве комментария, поскольку это не по теме и очень самоуверенно: если вы заботитесь о хороших практиках, get немедленно прекратите использовать. Я мог бы написать целую статью о том, почему это ужасно плохо написано.

2. Спасибо. Упаковка закусочной отделяет мое приложение от упаковки. Если я решу, что мне не нравится Get, я могу просто изменить свою реализацию snack bar в одном файле и сохранить контракт без изменений, а не засорять мое приложение. И я буду гораздо меньше подвержен влиянию их изменений в snack bar, если у них будут критические изменения, поскольку мне приходится иметь дело только с этими изменениями в одном файле. Мне также кажется неправильным не учитывать производительность, потому что якобы сотни классов создаются при каждой сборке, не влияя на производительность. По-моему, это звучит как опасное мышление.

3. Я понял вашу точку зрения о развязке, но вы должны учитывать, что Get работает с snackbar очень необычным способом. Например, если бы вы заменили snackbar Get на встроенную snackbar, ваш контракт не остался бы таким, какой он есть, потому что вам нужен BuildContext в качестве параметра.

4. Я должен настаивать на том, что ваша забота о производительности не является необходимой. Это преждевременная оптимизация, поскольку вы не оценили, влияет ли это на производительность вашего приложения. На самом деле трудно сказать, имеет ли определенная оптимизация какое-либо значение. На самом деле, они могут даже ухудшить производительность. Это потому, что компиляторы делают много магии, а процессоры не работают интуитивно понятным способом. На таком высоком уровне программирования невозможно сказать, что определенная оптимизация выгодна без бенчмарка.

5. Это верно в отношении Get Snackbar. Get SnackBar слишком сильно отличается от Flutter SnackBar, так что их нельзя легко заменить друг на друга. Немного обидно. И правда, я никоим образом не повлияю на производительность отрицательно в этой задаче.