Get Fluttered: MVC+S Architecture, Example

Thursday, Jan 14, 2021| Tags: flutter, mvc+s, get_fluttered, prapare, tutorial

Intro -

To all who watched my original GetFluttered: MVC+S Architecture video, I want to thank you immensely for your patience.

Before making new GetFluttered videos, we wanted to implement:

  1. A means to provide written, supplemental info … Meta-Blog;
  2. A complex, production-level MVC+S example … PRAPARE app; &
  3. A means for others to join / collaborate … FlutterJuun Slack invite.

With these elements now firmly established, it should be easier to follow along with GetFluttered content by comparing simple + complex code examples that achieve the same objective.

Given our healthcare focus, and specifically our interest in connecting FHIR® to Flutter, our roadmap for GetFluttered videos will also include some FHIR-FLI content…but by no means is the GetFluttered series limited to health apps. Many of the topics covered can be applied to any Flutter app.

Here’s the primer on FHIR-FLI:

Finally, I plan to periodically update this architecture page so the Slack invite remains active (since Slack links now expire after 30 days)…but if I miss it, let me know in a comment on one of my YouTube videos. I’ll respond to your comment when the invite link is reactivated. Update: link should no longer expire.

MVC+S: Architecture

You should probably start by reading Ryan Edge’s post on Flutter State 5 Ways. Then read GSkinner’s article on MVC+S Architecture. Finally, check whatever latest discussions may exist in the Flutter community. As of Jan 2021, Simon Lightfoot’s video may be a good start…

When deciding state / architecture, consider:

  • Do your classes follow the single responsibility principle?
  • Are they testable?
  • Are they modular?
  • How difficult is this setup?
  • Are others able to understand and build from it?

Ultimately, we decided upon the Get package to manage state and the GSkinner suggestion on MVC+S for our architecture. Because Get uses its controllers – not models – to manage state, we elected to make slight modifications from the original GSkinner approach.

Get MVC+S Diagram

Working with Streams

In the Architecture video, I particularly made a point of swapping between int counter = 0; and RxInt rxCounter = 0.obs; because I wanted you to be able to use this architecture with and without streams. GetX makes it extremely easy to work with streams and with minimal boilerplate, so you should feel comfortable swapping between the two.

Keep in mind that the GetX and OBx methods require a stream to function properly. If it isn’t a stream, use GetBuilder instead. Also, make sure to call update(); in your controller if you need to trigger a UI refresh.

I was very intentional in my GetFluttered commit history to have each commit focus on a single objective in my video. Swapping between typical variables <–> streams is one example where the commit log can help. I plan to continue this format as best I can (and within reason).

Variable Names ± Streams

Initially, I was quite strict about updating all variable names to include ‘rx’ at the front if it referenced a stream…but as we built PRAPARE it became apparent that this level of control seemed more a hindrance than a benefit. Including ‘rx’ was useful in many cases, but should not be a set requirement. For complex data models, I would suggest you focus on variables and method names that are easy to read / understand, following patterns when it makes sense to do so.

MVC+S: Example

In my opinion, learning about folder structure is best accomplished via example. Our video outlining the PRAPARE app as a complex example of the MVC+S architecture pattern should help. Keeping everything in one place, this is the general guideline we followed:

FolderSubfolderDescription
/_internalcustom modifications, constants / enums, utility classes
/componentscustom components / variations on Flutter widgets
/constantslocal constants created for the app
/enumspredefined, named constants
/utilslocal functions that do things like formatting
/apioptional API key location
<custom>.dartprivate API keys
api_public.dartpublic API keys (no gitignore)
api.dartgeneric export file
/controllersmanages state of the model and resultant data
/commandsperforms a specific global task (login, logout, change password)
../<custom>_command.dartcustom command class
../abstract_command.dartabstract class for commonly used controllers, placeholder execute() method for commands
<custom>_controller.dartcustom controller, typically used for state management
/modelsclasses / objects created specifically for this app
<custom>_data.dartcustom data class
<custom>_model.dartdata model that typically modifies or shapes a data class
/routesmaps route to screen widgets
app_pages.dartthe directory of each page within an app
app_routes.dartstring route names used in the app
/servicesinteraction with the outside world (REST, FHIR, http, file storage)
/uiessentially all things a user sees in the app
/styled_componentsshared widgets that use a common design system / theme so that the app seems consistent across screens
../styled_<widget_name>.dart
/viewstop level widgets that are loaded via a route
../<screen_name>/
../../<screen_name>.dartthe screen widget, may optionally include ‘page’, ‘card’, or ‘panel’ at the end based on view type
../../<screen_name>_binding.dartcontrollers/services that are loaded (or lazy-loaded) in a view
../../<screen_name>_controller.dartthe viewcontroller that only affects this screen widget
../../<screen_name>_test.dartany relevant tests for the screen widget or its viewcontroller
icons.darticon asset locations
localization.dartstrings with multiple translations
strings.dartstrings used throughout an app
themes.dartcustom themes and font sizes
main.dartthe first file a Dart app runs

Conclusion

I hope these written supplements will be useful as you design and build your own Flutter apps.

If there are any questions, or if you have any specific requests for GetFluttered topics to cover next, feel free to join us on the FlutterJuun Slack. A lot of GetFluttered content will build directly off of the work we already created in PRAPARE, and we have a lot of features to cover (themes, locales, databinding, serialization, etc.) in the short-term. That said, the path forward is pretty flexible and welcome to suggestions.

Keep learning, keep creating, and stay safe!

–John

Addendum

Since creating this post, I made another YouTube video that shows this architecture in much greater detail, using the PRAPARE app as an in-depth example.

Relevant timestamps for Get MVC+S architecture folder structure begin at ~50 min.

Want to Learn More?

Contact Us