Status: | DRAFT, under review (initial content is subjective interpretation of list discussions by author, for review and contributions by others) |
Intended Audience: | Apache Flex FlexJS SDK/Compiler developers (a separate document could be created for users of FlexJS SDK releases, based on relevant content) |
Review time frame: | annual |
PAYG - "Pay as you Go"
Pay as you go (PAYG) is a general principle for FlexJS whereby the SDK framework code (the actionscript codebase used to create FlexJS SDK library swcs) supports incremental functionality in components. The goal is to provide the possibility for a lower level of performance or memory impact of applications built using the framework (compared to not applying PAYG to the framework code). PAYG may imply a small performance or memory cost in the framework to support its implementation, but that is recouped in its use. Some PAYG aspects may also be provided by or supported by compiler options which may not have any corresponding framework overhead.
What is not PAYG?
todo: list any possible common misconceptions (or remove this topic)
What is 'Paying' in PAYG
'Paying' is defined as conscious decisions by developers to include functionality that has a measurable and substantial performance or memory impact. The ‘as you go’ implies ‘incremental functionality’. In simple terms, it means that you do not include performance and memory ‘cost’ for functionality you don’t use.
The ‘paying’ aspect of PAYG does not include 'developer effort' as ‘payment’ or ‘cost’. This means that for some projects using a full PAYG component set, additional developer effort will be required, however the FlexJS project team is working to reduce this by composing sets of general purpose components that include ‘general purpose’ functionality (See Doesn’t supporting PAYG have its own cost? below).
How is ‘measurable and substantial’ defined to determine thresholds for default functionality?
Determining whether something has merit for inclusion in default functionality or is categorised into ‘as you go’ is something that has generated discussions in the flex lists and has resulted in disparate views. Perhaps part of the reason for this is a lack of clarity and/or consensus as to whether ‘paying’ includes developer effort or not (see What is ‘Paying’ above).
Discussion areas:
How do we decide what is default functionality and what is ‘as you go’?
What does ‘substantial’ mean? And in what context?
Are there exceptions or inconsistencies that are justifiable (and under what conditions)?
Why PAYG?
To target javascript, the FlexJS SDK and components needed to be substantially different to the legacy Flex 4 SDK which is SWF-only (no need for details why here, but maybe link to other content?). Given this need to make large changes, the opportunity was also taken to review general improvements to the SDK component architecture to address some common criticisms of the Flex 4 component set. One of those criticisms (the size of compiled applications) relates to the size of some of the Flex 4 base classes which, in simple terms, is the opposite of PAYG. Implementing PAYG in FlexJS has the goal of maintaining the possibility of a full range of functionality, but making it more incremental/opt-in.
Doesn’t supporting PAYG have its own cost?
Performance
Yes, it may contribute to performance costs, because there is some overhead in supporting a runtime based composition model. However, the general principle is that establishing the ability to compose functionality (especially via mxml) is worth the overhead. For features that are opt-in via the compiler, these features may not have an extra framework cost.
Developer Effort
Because there can be extra effort to compose incremental functionality for common use cases, it would likely result in extra developer effort being required if the developer was using a full PAYG approach to development on every project. For this reason, the ‘Express’ component set exists which has pre-composed components that feature combinations of functionality to suit more general use cases. The intention behind this is to reduce the time and effort required in the use of common components by including the more commonly needed functionality.
How do we decide if a piece of functionality should be default/baseline functionality or ‘extra’/optional functionality?
todo: this needs to provide an actual guide for decision making. Currently it has questions that might help to arrive at such a guide
Suggested goal for this topic area: a decision framework with weighting on areas of importance when considering various factors.
The aim is to remove any lack of clarity and reduce any future debate around specific topics to a discussion around relevance to documented (consensus-based) criteria.
Current status: There is no definitive guide, suggested discussion topics
Discussion areas (What factors could be considered for this decision process, and what is their relative weighting in decisions).
1. What is ‘minimum’ vs. pareto-based functionality?
-Is the effort of avoiding functionality worth more than the cost of including it (is there a practical value in avoiding it - will any developer actually prefer to use the 'minimum' or is it to remain 'true' to PAYG principles, for example) .
-There appears to be general agreement that the Flex 4 sdk had ‘too much’ swiss-army-knife code, attempting to cover too much functionality in base classes and therefore had extra un-needed ‘weight’ or baggage in most applications. This has been often used as the justification for a PAYG approach, what is the right balance of functionality for the Express package.
Are there downsides to aiming too much in the opposite direction, or is it always justified? For FlexJS, what is the 20% of functionality/features that address 80% of needs (assuming pareto principles apply – 80/20 is only indicative for discussion here, not literal values). Is this always ‘express’ vs. ‘baseline’ or not? If baseline is not in line with pareto principles, what percentage of developers would find it useful to work with directly (or is it mainly intended for support of ‘express’ and other modules)?
2. How much ‘weight’ does an optional piece of functionality add? Is there a way to specify a threshold for what is considered baseline/default and what (for example) would be included in express component set?
3. Do additional compilation steps automatically eliminate un-used functionality, and how does that relate to PAYG?
-If yes, this could favour inclusion of greater functionality by default, because the ‘payment’ for unused functionality is essentially zero if it is optimised away by (for example, via Google Closure Compiler) when it is not used. Counter: what disadvantages are there with relying on an external process to do this?
4. Are all targets considered equal?
Discussions on the list have included suggestions that we favour the javascript target over SWF in terms of performance as a priority, with SWF target aiming more for consistency in results with the javascript target. If this is true then it might mean that the external compiler optimizations (GCC) play a greater role in determining what default implementations for ‘PAYG’ should contain (if unused functionality is optimized out of the production code). How does that fit in to PAYG?
5. What other factors might be important in the future?
-General trends continue to be increasingly faster processing, and greater memory capacity across device targets. Decisions have already been made about ES5 compliance as minimum target browser specification for javascript. Do we need to anticipate the target context (e.g. es6?) 2-4 years out when FlexJS has an (anticipated) healthy user base of developers?
The sands keep shifting, the idea here is to draw a line in the sand, at a point that anticipates the shape of the dunes in the relevant future. We have done this before.
As an example, here is a guiding statement that was documented 4 years ago which was true then, but has been addressed in ES6 (WeakMap) and is now supported by current browsers (but notably, not IE 9 -10, for example, which are still considered current FlexJS targets).
“Also, since Dictionary and weak references don't really exist on HTML/JS, the new framework will not use them on AS and you may have to explicitly call release() or some other API on some objects to make them available for garbage collection.“
At the outset FlexJS included IE8 as a target browser and that is no longer the case. The example above is intended to be illustrative of the changing ‘landscape’ only. The simple question here is whether, considering what we expect even only one year from now, external changes may impact decisions on any PAYG aspects now. This could include javascript language itself or browser performance.
-Does what we decide now make sense for possible future compiler targets (i.e. other than swf or javascript) (note: there are no established plans for other targets, but the possibility of considering them might factor in, although probably/perhaps this is a low-weight factor).
How does PAYG get implemented?
todo: Discuss and populate
Framework
1. Strands and Beads
The ‘strands and beads’ concept is a metaphor for adding extra functionality (beads) onto a component (strand). Beads represent the modular units of functionality that can be selected and composed together to configure functionality added to the base component (strand). Component sets such as ‘Express’ include more general functionality which may into reduce developer effort for the general case of application development.
Questions
Where do beads with additional functionality go? What determines inclusion in the sdk and which module (e.g. would some beads only be part of Express or are they central and Express is only a set of components composed of commonly used beads)? What criteria would we potentially have to suggest them being excluded from FlexJS (i.e. ‘that belongs more in an external library’ if that is ever a need).
General discussions to derive guidance:
Null Checks
todo: discussion When to include, when to exclude
Other ‘safety’ aspects
-Automatic removal of listeners/general ‘cleanup’ when removing functionality
Initial content: This should be done (in a bead) when a bead is intended to be removable, which is unlikely for the most basic implementation of that 'type' of bead. Therefore it should not be in the base class if the incremental functionality for that bead is inheritance based.
Approaches to Incremental functionality via beads
todo: discussion (resolve varied views)
Is there one preferred approach to coding beads (or?) ?
-New (isolated) Beads (copy paste with extra functionality) vs. DRY
-Bead inheritance and/or utility functions
-Beads of Beads?
Compiler
1. Compiler options.
initialised vs. uninitiliased variables
This is a topic of current discussion, with differing views.
todo: discussion (resolve varied views)
Question:
is it better to be compliant with actionscript language expectations as a priority (e.g. myUninitialisedObjectVar === null vs. myUninitialisedObjectVar === undefined in javascript) or is this a case where we forgo compliance with actionscript expectations in favour of minimal code (e.g. force developer to use .myUninitialisedObjectVar == null for compatibility between targets)
Partial answer: we can support initialisation to defaults as specified by actionscript, and create a compiler option to switch it on or off. So the question then becomes : which is the default? Is full PAYG more important than compliance with actionscript (in the javascript output)? For the optional approach, what is the capacity for problems arising from having it in one state for the framework code vs. a different state for the sdk user's code?