Stylistic concerns for large application

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Chris Smith

    Stylistic concerns for large application

    'Morning,

    Within the next few months, I'm going to embark upon a comparatively
    rather large base of JavaScript code to be called from a web browser
    environment. Not too awfully huge, but probably between 10K and 15K
    LoC. Having seen only the kinds of scripts that support interactive web
    pages, I'm dreading trying to stretch JavaScript that far. Has anyone
    here done something like this, and want to share some experience?

    In my feeble experience, I've adopted a few stylistic tendencies that I
    wanted to run by those of you with more experience, to see if you
    foresee problems. Here are a few questions:

    1. JavaScript books I've seen all seem to define object methods as
    functions with a global name, and then assign them into an object as a
    function. I'm concerned that this leads to a lot of global names. I've
    been looking at using anonymous functions as an alternative, as in:

    /* constructor */
    function Foo()
    {
    /* methods */

    this.foo = function()
    {
    ...
    }

    this.bar = function(baz)
    {
    ...
    }

    /* fields */
    this.kazoo = this.foo();
    this.kazam = null;
    }

    That way, I only define one global name, and don't end up with ugly
    temporary names that only exist to be used in assignments for object
    methods.

    2. What do you normally do with methods that are only intended for
    internal use within an object, and not to be called from the outside
    world? Do you tag them somehow (I've been looking at a leading
    underscore... I generally dislike these kinds of identifier tags, but in
    the absence of language support for visibility, I might be convinced to
    adopt one), or merely provide separate documentation of publis
    interfaces for each object and don't include them there?

    3. How do I combine lots of JavaScript source files into a single web
    page. Having zillions of script tags seems hokey, but I can't find a
    way to include one JavaScript source file from another, so it looks like
    everything does need to be included directly from the HTML source. Any
    other solution? Does this mean that the page will wait on the loading
    of this large amount of JavaScript before it finished its own loading?

    I'm considering solutions like having zero-size frames in a frameset
    that load other pages with JavaScript code in them, to avoid holding up
    the loading of functional pages. Any other ideas?

    --

    The Easiest Way to Train Anyone... Anywhere.

    Chris Smith - Lead Software Developer/Technical Trainer
    MindIQ Corporation
  • Richard Cornford

    #2
    Re: Stylistic concerns for large application

    "Chris Smith" <cdsmith@twu.ne t> wrote in message
    news:MPG.199053 e523d35fbc98987 c@news.altopia. com...
    <snip>[color=blue]
    > ... . I've been looking at using anonymous
    >functions as an alternative, as in:
    >
    > /* constructor */
    > function Foo()
    > {
    > /* methods */
    > this.foo = function()
    > {
    > ...
    > }
    > this.bar = function(baz)
    > {
    > ...
    > }
    > /* fields */
    > this.kazoo = this.foo();
    > this.kazam = null;
    > }[/color]

    Alternatively:-

    /* constructor */
    function Foo()
    {
    /* fields */
    this.kazoo = this.foo();
    this.kazam = null;
    }
    Foo.prototype.f oo = function(){
    ...
    }
    Foo.prototype.b ar = function(){
    ...
    }

    - the functions assigned to the prototype become methods of the object.
    They do not create named functions in the global namespace and only one
    function object is created (rather than one function object for each
    inner function assigned as a method from within the constructor for each
    invocation of the constructor) for each method.

    <snip>[color=blue]
    > 2. What do you normally do with methods that are only intended for
    > internal use within an object, and not to be called from the outside
    > world?[/color]

    Make them private members:-

    <URL: http://www.crockford.com/javascript/private.html >

    (also use groups.google.c om to locate a clj thread with the subject
    "closures, what are they good for?" for privat static members).
    (and also locate and read the page on inheritance on www.crockford.com).

    <snip>[color=blue]
    >but in the absence of language support for visibility,[/color]
    <snip>

    The language has supported visibility (though not explicitly) since
    version 1.1.

    <snip>[color=blue]
    >3. How do I combine lots of JavaScript source files into a
    >single web page.[/color]

    Depends on the specific requirement but document.write can be used by
    one script to write one or more SCRIPT tags into a page with their SRC
    attributes set to appropriate files (my experience is that this is most
    reliable if it is the last operation within a particular script section
    or file). Other dynamic JS file loading techniques are not very
    cross-browser.

    <snip>[color=blue]
    >Does this mean that the page will wait on the loading of this
    >large amount of JavaScript before it finished its own loading?[/color]

    Mostly yes, but you can set a flag to false at the top of a file and
    true at the bottom and not use the contents of that file until the value
    of the flag is true.
    [color=blue]
    > I'm considering solutions like having zero-size frames in a
    > frameset that load other pages with JavaScript ...[/color]
    <snip>

    I tried that a couple of years ago and decided that it was not worth the
    effort. Frames introduce lots of issues, both with scripting and in
    general. Given the choice (and any server-side scripting/include
    support) I would not now go anywhere near framesets. If you set your JS
    files to cache properly on the client you should not suffer for their
    size more than once.

    Richard.


    Comment

    • Lasse Reichstein Nielsen

      #3
      Re: Stylistic concerns for large application

      Chris Smith <cdsmith@twu.ne t> writes:
      [color=blue]
      > Okay, fair enough, but I'm beginning to see that this answer interacts
      > with what you say about hiding members... if I define methods in the
      > manner you describe above, then they don't have access to any more of
      > the object than an external observer would.[/color]

      Javascript objects are completely transparent. There is no more to
      access than what an external observer can see.

      If you add the so-called "private members" then it is not really
      supported by Javascript objects, but it can be *emulated* by scoped
      variables shared by the methods.
      [color=blue]
      > That's not really consistent with a set of reasonable visibility
      > rules (that is, I never really want to hide an object's state from
      > itself),[/color]

      You cannot hide anything from anybody using only Javascript objects.
      [color=blue]
      > so the only reason I'd define functions in the prototype is
      > the performance gain from only defining the function once rather
      > than per-object?[/color]

      It is. There is no noticable difference between
      ---
      function Foo(){}
      Foo.prototype.b ar = function(x){thi s.last=x;alert( x)};
      ---
      and
      ---
      function Foo(){
      this.bar = function(x){thi s.last=x;alert( x);}
      }
      ---
      when you write "new Foo()". The first have better memory usage
      if you create more objects.
      [color=blue]
      > Hmm. Can you point to some "other" techniques?[/color]

      In some browsers, changing the "src" property of a script element will
      load the code. In others it won't.
      In some browsers, creating a new script element with DOM methods will
      load the code. in others it won't.
      [color=blue]
      > My concern is that if I have a page with thirty-five to fourty
      > 'script type="text/javascript" src="..."' lines at the top, that the
      > browser won't finish loading and rendering the page until it makes
      > all thirty-five to fourty HTTP requests for the source files, parses
      > them, and finishes running them. After all, what if they contained a
      > document.write somewhere?[/color]

      You can add the "defer" attribute to the script tags:
      <script type="text/javascript" src="foo.js" defer="defer"></script>
      All that means is that you promise that the source contains no
      document.write' s, and that parsing can continue without waiting for the
      code to be loaded and run.

      /L
      --
      Lasse Reichstein Nielsen - lrn@hotpop.com
      Art D'HTML: <URL:http://www.infimum.dk/HTML/randomArtSplit. html>
      'Faith without judgement merely degrades the spirit divine.'

      Comment

      • Richard Cornford

        #4
        Re: Stylistic concerns for large application

        "Chris Smith" <cdsmith@twu.ne t> wrote in message
        news:MPG.199069 2d22ac769398987 d@news.altopia. com...
        <snip>[color=blue][color=green]
        >>- the functions assigned to the prototype become methods
        >>of the object. ...[/color][/color]
        <snip>[color=blue]
        >Okay, fair enough, but I'm beginning to see that this answer
        >interacts with what you say about hiding members... if I
        >define methods in the manner you describe above, then they
        >don't have access to any more of the object than an external
        >observer would. That's not really consistent with a set of
        >reasonable visibility rules (that is, I never really want to hide
        >an object's state from itself), so the only reason I'd define
        >functions in the prototype is the performance gain from only
        >defining the function once rather than per-object?[/color]

        Functions assigned to properties of the prototype will not have access
        to private members of their objects (though they could still access
        private static members) but in practice no all object methods will need
        access to an object's private members. They will have access to all of
        the public methods of their own object instance so they will be able to
        call "privileged " methods that can interact with private members. It is
        a matter of deciding which methods to define in which context to achieve
        the member access that is needed and get the best compromise between
        performance, resource use and the desired level of encapsulation.

        Whichever approach you use to defining a specific method you will still
        be avoiding filling the global namespace with named function
        definitions.

        <snip>[color=blue][color=green]
        >> ... . Other dynamic JS file loading techniques are not
        >>very cross-browser.[/color]
        >
        > Hmm. Can you point to some "other" techniques?[/color]

        <URL: http://tinyurl.com/d25q >
        [color=blue][color=green]
        > > <snip>[color=darkred]
        >> >Does this mean that the page will wait on the loading of this
        >> >large amount of JavaScript before it finished its own loading?[/color]
        >>
        >>Mostly yes, but you can set a flag to false at the top of a file and
        >>true at the bottom and not use the contents of that file until
        >>the value of the flag is true.[/color]
        >
        >Not sure what that means. My concern is that if I have a page with
        >thirty-five to fourty 'script type="text/javascript" src="..."' lines[/color]
        at[color=blue]
        >the top, that the browser won't finish loading and rendering the page
        >until it makes all thirty-five to fourty HTTP requests for the source
        >files, parses them, and finishes running them. After all, what if they
        >contained a document.write somewhere? The browser doesn't
        >know that they just define code that's called separately by the
        >browser in response to events. My feeling is that this could take
        >thirty seconds on a slow day before the page even renders.
        >
        >An ideal solution would be to actually locate and load the code on
        >demand as it is actually used, but I'm giving up on that one, I think.
        >Nevertheless , I'd like to have it load in the background, and then
        >call it later.[/color]

        <quote cite="http://www.w3.org/TR/html401/interact/scripts.html">
        defer [CI]
        When set, this boolean attribute provides a hint to the user agent
        that the script is not going to generate any document content
        (e.g., no "document.write " in javascript) and thus, the user agent
        can continue parsing and rendering.
        </quote>

        <snip>[color=blue][color=green]
        >>... I would not now go anywhere near framesets.[/color]
        >
        >That's actually not an issue, as framesets are already an important
        >part of the application. Not my choice... the specification I'm
        > implementing says that an object starts out by walking up the
        >frame structurse looking for a frame that defines a JavaScript
        >method with a particular name... so the page that's being loaded
        >MUST have a parent frame, at the very least.[/color]

        Surely generalised code should check the current window for the function
        name prior to chaining up through the parents? (so that it can work
        without a frameset as well as with one).

        Incidentally, if you have a frameset the frameset page is normally
        fairly constant and you can load script into it so they would not need
        to be re-loaded when any frame contents changed.

        But do simultaneously test in a good range of browsers.
        [color=blue][color=green]
        >>If you set your JS
        >>files to cache properly on the client you should not
        >>suffer for their size more than once.[/color]
        >
        > Wouldn't they be parsed each time? I'd think that parsing and walking
        > through 10K LoC would be non-trivial.[/color]

        10K is really not that big and parsing is quick compared to downloading.

        Richard.


        Comment

        • Richard Cornford

          #5
          Re: Stylistic concerns for large application

          "Lasse Reichstein Nielsen" <lrn@hotpop.com > wrote in message
          news:el099lwl.f sf@hotpop.com.. .
          <snip>[color=blue][color=green]
          >>In some browsers, changing the "src" property of a script
          >>element will load the code. In others it won't.[/color]
          >
          >I couldn't find one where that worked, maybe I am doing something
          >wrong. I seem to remember having heard that it should work.[/color]

          IE 5+ but there is no point in using it as the createElement method
          works OK there as well.

          <snip>[color=blue]
          > var script = document.create Element("script ");
          > script.src = "../../alerter.js";
          > document.body.a ppendChild(scri pt);
          > ---
          > together with the file "alerter.js " containing:
          > ---
          > alert("it works");
          > ---
          > worked (it said so!) in IE6, Mozilla FB and Opera 7.[/color]
          <snip>

          Which Opera 7 version? When I tried this a couple of months back I could
          not get it to work in Opera 7 up to version 7.02 (I think). It would be
          nice if they have fixed it because then dynamic DOM level 2 support
          might be taken to imply the ability to dynamically load scripts.

          Richard.



          Comment

          • Richard Cornford

            #6
            Re: Stylistic concerns for large application

            "Lasse Reichstein Nielsen" <lrn@hotpop.com > wrote in message
            news:ispl9mwg.f sf@hotpop.com.. .
            <snip>[color=blue]
            > It is. There is no noticable difference between
            > ---
            > function Foo(){}
            > Foo.prototype.b ar = function(x){thi s.last=x;alert( x)};
            > ---
            > and
            > ---
            > function Foo(){
            > this.bar = function(x){thi s.last=x;alert( x);}
            > }
            > ---
            >when you write "new Foo()". The first have better
            >memory usage if you create more objects.[/color]
            <snip>

            The first should also execute quicker. Maybe not noticeably quicker but
            almost certainly measurably quicker.

            Richard.


            Comment

            • Lasse Reichstein Nielsen

              #7
              Re: Stylistic concerns for large application

              "Richard Cornford" <richard@litote s.demon.co.uk> writes:
              [color=blue]
              > Which Opera 7 version?[/color]

              Opera 7.20 beta 2.
              [color=blue]
              > When I tried this a couple of months back I could
              > not get it to work in Opera 7 up to version 7.02 (I think).[/color]

              I checked, and it doesn't work in the last official
              release, O7.11.

              I admit I was a little surpriced that it worked, as I thought I
              remembered that it shouldn't.

              /L
              --
              Lasse Reichstein Nielsen - lrn@hotpop.com
              Art D'HTML: <URL:http://www.infimum.dk/HTML/randomArtSplit. html>
              'Faith without judgement merely degrades the spirit divine.'

              Comment

              • Lasse Reichstein Nielsen

                #8
                Re: Stylistic concerns for large application

                "Richard Cornford" <richard@litote s.demon.co.uk> writes:
                [color=blue]
                > The first should also execute quicker. Maybe not noticeably quicker but
                > almost certainly measurably quicker.[/color]

                Argh! Yes! I meant to say "apart from efficiency", but I somehow
                forgot to write it.

                /L
                --
                Lasse Reichstein Nielsen - lrn@hotpop.com
                Art D'HTML: <URL:http://www.infimum.dk/HTML/randomArtSplit. html>
                'Faith without judgement merely degrades the spirit divine.'

                Comment

                • Richard Cornford

                  #9
                  Re: Stylistic concerns for large application

                  "Lasse Reichstein Nielsen" <lrn@hotpop.com > wrote in message
                  news:adax9inb.f sf@hotpop.com.. .
                  <snip>[color=blue][color=green]
                  > > Which Opera 7 version?[/color]
                  >
                  > Opera 7.20 beta 2.[/color]

                  Strangely it is possible to dynamically load a script in the first beta
                  release of Opera 7 (7.0b1) by re-writing the innerHTML of a DIV to
                  include a new script tag. So it can be done in two betas but no official
                  releases.

                  Incidentally I don't think that I ever tested to see how (and if)
                  setting a - defer - property on a createElement(' script') element to
                  true influenced the success rate when trying this.

                  Richard.



                  Comment

                  • Dr John Stockton

                    #10
                    Re: Stylistic concerns for large application

                    JRS: In article <MPG.199053e523 d35fbc98987c@ne ws.altopia.com> , seen in
                    news:comp.lang. javascript, Chris Smith <cdsmith@twu.ne t> posted at Tue,
                    29 Jul 2003 10:51:10 :-[color=blue]
                    >
                    >3. How do I combine lots of JavaScript source files into a single web
                    >page. Having zillions of script tags seems hokey, but I can't find a
                    >way to include one JavaScript source file from another, so it looks like
                    >everything does need to be included directly from the HTML source.[/color]

                    If you had looked in the regularly -posted and -cited FAQ, you would
                    have found no relevant occurrence of "include", which seems a pity.

                    Most of my javascript date pages use include files; but start at
                    <URL:http://www.merlyn.demo n.co.uk/js-index.htm#IF>, visit
                    <URL:http://www.merlyn.demo n.co.uk/js-nclds.htm> and
                    <URL:http://www.merlyn.demo n.co.uk/js-other.htm>.

                    <FAQENTRY> - something on include files?

                    And perhaps the FAQ could link to an associated demonstration page,
                    intended to be most illustrative under View Source??

                    Might FAQ 3.2 be more readable with <ul> ... <li> ... </ul> ?

                    </FAQENTRY>

                    I think an included file can include another by document.write of the
                    HTML that calls the next; but I've not done it.

                    Code in an include file can use code in a previous include file, IIRC.

                    If you include a given file more than once, you might get confused but
                    the browser should do what you are actually asking for.

                    --
                    © John Stockton, Surrey, UK. ?@merlyn.demon. co.uk Turnpike v4.00 IE 4 ©
                    <URL:http://jibbering.com/faq/> Jim Ley's FAQ for news:comp.lang. javascript
                    <URL:http://www.merlyn.demo n.co.uk/js-index.htm> JS maths, dates, sources.
                    <URL:http://www.merlyn.demo n.co.uk/> TP/BP/Delphi/JS/&c., FAQ topics, links.

                    Comment

                    • Jim Ley

                      #11
                      Re: Stylistic concerns for large application

                      On Tue, 29 Jul 2003 10:51:10 -0600, Chris Smith <cdsmith@twu.ne t>
                      wrote:
                      [color=blue]
                      >I'm considering solutions like having zero-size frames in a frameset
                      >that load other pages with JavaScript code in them, to avoid holding up
                      >the loading of functional pages. Any other ideas?[/color]

                      framesets are generally a bad idea, a better idea would I think depend
                      on what you're doing and the nature of the interaction, and who the
                      audience is and ... I'm sure there is one though.

                      Jim.
                      --
                      comp.lang.javas cript FAQ - http://jibbering.com/faq/

                      Comment

                      • Chris Smith

                        #12
                        Re: Stylistic concerns for large application

                        Lasse Reichstein Nielsen wrote:[color=blue]
                        > Chris Smith <cdsmith@twu.ne t> writes:
                        >[color=green]
                        > > Okay, fair enough, but I'm beginning to see that this answer interacts
                        > > with what you say about hiding members... if I define methods in the
                        > > manner you describe above, then they don't have access to any more of
                        > > the object than an external observer would.[/color]
                        >
                        > Javascript objects are completely transparent. There is no more to
                        > access than what an external observer can see.
                        >
                        > If you add the so-called "private members" then it is not really
                        > supported by Javascript objects, but it can be *emulated* by scoped
                        > variables shared by the methods.[/color]

                        Yep. That was Richard's terminology, not mine, and I was adopting it.
                        So, it looks like it all comes down to two possible general approaches:

                        1. Add only members intended to be used by the outside world, and then
                        use closures and local variables and inner functions of the constructor
                        for other members. A few methods could be added to the prototype, but
                        only if they are the "convenienc e method" variety that can be entirely
                        expressed in terms of other object interface elements that are intended
                        to be exposed.

                        This seems to offer the best info-hiding behavior, but suffer from the
                        performance issues you mentioned.

                        2. Add all members to the object, and don't use Richard's trick with
                        closures at all. In this case, every method would be added to the
                        prototype. Then, back to my original question, would you use some kind
                        of identifier tagging such as a leading underscore to distinguish your
                        intended public interface from implementation artifacts.
                        [color=blue][color=green]
                        > > That's not really consistent with a set of reasonable visibility
                        > > rules (that is, I never really want to hide an object's state from
                        > > itself),[/color]
                        >
                        > You cannot hide anything from anybody using only Javascript objects.[/color]

                        That seems more than a bit disingenuous when you consider that Richard
                        has proposed to me a means of using closures to accomplish exactly that.
                        [color=blue]
                        > You can add the "defer" attribute to the script tags:
                        > <script type="text/javascript" src="foo.js" defer="defer"></script>
                        > All that means is that you promise that the source contains no
                        > document.write' s, and that parsing can continue without waiting for the
                        > code to be loaded and run.[/color]

                        Great! This is exactly the sort of thing I was looking for.

                        --

                        The Easiest Way to Train Anyone... Anywhere.

                        Chris Smith - Lead Software Developer/Technical Trainer
                        MindIQ Corporation

                        Comment

                        • Lasse Reichstein Nielsen

                          #13
                          Re: Stylistic concerns for large application

                          Chris Smith <cdsmith@twu.ne t> writes:
                          [color=blue]
                          > Lasse Reichstein Nielsen wrote:[color=green]
                          > > You cannot hide anything from anybody using only Javascript objects.[/color]
                          >
                          > That seems more than a bit disingenuous when you consider that Richard
                          > has proposed to me a means of using closures to accomplish exactly that.[/color]

                          That is why I said "using only Javascript *objects*". You can emulate
                          everything with closures[1], but if hiding methods or fields of objects
                          is so important, then maybe one should use a language that supports
                          it natively, without a hack (no matter how ingenious the hack is).

                          /L
                          [1] I mean *everything*. Closures, function calls and return statements
                          together are Turing complete, so they can emulate *any* computation. That's
                          mostly theoretical, since the emulation can be quite big in some cases,
                          but it suggests the power that closures have.
                          --
                          Lasse Reichstein Nielsen - lrn@hotpop.com
                          DHTML playground: <URL:http://www.infimum.dk/DHTMLindex.html >
                          'Faith without judgement merely degrades the spirit divine.'

                          Comment

                          • Lasse Reichstein Nielsen

                            #14
                            Re: Stylistic concerns for large application

                            Dr John Stockton <spam@merlyn.de mon.co.uk> writes:
                            [color=blue]
                            > I *guess* the above really means that loading foo.js must *execute* no
                            > document.write etc., without prohibiting loading functions that when
                            > called will execute such.[/color]

                            Ofcourse :)
                            [color=blue]
                            > And that, if the browser does not honour defer, the rest still works.[/color]

                            It should. Adding "defer" is only a hint to the browser that it can do
                            an alternative interleaving of the parsing of the source and the
                            loading and executing of the javascript. It tells the browser that it
                            is safe to continue parsing before executing the code, but it is always
                            safe not to wait.

                            /L
                            --
                            Lasse Reichstein Nielsen - lrn@hotpop.com
                            Art D'HTML: <URL:http://www.infimum.dk/HTML/randomArtSplit. html>
                            'Faith without judgement merely degrades the spirit divine.'

                            Comment

                            Working...