FluidGroup / MondrianLayout

🏗 A way to build AutoLayout rapidly than using InterfaceBuilder(XIB, Storyboard) in iOS.
https://medium.com/geekculture/describing-autolayout-with-imaginable-how-it-lays-out-programmatically-mondrianlayout-71efe82f3149
MIT License
168 stars 11 forks source link

Proposal: Unified API entry points #71

Open JohnEstropia opened 2 years ago

JohnEstropia commented 2 years ago

What do you think of using a unified entry point for Mondrian APIs? Currently, we have these:

// Classic
mondrianBatchLayout {
    backgroundView.mondrian.layout
        .edges(.toSuperview)
}

// Structured
view.mondrian.buildSubviews {
    ZStackBlock {
        button.viewBlock
            .size(size)
            .padding(padding)
    }
}

One big problem we have is that it's very hard to recall which methods to use because the API entry points are all different.

I propose something like:

// Classic
Mondrian.layout {
    backgroundView.mondrian.layout
        .edges(.toSuperview)
}

// Structured
Mondrian.buildSubviews(view) {
    ZStackBlock {
        button.mondrian.build
            .size(size)
            .padding(padding)
    }
}

The names I used (Mondrian.layout, mondrian.layout, .mondrian.build) are all placeholders. The naming can be decided later, but my proposal is based on three principles:

  1. The global entry point (Mondrian.* in the example above) would become the same entry point for both classic and structured layout syntaxes.
  2. We will define two terms we would use to separate the classic and structured layout contexts. In the example above, I used
    • Layout for classic layout (Mondrian.layout(), backgroundView.mondrian.layout)
    • Build for structured layout (Mondrian.buildSubviews(), button.mondrian.build)
  3. The subview namespace is easily remembered from the enclosing context. So inside Mondrian.layout(), views would use .mondrian.layout and inside Mondrian.buildSubviews()views would use .mondrian.build. They don't have to be the same, but the pair should be very memorable. For example: Mondrian.build*() with inner view.mondrianBlock (building blocks)

This is a breaking change from the current syntax, but I think the biggest annoyance with the API right now is the bad discoverability of the methods. If you think the guidelines above are good, then we can comment on this Github issue on naming ideas.

JohnEstropia commented 2 years ago

Side note If it was possible, ideally we would have something like below:

// Classic
Mondrian.layout {
    backgroundView.mondrian // note here
        .edges(.toSuperview)
}

// Structured
Mondrian.buildSubviews(view) {
    ZStackBlock {
        button.mondrian // and here
            .size(size)
            .padding(padding)
    }
}

but because of autocompletion inconvenience, I understand that we still need the inner namespace view.mondrian.viewBlock. In the future I think we might find some tricks using @propertyWrappers or @dynamicMemberLookups, but that's a topic for another day.

JohnEstropia commented 2 years ago
Another naming idea: Classic layout Structured layout
New terminology Layout Anchor syntax Block Builder syntax
Entry point Mondrian.layout* { ... } Mondrian.build* { ... }
View accessor view.mondrian.anchor view.mondrian.block
muukii commented 2 years ago

notes: partially solved. next needs to consider namespacing in the expressions.