root / branches / api-spec / alex / refactor.txt

Revision 7791, 23.1 kB (checked in by alex, 16 months ago)

adding note about configuration option change. Still haven't decided on new name for djConfig if it is going to be moved.

Line 
1Dojo 0.9
2========
3
4
5Intro:
6------
7
8Dojo is very clearly a success. The entire spectrum of web application needs is
9represented by Dojo's current user base. From high-profile, high-traffic
10installations to enterprise applications, Dojo provides the inventive, modular
11backbone of many application UIs. This success has created new problems, and
12Dojo 0.9 is aimed at addressing these issues while attempting to learn from our
13own recent history as well as the history of Ajax library development in order
14to deliver the very best, most useful, and most comprehensive set of tools for
15building great web experiences.
16
17This document addresses the non-widget namespaces of Dojo with the
18understanding that all widget infrasturcture along with all pruning/splitting
19of those namespaces is the exclusive perview of the Dijit maintainer.
20
21
22Axioms of Dojo 0.9/1.0 API design:
23----------------------------------
24
25    * Remove the magic
26
27      Too many 0.4.x APIs are magical. Where a plugin system is required, it
28      MUST NOT silently affect existing behavior. Requirement of additional
29      functionality SHOULD have an associated increase in API surface area.
30
31    * Pave the fast paths
32
33      It is our job to expose those things that can be responsibly used to
34      build great experiences. Nothing more. Given the constraints of the
35      browser environment, this means chosing winners.
36
37    * What we leave out is as important as what we put in.
38
39    * Code duplication in the trunk is unacceptable. Code duplication in the
40      leaves is undesireable, but more tollerable.
41
42    * Fewer idioms, better applied
43
44      Today, Dojo has no clear "identity" in its calling conventions and class
45      hierarchies. In many cases, there are too many classes to acheive what
46      appear to be single goals. In other cases, there are simple data
47      structures/classes operated on by multiple functions but that knowledge
48      or pattern is not shared by the rest of the system. Dojo 0.9 should seek,
49      from naming to class design, to reduce the number of "things" users need
50      to think about in the system. In many cases, this means giving users more
51      ways to take actions on fewer objects.
52
53    * Reward users for using more of Dojo, not less
54
55      In may ways this is subjective, but every K of file size should give
56      users something that they can appreciate on a daily basis.
57
58
59Major Proposed Changes:
60=======================
61
62
63Base vs. Core:
64--------------
65
66Splitting up the Dojo project has caused much consternation amongst committers
67and users. Contributors and committers are worried that their favorite features
68may not be easily available or that their modules will be moved out to some
69sort of second-class ghetto. Users are worried that Dojo will loose critical
70functionality that their applications depend on.
71
72Neither will happen.
73
74Many modules are going to be pruned and potentially split up in the creation of
75Dojo 0.9, but critical functionality will not be lost. Additionally, the new
76web-based build system will expose to users the entire spectrum of Dojo (dojo,
77dijit, dojox) as being available at build time. Users will still be able to get
78any, and all, of Dojo.
79
80For developers, there will be a new distinction: base vs. core. As outlined
81below, dojo.js will *always* include a useful set of functionality that all web
82applications can take advantage of. This is the Base.
83
84Dojo Core is a superset of Base. It includes modules which are of exceedingly
85high quality which the Dojo team is committed to maintaining and supporting for
86the long haul. Modules that are part of Dojo Core that are not part of the Base
87distribution (dojo.js) will be available in all builds and releases and can
88therefore be relied upon to be available. Users will need to explicitly include
89this functionality via <script> tags or dojo.require() calls, however.
90
91Modules which are experimental must be developed and maintained in dojox.
92
93The criteria for inclusion in Dojo Core are:
94
95    1.) a majority of Dojo contributors and commiters view the functionality as
96        necessaray for their applications
97    2.) the Core maintainer is convinced of the utility of the module in most
98        applications
99
100This is essentially a vote+veto structure, creating a higher barrier to entry
101for code into Dojo Core than has previously been applied.
102
103
104Promotion from dojox to Dojo Core:
105----------------------------------
106
107From time to time, modules may be deemed to be of high enough quality to be
108included in Core after a period of gestation in dojox. In order to reduce the
109burden on Dojo users, a compatibility module must be left in place in the dojox
110namespace for an entire major release cycle (1.x). Further migration from Dojo
111Core to dojox after the 0.9 split SHOULD NOT happen. If it does occur, it must
112only happen at major releases marks (1.0, 2.0, etc.). No compatibility shim
113will be required in these cases.
114
115
116dojo.js:
117--------
118
119dojo.js will "mean" one thing in a given environment (web, rhino, etc.).
120Including dojo.js in a runtime will always pull in the same code (all modules
121referenced in dojo.base) and builds will not add or remove from that
122functionality.
123
124Namespaces which are to be included in Dojo Base will be listed in a new
125"_base.js" file.
126
127
128Packaging and Builds:
129---------------------
130
131The package system is a Good Thing (TM).
132
133Today, though, the Dojo package system leaves little to the imagination about
134how slow synchronous network requests can make an application. There is
135built-in tension between allowing easy inclusion of code, locating that code
136on-disk as a developer, and deployment time performance. This tension has
137caused ongoing headaches for most non-trivial applications. Dojo's current
138approach to solving these problems has evolved over time and is in many ways
139half-finished. For Dojo 0.9 and beyond, the following policies and changes will
140be put in place:
141
142    1.) Files on disk
143
144        Today, files on disk do not always match the object structure that they
145        create. This cannot continue. Many modules have a
146        "src/modulename/common.js" file which includes the basic functionality
147        of a namespace, but there may be other files in a module which augment
148        the namespace. For instance, the following structure exists in dojo.io
149        in 0.4.2:
150
151        [dojo root]/
152            src/
153                io.js
154                io/
155                    __package__.js
156                    BrowserIO.js
157                    cometd.js
158                    common.js
159                    cookie.js
160                    IframeIO.js
161                    RepubsubIO.js
162                    RhinoIO.js
163                    ScriptSrcIO.js
164                    XhrIframeProxy.js
165                    xip_client.html
166                    xip_server.html
167
168        Today, io.js does a call to include io/__package__.js, which then
169        includes environment specific code in this way:
170
171            dojo.kwCompoundRequire({
172                common: ["dojo.io.common"],
173                rhino: ["dojo.io.RhinoIO"],
174                browser: ["dojo.io.BrowserIO", "dojo.io.cookie"],
175                dashboard: ["dojo.io.BrowserIO", "dojo.io.cookie"]
176            });
177            dojo.provide("dojo.io.*");
178
179        The object structure that is created, however, places a single
180        top-level interface into all of this functionality. dojo.io.bind()
181        wraps *most* of the included semantics, save those of dojo.io.cookie.
182        The justifications for this state of affairs hold up in part, but not
183        in whole.
184
185        There is a clear disconnect here. Instead of getting everything or
186        nothing, users must know ahead of time what they're getting when they
187        require a module, and it's possible to require modules that have little
188        or no effect on the callable "surface area" of the toolkit.
189
190        Starting with Dojo 0.9, the following structure will instaed be imposed
191        on this unruly namespace:
192
193        [dojo root]/
194            cookie.js
195            io.js
196            io/
197                _common.js
198                _browser.js
199                _rhino.js
200                cometd.js
201                iframe.js
202                repubsub.js
203                script.js
204                xip.js
205                xip_client.html
206                xip_server.html
207
208        And users will receive common-case functionality in the base Dojo
209        package.
210
211        While io.js may indeed continue in the tradition of __package__.js and
212        include environment-specific implementations of the APIs it exposes
213        (_common.js_, browser.js, _rhino.js, etc.), it will not provide
214        indirection. Note the use of leading underscores to denote files that
215        are "private" to the implementation of a particular namespace. This new
216        convention should be used whenever it is necessaray to defer
217        implementations, possibly in the case of multiple environments, to
218        external locations.
219
220        In Dojo 0.9, Builds will discover require statements in top-level files
221        that delegate down this way and will replace the top-level file with
222        the required code, similar to the way that dojo.js is replaced in build
223        environments today. Some special flag (perhaps in a comment?) may be
224        necessaray in these files to denote that they are "aggregators", but
225        that is an implementation detail.
226
227        The net result of these changes will be that modules which are not part
228        of the Base but which are still part of the Core will be includeable
229        with a single <script> tag. This reduces ambiguity about "what is
230        Dojo?" and allows the straightforward application of stock
231        performance-optimizing techniques to the files distributed with Dojo.
232
233        We should also investigate removing the "sources" of these aggregated
234        files from release distributions.
235
236    2.) ".*" and  "__package__.js" files will no longer be used in Core
237       
238        While support for these special cases may continue in the package
239        system, their use in Dojo Core will cease. The build-step replacement
240        of top-level or "aggregator" files will preform this function and will
241        also serve to remove the ambiguity of the ".*" semantic which today
242        does not actually gaurantee that all modules which reside in a
243        namespace are included.
244
245    3.) New functionality must be exposed on new objects
246
247        As outlined below (in the section "dojo.io"), things that provide new
248        functionality to an existing namespace but are not specified in the
249        core or "aggregator" include MUST implement this new behavior on new
250        namespaces, potentially sub-namespaces of the parent. This convention
251        will ensure symmetry between require() calls and calling conventions.
252
253
254dojo.io:
255--------
256
257The IO system features its own plug-in system which works fine, except that all
258cases where you want to do something different than XHR, you have to know about
259it and throw some semi-magical flags. This is dumb. Also, the design of bind()
260as a bid-directional tansport system was a clear mistake. Cometd does this, but
261bind() cannot and should not.
262
263In dojo 0.9, io transport functions are entirely disconnected from dojo.undo.
264Back-button handling is the responsibility of end developers via dojo.undo.*.
265
266The successors to dojo.io.bind() fully embrace their request/repsonse nature
267and the reality that they expose HTTP verbs:
268
269    dojo.io.bind() -->
270
271        // _base/io.js
272        dojo.xhrGet()
273        dojo.xhrPost()
274        dojo.xhrRwPost()
275
276        // dojo/io/iframe.js
277        dojo.io.iframe.get()
278        dojo.io.iframe.post()
279
280        // dojo/io/script.js
281        dojo.io.script.get()
282
283        // dojo/io/xip.js
284        dojo.io.xip.get()
285        dojo.io.xip.post()
286        ...
287
288        all bind() replacement APIs take the following argument structure:
289
290            {
291                url: "blah.html",
292
293                // all below are optional, but must be supported in some form by every IO API
294                timeout: 1000, // milliseconds
295                handleAs: "text", // replaces the always-wrong "mimetype"
296                content: {
297                    key: "value"
298                },
299                // browser-specific, MAY be unsupported in non-browser runtimes
300                form: dojo.byId("someForm")
301            }
302
303        Some of these variants may accept additional fields, but these are
304        specific to each variant. XHR requests, for instance, may include
305        "sync" or "headers" feilds to control the behavior of that particular
306        transport.
307
308        The return of all bind() successor functions MUST be a dojo.Deferred
309        object or a subclass thereof. All return handling is through
310        addCallback() and addErrback() methods of those Deferred objects.
311
312    dojo.io.queueBind() -->
313
314        dojo.io.queue("get", {/*args */})
315
316        dojo.io.queue will accept the name of any other dojo.io.* transport
317        function as its first argument. The result of a call to queue() is a
318        Deferred.
319
320    dojo.io.encodeForm -->
321
322        dojo.formToQuery()
323
324    dojo.io.argsFromMap() -->
325
326        dojo.mapToQuery()
327
328    dojo.io.FormBind -->
329
330        dojo.wrapForm(formNode)
331
332        wrapForm will need to be moved into its own file.
333
334    dojo.io.cookie.* -->
335   
336        dojo.cookie()
337
338        the getCookie() and setCookie() methods will be removed. A one and two
339        argument version of dojo.cookie() will be introduced in their place.
340        deleteCookie will be removed in favor of a two-argument call with null
341        or "" as the second parameter. If an object is passed as the second
342        param to cookie(), it may contain expiration and other relevent
343        properties and members and the string to be used as the value will be
344        expected in the object's "value" property.
345
346        getObjectCookie() and setObjectCookie() will be removed. Since
347        dojo.json is part of the core, users may easily serialize and
348        de-serialize objects themselves. Back-compat for "dojo.io.cookies"
349        (plural) will be removed.
350
351    // new I/O functions:
352    dojo.formToObject(formNode)
353    dojo.formToJson(formNode)
354    dojo.queryToObject(str)
355
356
357dojo.uri:
358---------
359
360    All code in dojo.uri.* that survives the merge will be integrated directly
361    into the package system. The names are being changed to "url" instead of
362    "uri" since everyone knows what the hell a URL is, even if they scratch
363    their heads over the academic differences between URI and URL.
364
365    dojo.uri.Uri -->
366
367        dojo.Url()
368
369    dojo.uri.dojoUri() -->
370
371        dojo.dojoUrl()
372
373    dojo.uri.moduleUri() -->
374
375        dojo.moduleUrl()
376
377
378dojo.query:
379-----------
380
381    An updated version of dojo.query will appear as a core piece of Dojo 0.9.
382    The result of all dojo.query searches will be an object of a new type:
383    dojo.NodeList. This class is described in "NodeList.txt", located in this
384    directory.
385
386
387dojo.event:
388-----------
389
390    Most of what's currently in dojo.event.connect()'s chain will be moved to
391    dojox.advice. In its place, two simplified functions will be introduced:
392
393        dojo.connect()
394        dojo.disconnect()
395        dojo.addNodeListener()
396
397    dojo.connect() will *only* handle "after advice" and will only take the
398    following call signatures:
399
400        dojo.connect({
401            source: objRef, // optional
402            sourceFunc: "thinger", // string or fp
403            dest: objRef, // optional
404            destFunc: "thinger2" // string or fp
405        });
406
407        dojo.connect(source, "funcName", dest, "funcName");
408
409    Further, dojox.advice.connect() will be broken up into:
410
411        dojox.advice.after()
412        dojox.advice.before()
413        dojox.advice.around()
414
415
416dojo.html and dojo.style:
417-------------------------
418
419These namespaces will be radically reduced and trimmed. It's not yet clear what
420form they will appear in, but some subset will be made available in the base
421with the rest "whacked" out of existance and some parts potentially moved to
422dojox.
423
424Some of this design work is contingent on getting answers to the outstanding
425"fast path" box model and style calcuation questions which are being worked on
426by Eugene.
427
428configuration:
429--------------
430
431Earlier versions of Dojo allowed the djConfig variable to provide a
432"allowQueryConfig" boolean flag in order to take debugging information from an
433easily modified location. This, however, required explicit permission from the
434djConfig flag which itself required its own <script> block. This was onerous
435and rarely used. It is also being replaced in 0.9 with a simpler system.
436
437Instead of requiring at *least* one extra <script> tag to configure Dojo, the
438system now supports a djConfig attribute on the <script> element which is used
439to include Dojo into the page. The value of this attribute much be well-formed
440JavaScript object literal syntax. Previously, putting Dojo into debugging mode
441required syntax such as this:
442
443    <script type="text/javascript">
444        djConfig = {
445            isDebug: true,
446            useXDomain: true
447        };
448    </script>
449    <script type="text/javascript" src="/path/to/dojo.js"></script>
450
451Could now be written as:
452
453    <script type="text/javascript"
454        djConfig="isDebug: true, useXDomain: true"
455        src="/path/to/dojo.js"></script>
456
457Note that the prior syntax is still available, but is not likely to be
458advantageous since the new variation is smaller and easier to use.
459
460The Split:
461==========
462
463
464APIs in Base:
465-------------
466
467    // loader
468    dojo.require()
469    dojo.provide()
470    dojo.moduleUrl()
471    dojo.dojoUrl()
472    dojo.registerModulePath() // or whatever it's called this week
473    dojo.platformRequire() // was kwCompoundRequire
474    dojo.version
475    dojo.is* // see below for details
476   
477    // i18n
478    dojo.requireLocalization() // need to find a way to make this code smaller, perhaps move to i18n?
479
480    // misc util
481    dojo.deprecated()
482    dojo.experimental()
483    dojo.getObject() // strToObj() ?
484    dojo.exists()
485    dojo.global()
486    dojo.doc()
487    dojo.addOnLoad()
488    dojo.addOnUnload()
489    dojo.cookie() 
490
491    // lang util
492    dojo.eval() // was dj_eval
493    dojo.hitch() // was dojo.lang.hitch
494    dojo.partial()
495    dojo.declare() // was dojo.lang.declare() new, lightweight version
496    dojo.extend() // was dojo.lang.extend()
497    dojo.mixin() // was dojo.lang.mixin
498    dojo.toJson()
499    dojo.fromJson()
500
501    // crockford funcs, et. al.
502    dojo.isString()
503    dojo.isArray()
504    dojo.isFunction()
505    dojo.isObject()
506    dojo.isArrayLike()
507    dojo.isAlien()
508
509    // array extras
510    dojo.forEach() // was dojo.lang.forEach
511    dojo.every() // was dojo.lang.every
512    dojo.some() // was dojo.lang.some
513    dojo.map()
514    dojo.filter()
515    dojo.indexOf()
516    dojo.lastIndexOf()
517
518    // node utils
519    dojo.byId()
520    dojo.query()
521    dojo.NodeList (described in "NodeList.txt") // any reason for a dojo.Node?
522    dojo.createElement(obj, parent, position)
523    dojo.place(node, refNode, position) // was dojo.dom.insertAtPosition
524
525    // style utils
526    // note, we must document the standards vs. quirks vs. explicit box model
527    // toggling upshots of using the following box functions
528    dojo.borderBox(node) // returns { w: 0, h: 0 }
529    dojo.borderBox(node, boxObj)
530    dojo.marginBox(node) // returns { w: 0, h: 0 }
531    dojo.marginBox(node, boxObj)
532    // in coords, x and y are absolute while w and h are border-box
533    dojo.coords(node)  // { x: 0, y: 0: w: 0, h: 0 }
534    // need a setter for coords or a moveTo method?
535    dojo.style(node) // returns computed style obj
536    dojo.style(node, propertyName) // pixel value of property
537    dojo.style(node, propertyName, value) // sets it
538
539    // I/O // was dojo.io
540    dojo.Deferred
541    dojo.callQueue("queueName", "dojo.xhrGet", {/*args */}) // returns Deferred
542    dojo.xhrGet()
543    dojo.xhrPost()
544    dojo.rawXhrPost()
545    dojo.formToQuery()
546    dojo.mapToQuery()
547    dojo.wrapForm(formNode) // was FormBind
548    dojo.formToObject(formNode)
549    dojo.formToJson(formNode)
550    dojo.queryToObject(str)
551
552    // event
553    dojo.connect()
554    dojo.disconnect()
555    dojo._addNodeListener()
556
557    // effects
558    dojo.fx // was dojo.lfx
559    dojo._IAnimation
560    dojo._Animation // must be a Deferred
561    dojo._PropertyAnimation
562    dojo._defaultEasing()
563    dojo.fadeIn()
564    dojo.fadeOut()
565    dojo.slideIn() // new, replaces wipeIn
566    dojo.slideOut()  // new, replaces wipeOut
567    dojo.animateProperty() // was dojo.lfx.propertyAnimation
568
569    // color functions. Were in dojo.color
570    dojo.extractRGB()
571    dojo.rgb2hex()
572    dojo.hex2rgb()
573
574    // environment test variables (boolean):
575    dojo.isBrowser
576    dojo.isRhino
577    dojo.isSpidermonkey
578    dojo.isMobile // ?
579
580    // browser test variables
581    // integers corresponding to version numbers
582    dojo.isFF // may need to roll up gecko rendering numbers
583    dojo.isIE
584    dojo.isKonq
585    dojo.isSafari
586    dojo.isOpera
587
588    // desupported:
589    //      dashboard
590    //      WSH
591    //      Adobe SVG (already dead)
592    //      Native SVG
593
594    // may need to add:
595    //      Apollo
596    //      WPF/E
597    //      Mobile browsers:
598    //          NetFront
599    //          Opera Mobile
600    //          PIE
601    //          BlackBerry
602    //          Reindeer (S60 webkit)
603
604In Core but not Base:
605---------------------
606
607    dojo.undo
608    dojo.dnd // modulo trimming and rework
609    dojo.lfx.html (everything not listed above)
610    dojo.rpc
611    dojo.string
612    dojo.i18n
613    dojo.html and dojo.style extras
614    dojo.topic // was dojo.event.topic
615    dojo.data
616    dojo.io.script
617    dojo.io.iframe
618    dojo.AdapterRegistry
619    dojo.validate
620    dojo.date
621    dojo.fx
622        _Chain
623        _Combine
624        // things users might actually use
625        chain()
626        combine()
627
628Unsure:
629-------
630
631    dojo.regex (?)
632    dojo.ns
633    dojo.dom // most of this NS can be removed, but where does the rest go?
634
635Moved to dojox:
636---------------
637
638    dojo.gfx
639    dojo.cal
640    dojo.charting
641    dojo.storage
642    dojo.dot
643    dojo.sync
644    dojo.DeferredList
645    dojo.profile
646    dojo.svg
647    dojo.crypto
648    dojo.flash
649    dojo.math.* (math.js will remain, albiet trimmed)
650    dojo.collections.*
651    dojo.behavior
652    dojo.uuid
653    dojo.xml.XsltTransform
654    dojo.advice // was dojo.event.connect()
655    dojo.selection
656    dojo.io.cometd
657    dojo.io.repubsub // was dojo.io.RepubsubIO
658    dojo.io.xip
659
660
661Removed:
662--------
663
664    dojo.render
665    dojo.animation
666    dojo.graphics
667    dojo.logging
668    dojo.props
669    dojo.debug (replaced by console.*)
670    dojo.xml.Parse
671    dojo.text
672    dojo.docs (?)
673
674
675A Note On Function Movement:
676============================
677
678Dojo committers will note that some functionality that was once left to utility
679namespaces is being migrated directly into the core of the system. This is by
680design.
681
682Today, many namespaces (dojo.a11y, dojo.uri.*, etc.) are assumed to be better
683left alone as utilities because there are scenarios that do not demand them.
684This, generally, is a false assumption. Most non-trivial uses of Dojo require
685many of these functions and in serveral places, "lower level" implementations
686within the bootstrap or in other modules exist in order to provide the same
687behavior to code that needs to run earlier in the lifecycle. Correcting this
688false choice is something that we should take the opportunity to do in 0.9. We
689have enough experience with the existing namespaces to now say what's really
690critical and what's not.
691
692vim:et:ts=4
Note: See TracBrowser for help on using the browser.