You are here: Home » NewsFeeds » Introducing the Famous Framework

Introducing the Famous Framework

We’re excited to announce that today we’re releasing a public alpha of our Framework open source, under the MIT license.

“Famous Framework,” you ask? “Didn’t you just release Famous in May?” Good question! In May we released our Engine, and today we’re releasing our Framework. Together, they are Famous.

We learned quite a bit from our initial release of Famous in April 2014, plus our subsequent year of developing Mixed Mode (now called the Engine). One lesson was that with a mission as ambitious as ours—to empower everyone to create beautiful experiences for any device—creating one library that tries to be ‘everything’ isn’t a tractable approach. In other words, the first version of our render engine was focused on too many goals: capabilities, performance, usability, extensibility, and approachability, to name a few.

This time around, we drew a line in the sand and chose to divide the responsibilities and conquer: the Engine layer is focused on capabilities and performance, i.e. “The Machine.” The Framework leverages the capabilities of the Engine but is focused on reusability, consistency, and integration with other technologies, collectively: “The User.”

For good measure, I’ll clarify again: our release today is an public alpha for the Famous Framework. Following is an introduction of the goals and design of the framework, but be aware that not every goal has yet been fully met, and we still expect to have some shifting ground as we learn from and respond to early user feedback. If this kind of disclaimer excites you, you are exactly who we’d like to have jamming with us today. If this kind of disclaimer makes you cautious, we invite you to keep an eye on the Famous Framework as it matures.

Goals

Let’s look at the goals of Framework in a bit more detail:

Goal: Component Reusability

Any component created by any developer should expose a consistent, discoverable interface that allows it to work predictably with any other component. We’ve driven our design around a “black box” model, where each component strictly isolates its own state—you can think of a component as an IC chip, a literal black box that has a clear “inside” and “outside,” with a standardized interface.

Integrated Circuit chips, our inspiration for “black box” components. Credit: Wikipedia, under Creative Commons

What’s more, every component is defined as a tree of other components, which are each defined as trees of other components, and each one can be reused inside yet other components—we like to joke about this reusability and composability of components as “turtles all the way down.”

Another analogue is a “Lego block”—Legos can have a whole variety of looks, feels, and functions, but they all snap together thanks to consistent interfaces. With Legos, you can put a pirate head on a princess body and snap it onto a space ship. In Framework, you can attach a data adapter to a scroll view and drop that into a header-footer layout, each as a single HTML tag. You can easily swap the pirate head for a goblin head just as you can easily swap the scroll view for a grid layout.

For example:

  
     
       
           ...

Note: Our full set of prebuilt layouts and components is still under development, but part of why we’re releasing Framework in public alpha is to give everyone an opportunity to create. We are consistently impressed and humbled by what our community creates with Famous, and we believe a solid foundation and ecosystem of reusable components will empower everyone to create incredible UIs incredibly fast.

Goal: Consistency

How do you build a large or complex project with Famous? Or with JavaScript in general? As teams and projects grow and change, software consistency becomes increasingly important for keeping pain low and productivity high. Code style standards can help, but JavaScript simply offers so many ways to approach any problem that it’s practically impossible to maintain consistency without some sort of enforcement at a framework level.

Breaking a large project into a number of consistent, predictable components with isolated responsibilities is a well demonstrated way to build software at scale. Enabling this consistency inside both Famous and JavaScript is a goal of Framework.

That said, there are several world-class frameworks and libraries out there in the Web ecosystem. We expect that some developers will choose to use Framework to build applications from start to finish, and many will choose to use it alongside other libraries. In both cases, it should be clean, consistent, and obvious to the developer how and where to create, edit, and configure Framework code. Importantly, the Framework shouldn’t get in the way of developers creating projects of any size, be they simple ads, reusable widgets, or full-on native/web applications.

Goal: Ease of Integration

“How do I use Famous within my existing application?” This is a tricky question. In the simplest case, you give a div to Famous, and it renders inside that div. This model is comparable to Flash, and it works just fine for applet-like, isolated experiences. What about when you want to go a level deeper, though? What if you want to use Famous with Angular’s data-binding? Or Meteor’s templating system? Or React’s component model? The Flash model of completely isolated applets doesn’t work when you want to bring the full experience of Famous together with the function of these other tools.

Until today, this has left developers with limited options:

  1. “Either-or” — Either you use Famous and build an app from scratch, or you use other tools like React, Meteor, etc.
  2. “Build an integration” — If you want to use Famous seamlessly with Angular, you must build an extensive integration library that hooks together every piece of each API. (example: Famo.us/Angular)
  3. “Isolate the experience” — i.e. go with the “Flash” model of applet-like experiences, isolating the rich experience of Famous from the rest of your application.

None of these options is ideal. Fortunately, we can do better. This is one of the goals of Framework.

How? The key is to build not only on top of technical web standards, which is what the Engine does, but also web authoring standards. Ultimately, using Famous should be as seamless and simple as using a div. You can include it, size it, move it, listen to events on it, hide it, pass content into it, query it with selectors, and even style it and bind data to it with your framework of choice—just like you do with a div. Abiding by this interface gains us foundational support from every standard library/framework out there.

For those familiar with AngularJS, here’s an example of how simple it should be to include a Famous component inside of an Angular app:

I'm inside a Famous component, and {{someAngularVariable}} ...

Or with jQuery:

$( ".inner" )
    .append( “” )
    .on(‘click’, function(){alert(‘click works on this component!’)});

In other words: good fences make good neighbors. Let Angular be Angular, let React be React, and let Famous be Famous. Rather than hooking up each API of each library wire by wire, by going one level deeper and integrating with HTML, DOM, and CSS itself, 95%+ of the effort of integrating with each of these technologies is already solved. This allows each tool to shine at what it does and allows the developer to use the best tool for the job—and it lets everyone use Famous in any application, on any device, pain-free!

Note that at our public alpha stage we haven’t yet finished all of the features of this “one integration to support them all,” but we’ve designed from the ground up with this goal in mind—e.g. by using the standard DOM event pipeline for Framework events and using HTML as the language for authoring the render tree. This means that the bulk of this functionality is already in place.

Design

Addressing all of these goals within the constraints and standards of the Web is an ambitious charge requiring thoughtful design. So, we pooled inspiration from existing, successful technologies along with our experiences with our previous products in order to come up with the design for our Framework.

Inspiration

Game Engines: Given that the Famous Engine is modeled after the capabilities of modern game engines, it made sense to start by looking at first-class game engines like Unity3d and Unreal Engine. How do these tools enable building richly interactive applications and interfaces? Two recurring patterns are:

  1. Component-based application structures and
  2. Data-driven architectures that prefer dealing with streams of data rather than procedural manipulation of state.

We designed our Framework around both of these principles: components are first-class citizens. Components are also modeled after finite state machines (a pattern common in game engines,) which map streams of data into application behavior. This keeps logic clean and localized, even as applications grow in complexity.

Web Frameworks: Given that we’re building a web framework, it made sense to look at how other folks approach similar problems. React’s Flux architecture and AngularJS both inspired the design of our Framework in different ways.

Flux (React) has championed the idea of a “unidirectional data-flow,” i.e. dealing with streams of data in a consistent, limited-side-effects way, using functional programming patterns. Why does this matter? Simply enough, it keeps application complexity low and encourages component reusability. Check and check—these are both traits that we need in our Framework.

Though not a web framework, we took quite a bit of inspiration from Haskell, a functional programming language that uses monads as a way to handle state changes or side effects like user input. The way our Framework exposes State values as data streams into Behaviors is directly modeled after Haskell’s monads. We strived, though, to keep the API familiar and comfortable to web developers. In other words, although our approach is modeled after monads, most developers should never have to think directly about the word or concept.

AngularJS is the most popular MVC-ish JavaScript framework in the community today. It brought some game-changing ideas to the JavaScript landscape, and several of those ideas have been adapted into the design of our Framework. For example, anyone coming from an Angular background should see same familiarity to the ‘flavor’ of the API, notably aesthetics and naming conventions.

Another similarity to Angular is our use of dependency injection. Though not common in JavaScript, dependency injection is more common in statically typed languages and enterprise software settings. Angular uses it as a tool for scaling applications and easily unit-testing code, plus as a way to manage reusable logic/state (Angular Services.) Check: we want this same level of rich unit-testability.

Web Languages: When tasked with building a framework for use on top of web languages, we figured we should study the semantics and patterns of those languages, and then to celebrate them in the design of the framework.

Consider HTML: although JSON is a more comfortable format for many developers to use for tree data structures, one thing HTML does better than JSON hands-down is describe the hierarchy of a user interface. That’s what it was created for! Even though Famous doesn’t use

s and s to represent its UI hierarchy—it uses a virtual render tree instead—it turns out that using HTML as the language for authoring the tree is elegant, familiar, and naturally compatible with other web tools. Why reinvent the wheel?

Now consider JavaScript: it’s a language that many people love to hate. It does have its fair share of quirks and challenges—but it’s also an extremely powerful language if harnessed properly. It has declarative aspects like JSON. It has functional aspects, to the point of being arguably more Lisp-like than procedural. Nonetheless, it has obvious stateful and procedural aspects, and most people who pick up the language for the first time will use it procedurally, similarly to Java or C++. How can we celebrate each of these powerful aspects of this unique language?

Meet BEST

What we came up with is Behavior Event State Tree. BEST is a new architectural pattern for building reusable, interchangeable components that behave predictably both in isolation and at scale. Our Framework is an implementation of BEST.

You can think of BEST as an event-driven evolution of MVC. MVC provides a Model for managing state and persistence, a View for presenting state to the user and gathering input, and a Controller for brokering communication and logic between the Model and View. Visually:

MVC has been used for decades to create software in all sorts of languages for all sorts of uses. Though MVC has been used to great success in many projects over the years, it also bears many well recognized pain points 0 1 2 3 4.

Many of those pain points center around the Controller, the oft-unkempt middleman of MVC. A common scenario in MVC is for state to be brought into the Controller from the Model, where it is locally duplicated and then sent off to the View. The user may manipulate that state (say, by filling out a form), which is then submitted back into the Controller. The Controller may store yet another copy of that state and/or possibly affect other pieces of application state as a result (e.g. log in a user; add an order to the cart). The Controller may or may not send that state back to the Model for persistence—it depends on what the application is trying to do.

Throw 20 churning developers and 100 evolving features at this application and just imagine how the code unfolds. Or better yet, don’t imagine: just look at any battle-worn MVC codebase. The Controller often bears the brunt of the inevitable complexity—synchronizing and managing each different version of state and their interdependencies across several features, plus shuttling those states off to the Model and the View gets complex quickly.

Thus the Controller is the key place where BEST diverges from MVC. In fact, you can think of BEST as an event-driven variant of MVC that breaks out the output/input responsibilities of the Controller into separate concerns: Behaviors and Events.

Example

Let’s walk through the pieces of BEST with a simple example.

Tree: It’s simplest to start with the Tree, as it should be very familiar and straight-forward. It’s the hierarchy of your component, and it’s written in HTML. This is one of the places where we get to celebrate the semantics of web languages. HTML is great for expressing UI hierarchies, and it’s already used pretty universally across the web for exactly that purpose.

Here’s an example Tree, which blends into using vanilla HTML (a div):

tree: `  
    
        
`

The Tree is simply a logic-free skeleton of your UI.

Events: Events are where you assemble the nuts and bolts of your application logic. For example, ‘On click, increment x by 1,’ or ‘On data load, update array of Tweets to be the list from the server, and set isLoading to false.’ Events are where we celebrate the procedural side of JavaScript.

All manipulation of application State occurs inside Event handlers, and Event handlers can manually kick off other Events. They’re really similar to methods in an object-oriented system, except these handlers are triggered by events rather than direct method calls.

Events are attached to elements of the Tree utilizing another familiar piece of JavaScript and CSS: selectors. Selectors allow Events and the Tree to be maintained as separate concerns, just like they allow CSS and HTML to be maintained as separate concerns in traditional web development.

In the example of the Tree above, the selector ‘#square’ allows us to target the node with that id, and we can declare Events that should be attached to it like this:

events: {  
    '#square': {
        'click': function($state) {
            $state.set('numberOfClicks', 1 + $state.get('numberOfClicks'));
        }
    }
}

Component state is managed through the StateManager, which is what that $state variable is referencing in this example. Why a StateManager? In part, because it allows us to maintain yet another separation of concerns, between our Events and our State.

State: State is simply enough the state — internal data and settings — of your component. Unlike an MVC Model, which generally has oodles of getter/setter logic for things like data retrieval and persistence, a BEST State is strictly declarative and logic-free. In other words, the State of a component can always be losslessly serialized and deserialized as JSON. This is where we celebrate the stateful and declarative sides of JavaScript.

states: {  
    numberOfClicks: 0
}

In the Event example above, when we incremented the numberOfClicks variable, it updates the same numberOfClicks variable whose default value 0 was declared here.

Behaviors: Behaviors complete the cycle, connecting to both States and the Tree. Behaviors are functions, in the sense of ‘functional programming’—this is where our Haskell inspiration shines through. They’re not just any functions, though—they’re “functions of States,” in the sense that a function f(x) is a “function of x”. We use dependency injection to match State names to parameters of Behavior functions—the State numberOfStates gets injected into any Behavior function that lists is as a parameter, like function(numberOfStates).

Just like Events, Behaviors are attached to elements of the Tree using selectors. Behaviors are even more CSS-like than Events, though. One way to think of Behaviors is as “functional CSS,” and indeed this is where we celebrate the functional side of JavaScript. For example:

behaviors: {  
    '#square': {
        'rotation-z': function(numberOfClicks) {
            return numberOfClicks * Math.PI / 2;
        }
    },
    'div' : {
        'background-color': 'red’,
        'text-content': function(numberOfClicks){
            return numberOfClicks + " clicks!";
        }
    }
}

In this example, before the square has been clicked, the square’s rotation-z evaluates to 0 * Math.PI / 2, or 0. The text-content of the div is “0 clicks!” When the user clicks the element ‘#square”, the Event handler “click” is fired. That handler updates the State numberOfClicks, which automatically causes both behavior functions to be re-evaluated. #square’s rotation-z will then reactively update to 1 * Math.PI / 2, and the content of the div will reactively update to “1 clicks!” And our cycle is complete!

Learn More

Hopefully this was enough to start to get you as excited about the possibilities of the Famous Framework as we are. We’ve got plenty of work ahead, but our open source release today means that we can work toward our goals together as a community.

We have a number of resources available for you to learn more about Framework. Check out the GitHub repo and explore the code—including many examples—or join our Slack channel and chat with our team and community directly. We hope to see you around!


 

Original article