Are components really a good substitute for pages?
One of the things I get hung up on is that HTML-based sites are built up from pages, whereas Flex sites are one big glob of goo as far as the outside world is concerned. Some people see breaking up sites into pages as a bad thing (e.g., it forces you to jump through hoops to ensure that the proper data has been fetched on each page, etc.), whereas I see breaking up sites into pages as a good thing (in general, I agree with the REST folks, although I’m not religious about it).
~
For my project, I envisioned the following “pages” to start with:
- welcome
- new user
- album list + album detail
In the Flex world, the easiest way to split things up like this is to use a ViewStack. Coming from the HTML world, I find the idea that all the pages of your app are just lying around waiting to be displayed a bit unnerving, but I think it’s just something I need to get used to.
At this point, my app looks something like this:
<Application> <Script> all script for all pages goes here... </Script> <ViewStack id="vs"> <Panel title="welcome"> lots of stuff... </Panel> <Panel title="new user"> lots of stuff... </Panel> <Panel title="album list"> lots of stuff... </Panel> </ViewStack> </Application>
While the visual elements for all the “pages” of my app are split up in the ViewStack, the logic is all stored in one big block.
In Flex-land, the way to separate this out is to create components, so I tried that. At this point, my app looks like this:
<Application> <ViewStack id="vs"> <local:WelcomePanel id="welcomePanel" /> <local:NewUserPanel /> <local:AlbumInfoPanel /> </ViewStack> </Application>
Hooray for encapsulation! It looks pretty, right?
Well, now what happens when I want to hook these pages up? Let’s say there’s a button on the welcome panel that takes you to the new user page. Before, the code might have looked like:
<Button label="Create account" click="vs.selectedIndex = 1" />
Now, the same code would look like this:
<Button label="Create account" click="Application.application.vs.selectedIndex = 1" />
Ack! That looks like a severe violation of encapsulation! How does the component know that the application has a viewstack called “vs”, let alone what index to set?
Another possible solution is to add the handler to the application, not the button, like so:
<Script> <![CDATA[ function appInit() { welcomePanel.newAccountButton.addEventListener("click", this); } function handleEvent(event: Object) { if (event.type == "click" && event.target == welcomePanel.newAccountButton) { vs.selectedIndex = 1; } } ]]> </Script>
But this is a violation of encapsulation in the other direction. How does the application know that the welcome panel has a button named “newAccountButton”?
The only “clean” solution is to provide a formal contract between the components and the application. This could be done by having the component declare an event (newUserClicked) or having the application create API functions which the components can depend on. The problem is that all of these solutions feel like overkill, when all I want is the equivalent of “go to this page”.
In HTML, this is solved by the <a> tag, which essentially says “set the application state as described by ‘xxx.html’.” One could say that this violates “encapsulation” in that the page needs to know that xxx.html exists, but that’s part of the architecture of the web. URIs are meant to be meaningful, persistent, and represent states that you are guaranteed to be able to get back to.
I don’t have a perfect answer to this yet, but it’s something I’ve been thinking about a lot.
I think encapsulation is a relative thing. I agree with you that we’d better don’t overkill on it. You can do API, event handling, abstract factory, interfacing, delegation, decorator, etc. all those design patterns to make it more OO or encapsulation-alike. But at certain point, regardless, you HAVE TO tell the program what exactly page (component) you want to go. No escape on that.
I think the design goals are reusability, manageability, extensibility and flexibility, not just following encapsulation or some other OO techniques or concepts.
Keep going Sho! Can’t wait to see the final product!
Not surprisingly I’m in the REST camp, not so much because of programmer-side encapsulation issues, but because there a lot of tools out there that have been built with the REST nature of the web as an assumption.
You might try passing a reference to the ViewStack into the component:
and then the welcomePanel can act on the ViewStack locally. This way the component doesn’t have to know anything about the structure of the application and the application doesn’t have to that there is a Button inside the component which triggers the jump to the next state. Does this meet your encapsulation goals without being overkill?
Nice post, Sho.
We can do REST in Flex with the help of history management, but it’s not clean, and I don’t like to think of Flex applications like that.
http://www.klynch.com/archives/000076.html
http://www.livejournal.com/~mannu/263246.html
There’s the page-based paradigm of web applications, and there’s the window-based paradigm of desktop applications. I believe RIAs are somewhere in the middle, and as a result people coming from both camps are likely to be confused while doing their first apps (you’re not alone). It can take a little getting used to, and that worries me sometimes. We need more “getting started” type training material, but also some examples of how to migrate traditional web applications to the Flex way.
>How does the application know that the welcome panel has a button named “newAccountButton”?
It shouldn’t. WelcomePanel should just broadcast its own event — let’s call it “newAccount” — and handleEvent should care about that. The “newAccount” event would be a part of the public API for the WelcomePanel component. How the “newAccount” event got triggered — whether it was because of a mouse click or a network event or whatever — is what’s encapsulated.
Good points. And great work on the URL management code, BTW!
For me, the REST issue is not solely about encoding the state of the app in the URL. It’s a philosophy of how to put web apps together: the site is broken up into pieces, and the state information is passed back and forth.
Whether you like it or not, REST *is* important because the rest of the web (ha ha) depends on it. URLs are central to how search engines, bookmarks, the refresh button, deep linking, etc., etc. work.
As to Paul’s point.. passing in a ViewStack seems like it would be a good medium-weight solution. But I still miss the simplicity of . I mean.. I can get my head around components because I’ve done lots of Windows and Mac programming. But there is a simplicity to the Web that I hope we aren’t overlooking….
Although flex might look like on big glob it does not have to be that way.
Using deferred instantiation, the components in your viewstack can be really instantiated when they are required.
Decomposition of your application is very important. It is completely bad form to make anything but a trivial example in one big hunk of swf bytecode.
The samples application has a pretty neat way of doing something similar.
all loose mxml files that are pulled together at the last moment.
As far as your thoughts about encapsulation and chain of command, you might want to check out the lightweight microarchitecture for Flex called Cairngorm. it uses the frontcontroller/command patterns to solve changes between the main application states. Although you define this as “overkill”, it really is not for maintainable pages.
If you ask: why do I need patterns/architecture for something as trivial as a “go to page”: that is because of your conceptual starting point: a series of pages instead of a combination of screen elements that can interact.
The right way to solve the encapsulation is having your button broadcast a specific event, and the application listening for this specific event. That way the application doesn’t have to know about the existence of the button, the event can also originate from a menu, a keyboard shortcut etc. etc. Take a look at event dispatching and publish subscribe posibilities in Flex.
cheers,
ilya
Great thoughts. Thanks, Ilya! I’ve got a lot to learn about Flex, and it is helpful to hear from people like you who have thought about this more than I have.
Let me give more background on where my thoughts come from, including the conceptual starting point of “pages”, which I believe was important to the success of the web.
1) My main worry is that it is too easy for those of us who do programming as a living to forget how important simplicity is for the adoption of a new technology.
Concepts such as objects, events, MVC, etc., are fine when creating big applications or reusable components.
However, when creating a one-off project, people shouldn’t need to learn how to define, dispatch, and catch events just to get their applications built.
Let me take an example from Mac programming in the 80s. In many ways, HyperCard was a direct predecessor to the web. It used a page-based metaphor, along with a simplified scripting language. On the other end of the spectrum was MacApp, which was a framework for serious programmers.
HyperCard and MacApp are for two totally different classes of users and applications. You wouldn’t want to design a full blown desktop app in HyperCard, and you wouldn’t want to introduce MacApp to someone who wasn’t already very comfortable with OO concepts.
The beauty of the web is that it encompasses both types of users and applications. Very simple things can be built simply. Meanwhile, technologies like the J2EE stack exist to service larger, more complex sites.
Both sides of this spectrum are important. My concern is that Flex does not do enough to service the “keep it simple” end of the spectrum.
2) When I talk about things being a “big glob of goo” as far as the outside world is concerned, my concern is not with load time or componentization.
The issue is that the rest of the web is built with the assumption that applications are broken up into states, and that these states can be captured in the URL (see http://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm). Unlike the true REST advocates, I understand that session state and other factors make it impractical to always store state in the URL, but in 80% of the cases, the URL does just fine.
Web applications are not the same as desktop applications. Decomposing a web app into individual states that are captured through the URL has lots of indirect benefits (scalability, deep linking, indexability, etc.) that we should not take lightly.
Thanks for taking the time to write. I’ll keep posting more thoughts as I learn more about Flex.
Nice args!!! If we consider en[capsulating] the logice behind the stacks its a very simple arguement. It’s something like hit what you see. But we dont know what is there. In that case we can apply the logic from einstein’s theory… dont memorise something that you can look up…
I think view stack components can defined their own API when loaded that can publish events and frameworks. This can be used to initiate a single from any component like comp1.call(); that will return a map of that component to use… we have many comps in our mail application that does the same trick once loaded…
Ku Sir, I would expect some of your comments on this.
Tx
As a very experienced Web designer who’s spent the last few months totally immersed in Flex, I must admit that the difficulty associated with making a link/button/whatever in a custom component go to a state or stack index in anothr component was daunting and still occasionally gives me fits despite my growing comfort with event listeners etc.
To date remains also hard to find good documentation on this obvious migration issue; that is, web designer to Flex designer. Bottom line: the level of componentization that is obviously required if you were to build a 50 page site will require the web designer to learn a whole lot more actionscript than they knew or would like, with a likely ouotcome of them building it in a way less than idea way given their likley lack of OOP basics.
All that said, having been a Web designer with 12 years of deep experience in HTML/CSS, request/response web apps, I”m pumped on Flex and more eager than ever to get my OOP chops together so I can build complex Flex apps as they should be built.
My recommendation, which it seems is already in the works, is for much more upfront examples and sample code for the most likely migration issues.
cheers, ethan
Totally agree, Ethan. We’re working on a doc plan to address this. More examples and sample code!!
Nice post.
I’m studying Flex in these days, and I followed the very same path to handle navigation among views (opposed to pages): viewstack, custom components, events dispatching.
After some years of development for the web, I feel a little lost.. maybe, the AS/MXML should offer some way to describe user navigation concepts (simple jumps, wizard-like, etc.). It seems like Flex does a fine job designing the interaction between the user a single, estabilished view, but force you to code all the navigation logic.
What an outstanding post, thank you for climbing this acute issue.
Being deeply reassured that lots of folks would discuss your perspectives,
and I showed your writing to a close friend of mine.
And that is when the arguments began… We have
different opinions but, needless to say, no problem, be it just something routine
or genuinely important, should ruin a true friendship.
In my humble view, which has the right to
exist, the purpose you’ve made cannot be contested.
I didn’t have some expectations concerning that title, but the
more I was amazed. The writer did a fantastic job. I spent a few minutes studying
and assessing the truth. Everything is crystal clear
and understandable.