<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: مصعب يوسف</title>
    <description>The latest articles on DEV Community by مصعب يوسف (@ms3byoussef).</description>
    <link>https://dev.to/ms3byoussef</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F587396%2F8cba00f3-fe0c-4fd6-9e45-b85c9a7da7ba.jpg</url>
      <title>DEV Community: مصعب يوسف</title>
      <link>https://dev.to/ms3byoussef</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ms3byoussef"/>
    <language>en</language>
    <item>
      <title>Flutter Architecture Recommendations and Resource</title>
      <dc:creator>مصعب يوسف</dc:creator>
      <pubDate>Sat, 17 May 2025 16:34:27 +0000</pubDate>
      <link>https://dev.to/ms3byoussef/flutter-architecture-recommendations-and-resource-3kf</link>
      <guid>https://dev.to/ms3byoussef/flutter-architecture-recommendations-and-resource-3kf</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Building a Flutter application with a solid architectural foundation is crucial for creating maintainable, scalable, and efficient code. The Flutter team provides recommendations for best practices in app architecture. These recommendations are adaptable and should be tailored to your app’s unique needs. Below, we explore these practices with examples and explanations.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Separation of Concerns
&lt;/h2&gt;

&lt;p&gt;Separation of concerns is a fundamental architectural principle. It ensures that your app is divided into distinct layers, each responsible for a specific functionality, such as UI, data handling, and business logic. Here are the key recommendations:&lt;/p&gt;

&lt;h4&gt;
  
  
  1. Use Clearly Defined Data and UI Layers
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Recommendation Level:&lt;/strong&gt; Strongly Recommend&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Why It Matters:&lt;/strong&gt; By separating the data and UI layers, your app becomes more modular, testable, and maintainable.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Implementation&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data Layer:&lt;/strong&gt; Responsible for managing data sources (e.g., APIs, databases) and business logic.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;UI Layer:&lt;/strong&gt; Displays data and listens for user interactions.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Data Layer
class UserRepository {
  final ApiService apiService;

UserRepository(this.apiService);
  Future&amp;lt;User&amp;gt; getUser(String id) async {
    return await apiService.fetchUser(id);
  }
}
// UI Layer
class UserViewModel extends ChangeNotifier {
  final UserRepository repository;
  UserViewModel(this.repository);
  User? user;
  Future&amp;lt;void&amp;gt; fetchUser(String id) async {
    user = await repository.getUser(id);
    notifyListeners();
  }
}
// Widget
class UserScreen extends StatelessWidget {
  final UserViewModel viewModel;
  UserScreen(this.viewModel);
  @override
  Widget build(BuildContext context) {
    return FutureBuilder(
      future: viewModel.fetchUser('123'),
      builder: (context, snapshot) {
        if (snapshot.connectionState == ConnectionState.waiting) {
          return CircularProgressIndicator();
        } else if (snapshot.hasError) {
          return Text('Error: ${snapshot.error}');
        } else {
          return Text('User: ${viewModel.user?.name}');
        }
      },
    );
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Use the Repository Pattern
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Recommendation Level:&lt;/strong&gt; Strongly Recommend&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;why It Matters:&lt;/strong&gt; This pattern isolates data access logic, making the app more flexible and easier to test.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Use ViewModels and Views in the UI Layer (MVVM)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Recommendation Level:&lt;/strong&gt; Strongly Recommend&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Why It Matters:&lt;/strong&gt; Keeps widgets “dumb,” reducing errors and increasing reusability.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. Avoid Logic in Widgets
&lt;/h3&gt;

&lt;p&gt;Encapsulate all logic in ViewModels or other helper classes, leaving widgets responsible only for rendering UI.&lt;/p&gt;

&lt;h2&gt;
  
  
  Handling Data
&lt;/h2&gt;

&lt;p&gt;Handling data with care improves code reliability and prevents errors.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Use Unidirectional Data Flow
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Recommendation Level:&lt;/strong&gt; Strongly Recommend&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Implementation&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Data flows from the data layer to the UI layer.&lt;/li&gt;
&lt;li&gt;User interactions trigger updates in the data layer.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Use Immutable Data Models
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Recommendation Level: Strongly Recommend&lt;/li&gt;
&lt;li&gt;Why It Matters: Prevents unintended mutations and makes debugging easier.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import 'package:freezed_annotation/freezed_annotation.dart';
part 'user.freezed.dart';
part 'user.g.dart';

@freezed
class User with _$User {
  const factory User({
    required String id,
    required String name,
  }) = _User;
  factory User.fromJson(Map&amp;lt;String, dynamic&amp;gt; json) =&amp;gt; _$UserFromJson(json);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Create Separate API Models and Domain Models
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Recommendation Level: Conditional&lt;/li&gt;
&lt;li&gt;Why It Matters: Reduces complexity in large apps by preventing coupling between API responses and business logic.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  App Structure
&lt;/h2&gt;

&lt;p&gt;A well-structured app simplifies collaboration and enhances code quality.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Use Dependency Injection
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Recommendation Level: Strongly Recommend&lt;/li&gt;
&lt;li&gt;Why It Matters: Prevents global state and enhances testability.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import 'package:provider/provider.dart';

void main() {
  runApp(
    MultiProvider(
      providers: [
        Provider(create: (_) =&amp;gt; ApiService()),
        ProxyProvider&amp;lt;ApiService, UserRepository&amp;gt;(
          update: (_, apiService, __) =&amp;gt; UserRepository(apiService),
        ),
      ],
      child: MyApp(),
    ),
  );
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Use go_router for Navigation
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Recommendation Level: Recommend&lt;/li&gt;
&lt;li&gt;Why It Matters: Simplifies navigation while supporting deep linking and state restoration.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Use Abstract Repository Classes
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Recommendation Level: Strongly Recommend&lt;/li&gt;
&lt;li&gt;Why It Matters: Allows different implementations for various environments (e.g., development, staging).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Testing
&lt;/h2&gt;

&lt;p&gt;Testing ensures your app’s reliability and reduces the risk of introducing bugs&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Test Architectural Components Separately and Together
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Recommendation Level: Strongly Recommend&lt;/li&gt;
&lt;li&gt;Implementation:&lt;/li&gt;
&lt;li&gt;Write unit tests for repositories, services, and ViewModels.&lt;/li&gt;
&lt;li&gt;Write widget tests for views.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;void main() {
  test('UserRepository fetches user correctly', () async {
    final mockApiService = MockApiService();
    final repository = UserRepository(mockApiService);

when(mockApiService.fetchUser('123'))
        .thenAnswer((_) async =&amp;gt; User(id: '123', name: 'John Doe'));
    final user = await repository.getUser('123');
    expect(user.name, 'John Doe');
  });
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Use Fakes for Testing
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Recommendation Level: Strongly Recommend&lt;/li&gt;
&lt;li&gt;Why It Matters: Encourages modular and testable code by focusing on inputs and outputs.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Recommended resources
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Code and templates
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Compass app source code — Source code of a full-featured, robust Flutter application that implements many of these recommendations.&lt;/li&gt;
&lt;li&gt;very_good_cli — A Flutter application template made by the Flutter experts Very Good Ventures. This template generates a similar app structure.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Documentation
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Very Good Engineering architecture documentation — Very Good Engineering is a documentation site by VGV that has technical articles, demos, and open-sourced projects. It includes documentation on architecting Flutter applications.&lt;/li&gt;
&lt;li&gt;State Management with ChangeNotifier walkthrough — A gentle introduction into using the primitives in the Flutter SDK for your state management.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Tooling
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Flutter developer tools — DevTools is a suite of performance and debugging tools for Dart and Flutter.&lt;/li&gt;
&lt;li&gt;flutter_lints — A package that contains the lints for Flutter apps recommended by the Flutter team. Use this package to encourage good coding practices across a team.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By following these recommendations, you can create Flutter applications that are efficient, scalable, and easy to maintain.&lt;/p&gt;

&lt;p&gt;Thank you for reading&lt;/p&gt;

&lt;p&gt;see more &lt;a href="https://ms3byoussef.medium.com/" rel="noopener noreferrer"&gt;https://ms3byoussef.medium.com/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>architecture</category>
      <category>cleancode</category>
      <category>mobile</category>
    </item>
    <item>
      <title>Flutter Enums in Flutter with Sealed Classes in Dart 3</title>
      <dc:creator>مصعب يوسف</dc:creator>
      <pubDate>Sat, 17 May 2025 10:07:41 +0000</pubDate>
      <link>https://dev.to/ms3byoussef/flutter-enums-in-flutter-with-sealed-classes-in-dart-3-28cl</link>
      <guid>https://dev.to/ms3byoussef/flutter-enums-in-flutter-with-sealed-classes-in-dart-3-28cl</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Enums have long been a reliable and expressive way to represent a set of constant values in both Dart and Flutter. With the arrival of Dart 3, enums are no longer just simple constants — they now support advanced features that make them incredibly versatile. When used alongside sealed classes, another exciting Dart 3 addition, enums can help you build cleaner, more robust, and type-safe application logic.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  In this expanded article, we’ll dive into:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;What are enums in Dart, and why they matter&lt;/li&gt;
&lt;li&gt;A look at Dart 3’s powerful enum upgrades&lt;/li&gt;
&lt;li&gt;Introduction to sealed classes and union types&lt;/li&gt;
&lt;li&gt;Real-world examples combining Enums with sealed classes for elegant modeling in Flutter apps&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What Are Enums in Dart?
&lt;/h2&gt;

&lt;p&gt;Enums (short for “enumerations”) are a special kind of type in Dart that represent a fixed set of named values. They are particularly handy for situations where a variable should only take one of a limited number of possible values. Use cases include user roles, app themes, navigation tabs, button states, form field types, and more.&lt;/p&gt;

&lt;p&gt;Here’s a basic example of how enums are defined and used in Dart:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;enum AppTheme {
  light,
  dark,
  system,
}

void applyTheme(AppTheme theme) {
  switch (theme) {
    case AppTheme.light:
      print("Applying light theme");
      break;
    case AppTheme.dark:
      print("Applying dark theme");
      break;
    case AppTheme.system:
      print("Following system theme");
      break;
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This approach ensures that only one of the defined values can be used, reducing errors and improving readability.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dart 3: More Powerful Enums
&lt;/h3&gt;

&lt;p&gt;Dart 3 takes Enumsto a whole new level by allowing them to carry data and implement behavior. These enhancements make enums act more like regular classes, opening new opportunities for modeling domain-specific logic right within an enum.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Instance Fields and Methods
&lt;/h3&gt;

&lt;p&gt;Enums can now include constructor parameters, fields, and methods — giving them far more expressive power.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;enum AppTheme {
  light("Light"),
  dark("Dark"),
  system("System");

final String displayName;
  const AppTheme(this.displayName);
  void log() =&amp;gt; print("Selected theme: $displayName");
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can now treat Enums like objects, which allows for cleaner UI representation and logic encapsulation.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Mixins and Interfaces
&lt;/h3&gt;

&lt;p&gt;Enums are now capable of implementing interfaces and applying mixins, just like regular classes. This is great for unifying behavior across enum cases.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;abstract interface class Loggable {
  void log();
}

enum LogLevel implements Loggable {
  info,
  warning,
  error;
  @override
  void log() =&amp;gt; print("Level: $name");
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This technique makes it easier to integrate Enums into larger application architectures and design patterns.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sealed Classes &amp;amp; Union Types (Dart 3)
&lt;/h2&gt;

&lt;p&gt;Sealed classes are a new Dart 3 feature designed to model restricted class hierarchies, where all subclasses must be declared in the same file. This guarantees that the compiler knows all possible subclasses, enabling exhaustive checks and powerful pattern matching.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sealed class Result {}

class Success extends Result {
  final String data;
  Success(this.data);
}
class Failure extends Result {
  final String message;
  Failure(this.message);
}
void handle(Result result) {
  switch (result) {
    case Success(:final data):
      print("Success with $data");
      break;
    case Failure(:final message):
      print("Failed: $message");
      break;
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This makes sealed classes ideal for modeling outcomes, states, or event flows, where every possible case should be handled explicitly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Combining Enums with Sealed Classes
&lt;/h3&gt;

&lt;p&gt;One of the most compelling use cases is combining enums and sealed classes to build modular validation logic. This approach leads to highly testable, decoupled components.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Define an enum for the field type
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;enum FieldType {
  email,
  password,
  username,
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2: Define a sealed class hierarchy for validation results
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sealed class ValidationResult {}

class Valid extends ValidationResult {}
class Invalid extends ValidationResult {
  final String reason;
  Invalid(this.reason);
}
class Empty extends ValidationResult {}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3: Use both together for validation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ValidationResult validate(String value, FieldType type) {
  if (value.isEmpty) return Empty();

switch (type) {
    case FieldType.email:
      return value.contains('@')
          ? Valid()
          : Invalid("Invalid email format");
    case FieldType.password:
      return value.length &amp;gt;= 6
          ? Valid()
          : Invalid("Password too short");
    case FieldType.username:
      return value.length &amp;gt;= 3
          ? Valid()
          : Invalid("Username too short");
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This architecture is modular and keeps responsibilities clearly separated: Enums define types, while sealed classes represent outcomes.&lt;/p&gt;

&lt;h2&gt;
  
  
  💡 Real-World Use Case: Flutter UI State Modeling
&lt;/h2&gt;

&lt;p&gt;A typical scenario where sealed classes shine is in managing UI states in a Bloc or Cubit. This lets you represent each state explicitly and attach data to it when needed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sealed class FetchState {}

class Loading extends FetchState {}
class Success extends FetchState {
  final List&amp;lt;String&amp;gt; items;
  Success(this.items);
}
class Error extends FetchState {
  final String message;
  Error(this.message);
}
Widget build(BuildContext context) {
  return switch (state) {
    Loading() =&amp;gt; const CircularProgressIndicator(),
    Success(:final items) =&amp;gt; ListView(
      children: items.map(Text.new).toList(),
    ),
    Error(:final message) =&amp;gt; Text('Error: $message'),
  };
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using sealed classes in UI state management eliminates the need for nullable types, flags, or combining  Enums with data-holder classes — resulting in more elegant and reliable code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Dart 3’s support for enriched Enums and sealed classes transforms how we model logic and data flow in Flutter apps. This powerful duo enables you to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Represent fixed choices with associated data using Enums&lt;/li&gt;
&lt;li&gt;Build fully type-safe and exhaustive logic flows with sealed classes&lt;/li&gt;
&lt;li&gt;Eliminate ambiguity and boilerplate when working with UI states or business logic&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you’re aiming for maintainable, testable, and scalable codebases, these tools should become a core part of your Flutter development workflow. Whether you’re building form validators, handling network states, modeling navigation routes, or structuring domain logic, combining Enums with sealed classes provides the clarity and precision modern apps demand.&lt;/p&gt;

&lt;p&gt;you can see our blogs in &lt;a href="https://medium.com/@ms3byoussef" rel="noopener noreferrer"&gt;https://medium.com/@ms3byoussef&lt;/a&gt;&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>dart</category>
      <category>mobile</category>
      <category>database</category>
    </item>
  </channel>
</rss>
