Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Restructuration of the solution : Fabulous / Fabulous.XamarinForms / Fabulous.StaticView #481

Merged

Conversation

TimLariviere
Copy link
Member

@TimLariviere TimLariviere commented Jun 26, 2019

Closes #333

Description

Today, Fabulous is a unique framework that only address Xamarin.Forms.
After a year working on it, I became pretty confident that it would be possible to split the projects into different products and that would open a lot of opportunities.

This PR restructures almost all the source code into 3 differents parts (still the same repo):

  • Fabulous
    Can be considered as the V pendant of Elmish (M+U) of the MVU pattern.
    It regroups all the logic (ViewElement, UpdateIncremental) and toolings (Generator, LiveUpdate) to provide a solid foundation for UI frameworks to create their own declarative UI APIs in F# with minimal effort.

  • Fabulous.XamarinForms
    One of those possible declarative UI APIs.
    Builds on Fabulous to provide a way to create apps using Xamarin.Forms.

  • Fabulous.StaticView
    A legacy framework
    Allows to create apps using Xamarin.Forms using MVU and XAML files.
    Independent of Fabulous / Fabulous.XamarinForms

This PR also consolidates the NuGet packages into more meaningful ones:

  • Fabulous
  • Fabulous.LiveUpdate (not usable by itself -- for library authors only)
  • Fabulous.XamarinForms
  • Fabulous.XamarinForms.LiveUpdate
  • Fabulous.XamarinForms.Templates
  • Fabulous.XamarinForms.* (Extensions like Maps, SkiaSharp, etc.)
  • Fabulous.StaticView.XamarinForms
  • fabulous-cli

The build script has been adapted to support this new structure, and makes it easier to spot which project failed to compile.

This has been done with minimal breaking changes in mind!
A migration guide is coming.

Motivations

  • Improve maintainability of Fabulous

Fabulous keeps growing day after day.
The mix between DynamicView, StaticView and View management was getting more and more complex to maintain in a single project.

For instance, for Xamarin.Forms, we need to create custom controls that can support our declarative UI APIs.
If those controls were not dependent of Fabulous, we could put them into Fabulous.CustomControls.
If not, we were forced to put them directly in Fabulous.Core.

Then came the day where the Generator needed Fabulous.Core.dll to generate a file required by Fabulous.Core.dll...

  • Improve API ergonomics

With the mix-match of modules, knowing why a certain function was in the namespace Fabulous.DynamicView instead of Fabulous.Core, when both are in the Fabulous.Core.dll, was hard.

Separating everything out allows us to put the namespaces into their respective dlls.
Way easier to know where something comes from.

  • Align with Elmish to simplify the F# MVU ecosystem [SUSPENDED]

Elmish is already very popular among F# developers, and serves as a base for a lot of UI frameworks (Elmish.WPF, Avalonia.FuncUI, and many more!)

Those frameworks even start to provide their own implementation of declarative UI (Elmish.WPF.Dynamic)

But today, Fabulous provides its own implementation of MVU.
Almost identical to Elmish, yet completely separated.

This ability to share code between Fabulous and Elmish has been requested many times.
But this separation between the two makes it hard to achieve one codebase (at least for the M-U part).

Aligning with Elmish would also greatly streamline the F# MVU ecosystem.
Want M-U support? Go Elmish.
Want V support as well? Go Fabulous (fully compatible with existing Elmish code).

// SUSPENDED because of some incompatibilities between Fabulous and Elmish.
Fabulous requires some features (like swappable dispatch function) to fully support LiveUpdate and simple ways to send a message from a platform project.
This is too Fabulous specific to ask Elmish to integrate it.
Needs further discussions

  • Allow new frameworks to build on Fabulous and provide their own declarative UI APIs

A lot of UI frameworks build directly on Elmish to provide their own declarative UI.
They each need to reimplement their own way of dealing with view attribute holders (Button.Text = "Hello"), view diffing, optimizations and toolings.

This leads to a lot of efforts that goes into some projects, where it could be centralized in one place and benefit everyone.

These new frameworks will be able to leverage existing Fabulous toolings like the Generator (to automate their view APIs creation) and LiveUpdate.

In the future, we can imagine seeing Fabulous.WPF, Fabulous.Android, Fabulous.iOS, etc.

  • Allow generic optimizations that will benefit other frameworks

Providing this one foundation for all UI frameworks to work on allows us to make optimizations that will benefit everyone.
One such optimization is the new diff algorithm I'm currently working on.
Fabulous will be able to directly provide the precomputed view diff to dependent frameworks, greatly simplifying their implementations.

  • Provide the ability to move Fabulous.XamarinForms, Fabulous.XamarinForms extensions and Fabulous.StaticView into their own separate repositories if needed

As this PR clearly separates Fabulous from Fabulous.XamarinForms and other, this allows us to eventually move them into their own separate GitHub repos for easier maintainability and evolutivity.

New structure

The solution will be structured like that:

(Root Level is Fabulous)

  • src
    • Fabulous
    • Fabulous.LiveUpdate
    • Fabulous.Cli
  • tests
    • Fabulous.Tests (unit tests for Fabulous)
    • Generator.Tests (unit tests for Generator)
  • tools
    • Generator
  • Fabulous.XamarinForms
    • src
      • Fabulous.XamarinForms (contains the custom controls, the converters and the Elmish Program specific to Xamarin.Forms)
      • Fabulous.XamarinForms.Controls (contains the generated View API)
      • Fabulous.XamarinForms.LiveUpdate (enables LiveUpdate for Xamarin.Forms)
    • tests
      • Fabulous.XamarinForms.Tests
      • FSharpDaemon.Driver.Tests (integration tests of FSharp.Compiler.PortaCode for the Xamarin.Forms samples)
    • samples
      • All the existing DynamicView samples
    • templates
      • Fabulous.XamarinForms.Templates (Fabulous.Templates rebranded for the occasion)
    • extensions
      • All the existing Fabulous.XamarinForms extensions
  • Fabulous.StaticView
    • src
      • Fabulous.StaticView.XamarinForms (I only separated the existing StaticView part as-is. No work as been done to generalize it like Fabulous/Fabulous.XamarinForms)
    • samples
      • All the samples specific to StaticView

Future

This PR lays the groundwork for future features and optimizations.

One of those new features will be to create a new diff algorithm that we will directly integrate into Fabulous (others won't have to reimplement it) and it should provide better performance (see #241)

Another feature will be to significantly improve the Generator to automatically find existing controls inside dlls and generate view APIs for them.
This would be overridable with an external json file where library authors could remove controls, add new ones, customize the update behavior, etc.

@dsyme
Copy link
Collaborator

dsyme commented Jun 27, 2019

Fascinating! This is fantastic!

@TimLariviere TimLariviere force-pushed the solution-restructuration branch from 9ba74de to 9122335 Compare June 29, 2019 12:01
@fabulous-dev fabulous-dev deleted a comment from azure-pipelines bot Jun 29, 2019
@fabulous-dev fabulous-dev deleted a comment from azure-pipelines bot Jun 29, 2019
@fabulous-dev fabulous-dev deleted a comment from azure-pipelines bot Jun 29, 2019
@TimLariviere
Copy link
Member Author

/azp run full build

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@TimLariviere TimLariviere marked this pull request as ready for review June 29, 2019 13:49
@TimLariviere
Copy link
Member Author

@SergejDK @cmeeren If you want to take a look and let me know what you think, this PR is ready. :)

@cmeeren
Copy link

cmeeren commented Jun 29, 2019

I really like the idea. I will leave it to others to check. 👍

Copy link
Collaborator

@SergejDK SergejDK left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It works great! nothing broken.
Good job here! :)

@TimLariviere TimLariviere merged commit e1613ad into fabulous-dev:master Jun 30, 2019
@TimLariviere TimLariviere deleted the solution-restructuration branch June 30, 2019 19:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Consider moving the half-elmish approach in another project
4 participants