On Feb 18, 12:29 pm, Scott Sauyet <scott.sau...@gmail.com> wrote:
> (Just a quick note to say that if I read your tone correctly, you seem
> to be offense to my comments.

Not at all. No offense is taken.

> I just want to say that although I
> disagree here, I've seen many of your posts in cljs and hold a good
> deal of respect for you.  I just seem to use JS in a very different
> way than you do.)

I'm somewhat echoing the point Asen made earlier in this thread though
the details may differ.

Earlier you stated:
"However the manner in which you choose to organize it is strongly
influenced by your choice of language. "
...
"You're right, if you're trying to code as though you were in a
statically-typed language.  JS certainly allows you to code in that
manner.  But IMHO that ignores the strengths of the language. "

I'd like to add that this manner is also influenced heavily by common
practice by the community for good or ill. The drum I'm beating is
that coding in a pattern ~vaguely~ similar to what you'd see in a
statically typed language does not have to take away from the
"strengths" of the language.


> Michael Haufe (TNO) wrote:
> > Scott Sauyet wrote:
> >> [ ... ]  When I program in Javascript, I don't usually
> >> think in terms of classes of objects, but in one-off objects that may
> >> or may not have certain properties.  One of the great things about the
> >> language is the ability to add and remove arbitrary properties of
> >> objects.
>
> > And if you want scalable code you'll change what terms you consider
> > again. The "great things" about the language are also terrible things
> > when dealing with scale, hence the large number of meta-object
> > features introduced in ES5.
>
> I'm not sure what you consider scale.

Any code-base too large to keep in your head at once.

> My current project involves ~65
> JS files with just over 20K lines of JS code.  It's a single-page web
> application, AJAX-heavy, with JS required to use it.  (Not my
> choice!)  The main data configuration used per client is between 20KB
> and 300KB, with an object count in the  thousands or tens of
> thousands, or in rare cases in the low hundreds of thousands, never in
> the millions.  The user base will be moderate, measuring in the tens
> of thousands, but not hundreds of thousands or millions, and probably
> not more than a few hundred simultaneous users.  What sort of scale do
> you think is required to make your suggestion necessary?

Its not necessity as much as it is clarity and simplicity.  To take a
small modification the example earlier:

var persons = [{address: {zip: 1234}}, {}];

//persons is an array of objects whose structural rules are in the
mind of the developer

//the persons array could have been created anywhere so lets make sure
we're actually getting
//the data we expect
persons.forEach(function(person){
    if(typeof person == "object"){
        if(typeof person.address == "object"){
            if(typeof person.zip == "number")
                print(person.zip);
            else
                print("No zip code or an invalid zip code")
        }
        //type error (doesn't seem to be a person object, or else the
person object
       // address is missing/invalid)
    }
    //type error (object was expected)

});

Now obviously this is ludicrously verbose and JS developers don't code
like this, they instead assume the data will probably be correct:

var persons = [{address: {zip: 1234}}, {}];

persons.forEach(function(person){
    if(person && person.address && person.address.zip)
        print(person.address.zip || "no zip");
});

As long as you can control the data in that array, you can be
relatively certain that all will be well.  But what if more moving
parts are included? What if the persons array is created from a JSON
file? What if not all persons are created equally? Does it matter if I
mix and match persons of different roles? This is where the method of
code organization starts to matter as the code size increases with
features. As things progress and more exceptions and additions are
made to the code, more and more checks get added and this second
example slowly starts looking like the first. Sure, you could come up
with creative ways to decorate the objects with new properties to
sniff for type info, or use some library/language trickery to reduce
the bloat (adding a new method or use nullable objects) but I believe
that makes it much harder than it needs to be. So if you initially do
what Asen and I suggest with constructors you could avoid some of this
code bloat down the line:

var persons = [new Person(new Address(1234)), new Person()];

persons.forEach(function(person){
    if(!(person instanceof Person))
        //type error
    print(person.address.zip || "no zip")
});


> We do an awful lot with configuration object parameters to our
> functions, merging them with default values where appropriate.

I assume you mean:

doSomething({ foo:1, bar:2 });

Of course there is nothing wrong with this by itself, but if you start
using multidimensional arguments or a long list of them I'd say this
is also something that needs to be re-visited:

doSomething({
    foo : 1,
    bar : 2,
    quux : 3,
    address : {
        zip : 1234,
        state : "TX",
        country : "USA"
     }
})

> But there are many cases when we simply branch on the existence of certain
> properties in objects supplied.  We haven't run into any issues except
> for slightly less readable code than we might have if we had the sort
> of static contract you discuss.

A contract does not have to be static.

> We have not introduced any general nested property access of the sort
> suggested by Peter van der Zee, but we do have the equivalent for the
> main data configuration object, which is simply a JSON-ified version
> of an industry-standard XML
> format in which many elements at various levels are optional.  It
> works as you might expect, a get of "path.to.property" returns null if
> any of the nodes are missing.  A set for the same path creates empty
> objects for any of the missing nodes.
>
> We could of course create a data model of constructor functions for
> every level of the data model, and hook them together in an
> appropriate way.  But in the last six months, we've already done three
> updates to the structure of the data model to later versions of the
> industry standard.  This involved no changes to our core data-access
> mechanism.  Had we tried to work with such a data model, it would have
> been substantially more work, and I can't see that it would have
> gained us anything.

I had a similar project some years ago and used something like this:

var myConfig = Config(
    AppSettings(
        Key("DBConn", "..."),
        Key("FileName","...")
    ),
    OtherStuff(),
   ...
)

...

doStuff(myConfig);

Its of course easy enough to treat something like that as an object
but this approach made the semantics explicit and the enforcement much
easier as it simply takes a single instanceof check to know what data
I'm getting and what operations can act upon it.

> >> [U]nless you're quite certain that no code has done the equivalent of
>
> >>     delete person2.address,
>
> >> you still need something like that to ensure your code won't fail
> >> horribly.
>
> > Object.seal(...)
>
> If you're fortunate enough to be working in an ES5 environment, or you
> code these features yourself, and if no one is passing you an unsealed
> clone of your object, and no one has set the `address` property to a
> non-object value, then maybe you can count on this working.  But there
> are probably other cases too where it still won't work.

With JS being the language that it is, one could shoot holes in most
anything. But the use of more robust patterns obviously reduce the
probability of running across unintentional issues.

> >> The point is simply that JS is a class-free language.  You can
> >> simulate classes to some degree, but it's never an exact match with
> >> what's available in class-based languages.
>
> > I don't recall saying anything about classes nor their simulation nor
> > any feature that is necessarily shared with them. You seem to be
> > trying to present a Straw man.
>
> Not intentionally, I assure you.  So what is the point of introducing
> the Person and Address constructor functions in your earlier message
> if not to use them as the equivalent of class constructors?  I thought
> the whole point was the contract that every person would have an
> address which would have a zip code.  If that is the point, then how
> does that differ from OO-style classes?

Using that terminology comes with a lot of implications that are
invalid, so I prefer to avoid the use of the term. I assumed you were
trying to imply that I was trying to smuggle in some type of foreign
language construct which is not the case. But the constructor pattern
obviously serves a similar role to OO-classes which serves a similar
role to some constructs you can see in some functional languages which
is not a bad thing.  I could go on but I don't want to stray to far
from the subject of the thread.

-- 
To view archived discussions from the original JSMentors Mailman list: 
http://www.mail-archive.com/jsmentors@jsmentors.com/

To search via a non-Google archive, visit here: 
http://www.mail-archive.com/jsmentors@googlegroups.com/

To unsubscribe from this group, send email to
jsmentors+unsubscr...@googlegroups.com

Reply via email to