HNHacker News
TopNewBestAskShowJobs

AnEngineer

9 karma · joined June 4, 2015

submissionscomments
AnEngineer··on Prototypes are Objects
Points well presented, noted, and internalized for future use. :-)

Thank you for taking the time to reply. In attempting to preface the content as potentially being controversial, I succeeded in only being trite (or droll or both).

Learning is fun. Embarrassing sometimes, but fun.

AnEngineer··on Prototypes are Objects
(Side note: it turns out I can't delete the other message. I must have hallucinated having that ability last night.)

> I would argue that objects are nothing more than a uniquely identified run-time entity. With that identity, they can easily have their own encapsulated state (since their identity can be used as an address or key into a global map), and can be associated with behavior that is selected dynamically.

I largely agree and believe this is pretty consistent with the commonly accepted definition of an object in the Comp Sci sense. There are a couple examples which immediately come to mind (Smalltalk, Objective-C) along with other languages (Ruby, Perl, Python) having the ability to selectively provide equivalent behaviour.

Where I previously said "largely agree", the point where I disagree is when you state "objects are nothing more than a uniquely identified run-time entity." Objects also have associated with them a set of messages which are either intrinsic to the environment's definition of what minimally constitutes any object's behavioural contract, identified by the definition of the object's type, or some mixture of the previous two along with a mechanism to resolve message dispatching.

> Compare this with the dual of an object, the value, whose identity is determined by its structure alone (e.g. 1 and 1 are the same values), and so does not allow for state, nor does it allow for dynamic behavior selection without first turning them into objects (aka boxing).

Here, I think we disagree as not all languages treat values as being disjoint from objects. I realize you mention boxing, which languages such as C# and Java perform for _their_ definition of "plain old data" types, but this is not the same as languages such as Ruby, which represents all values as objects intrinsically.

> The only fallacy, I think, is ascribing a notion of objects based on a couple of mainstream data points.

The fallacy which I mentioned is in thinking that a person has the same checks in JavaScript applied to collaborations as is expected in other OO languages/environments. I view this as a direct consequence of JavaScript objects being hash maps. Supporting this view is:

> A JavaScript object is an unordered collection of variables called named values. (source: http://www.w3schools.com/js/js_object_definition.asp)

AnEngineer··on Prototypes are Objects
Prefacing a potentially contraversial position is a well established practice to inform a reader that what follows may not be readily accepted.

In retrospect, mentioning down voting was trite. Thank you for being conscientious enough to point this out to me.

AnEngineer··on Prototypes are Objects
I want to spend the time to provide a cogent response and it is late where I am at. So this is a "todo" response which will be deleted with a proper one ASAP.
AnEngineer··on Prototypes are Objects
My main point was not an "attack" on JavaScript objects. Instead, it was to illuminate that how many people write/speak of JavaScript objects use a frame of reference which simply is incorrect.

Your question:

> Yes JavaScript objects are weak (allow more, too much) compared to legitimately called OOP ones. But is it really different ?

Can certainly spark an intriguing conversation indeed. Without making this a treatise, having the likelyhood of mistakes an on-the-fly one would produce, allow me to address this in parts.

> Yes JavaScript objects are weak (allow more, too much) ...

This is the basis of my assertion that semantic guarantees do not exist in this language. Remember, the article's author makes the statement:

> ... modifying the functions bound to properties of the object. This differs from most classical languages, they have a special form (e.g. Ruby’s def) for defining methods.

Significant in this quote is that, in this example, Ruby uses a keyword in its identification of a method. As such, use of the symbol identified by the keyword def allows the Ruby environment to provide a semantic guarantee that its use as a method definition is within the allowable bounds of the language. While this may not sound like much, when presented with thousands of symbols/variables in many systems, the cognitive load is reduced while simultaneously some portion of semantic use is verified by the environment.

> ... compared to legitimately called OOP ones.

I beleive a better categorization of JavaScript would be as "object based", with a non-trivial functional leaning. But that's just me.

> But is it really different ?

Yes, but different !== bad.

> When I see an anonymous function I see a map, lambda calculus classes made me see the world through this choreography of maps. Sure they don't mutate, they rewrap, shadow, etc etc.

IMHO, the significance of immutability is key with the core concepts of functional programming (to which it owes its existence to lambda calculus). Transformations with the certainty that <a href="https://en.wikipedia.org/wiki/Referential_transparency_(comp... transparency</a> is enforced is the foundation which reasoning about complex function interactions is made possible. So when an environment allows effectual modifications _at any point in a call chain_, there is no provable way to show what state a system is in based on the call flow.

This is the dagger with which mutable collaborations stab provability. Of course, all "OOP languages" I am aware of support this style of programming, which is the topic of another thread I suppose.

> What are real OOP semantic guarantees ? static types ?

Many times, but not always. To me, a semantic guarantee is along the lines of the Ruby example explored above. It is when a language's environment provides the developer with feedback when use of a symbol is not conformant with its definition (if known). What JavaScript specifically does not provide is any assistance in identifying this type of issue (albeit trivial):

var foo = doSomethingAndGiveMeBackAFoo ();

// Is this correct? foo.a ();

// Or this? foo.a + 1;

AnEngineer··on Prototypes are Objects
I believe what you describe can be also described as performing a shallow copy on the prototype which includes the entries from previous copies of the hash map referenced in prior statements.

Unless what transpires is a "back link" to prior definitions such that additions to those prototypes are reflected in subsequent references. Quite frankly, I don't recall off the top of my head which way compliant EMCAScript implementations behave.

> This is very different then a dictionary, where you now have the ability to 'shadow' a property or to change the value of a key in a prototype and have it reflected in all children (which is the exact opposite of a shallow copy).

A dictionary which is shared across all instances would reflect this behaviour, true, but when a dictionary's contents are copied, changes made to the source would not be reflected in the copy (for "first level" key value pairs). I'm pretty sure that adding an indirection to a JavaScript prototype definition (such as placing a hash map in the prototype) would have _its_ key value pairs shared across instances.

But I could very easily be wrong about that.

AnEngineer··on Prototypes are Objects
While the observations I am about to make likely will be down-voted by some/many in this forum, perhaps even be viewed as heresy, I am compelled to present them on the chance that it helps some to understand what JavaScript objects truly are.

TL;DR JavaScript "objects" are nothing more than a <a href="https://en.wikipedia.org/wiki/Hash_table">Hash map</a>.

From the article:

> Prototypes in JavaScript are “just objects,” and since they are “just objects,” we can add, remove, or modify methods of the prototype by adding, removing, or modifying the functions bound to properties of the prototype.

They are not "just objects." In fact, symantically they are nothing more than a hash map (a.k.a. hash table, dictionary)[1]. The above quote from the article clearly indicates this fact as, if we peform three simple keyword substitutions, the sentence reads thusly:

Prototypes in JavaScript are “just hash maps,” and since they are “just hash maps,” we can add, remove, or modify values of the prototype by adding, removing, or modifying the values bound to keys of the prototype.

Attempting to think of JavaScript objects in the same manner as what most mainstream "OO" languages semantically provide is simply wrong. "Prototypical inheiritance" is nothing more than a shallow copy of an associative array. By its very definition, that is _all it is_.

Now, IMHO there is nothing wrong with a hash map. There's nothing right about it either. Those sentiments imply judgement, whereas what I have said above is simply analyzing the nature of the subject. The fallacy in calling JavaScript "objects" objects lies in deceiving one's self into thinking that the same semantic guarantees OO languages provide can be done in native JavaScript. The quicker a developer accepts that JavaScript objects are simply hash maps, the quicker they can understand the semantic contract being proffered by the environment _and_ be able to work with it as best as possible.

1 - http://www.w3schools.com/js/js_object_definition.asp

AnEngineer··on Make hard coding your default choice
This thread may have already gone stale, but just in case not...

I've found that treating configuration settings as "first class abstractions" in the Domain Model pays off quite nicely. By this, I mean grouping related settings into an immutable class which is given the configuration settings provider in one of its constructors. If there are reasonable defaults for all settings, then having a no-args constructor may be acceptable as well.

For example, in Scala I have types such as:

<pre> // Assume 'config' is what can read external configuration case class NetworkSettings (config : SomeConfigReader) { val rootPath = "company-name.project.network";

   host : String = config.stringEntryOrDefault (s"${rootPath}.host", "localhost");
   port : Int = config.intEntryOrDefault (s"{rootPath}.port", 1234);

   // etc.
} </pre>

Of course, this pattern could be used before or instead of having the ability to externalize configuration parameters.

AnEngineer··on FBI: Companies should help us ‘prevent encryption above all else’
Is it just me, or is the irony of this story colossal:

https://news.ycombinator.com/item?id=9662421

AnEngineer··on Distributed Systems Are a UX Problem
By "primary system", I meant the initial system(s) interacted with in a distributed environment. Assuming a connection based distributed model (e.g. TCP/IP), there is a system on the other end of the connection to which a client is communicating. Even for connectionless models, in my mind the "primary system" would be defined as the set of systems which could possibly respond to a client's request.

Perhaps the term "primary" is not the best fit for this role. It just seemed less verbose than saying something like "the set of systems for which a client is directly aware and may interact with."

AnEngineer··on Distributed Systems Are a UX Problem
And my reply:

I agree that there are complexities (as you state, “certain realities”) inherent in distributed systems. If there is one thing I believe we could both agree upon is that distributed systems increase the surface area of complexity exponentially when compared to the relatively simpler stack of clients communicating with one system.

Failures in a distributed environment must be expected. Embraced even, since treating them as “an exception” is tantamount to the proverbial ostrich poking its head into the sand.

However, failure in a distributed system does not necessitate “Frontend and UX folks” having to address failures which are not directly a result of client communication with the next tier. For example, should the UX be prepared to handle when the primary provider of a service is down and fail over to a secondary system? If the service is the one which the client is directly interacting with, then likely that makes sense.

But what of the case when the primary system has issues interacting with its collaborators? Such as its persistent store. Or a strategic partner providing required functionality for the workflow. Is it your position that this type of failure be handled by the UX?

Why wouldn’t a server maintain separation of concerns and only communicate to a client when its options have been exhausted? IOW, why assume what “the other side of the connection” is going to do in order to satisfy a request placed on it?

In summary, my position is that when the collaborators in a distributed system have a well defined software contracts (protocol, expectations, etc.) and all parties adhere to them (without assumptions in implementation), then this allows the system(s) involved to provide resilience in depth. However, the fashionable trend of replicating a PowerBuilder environment does not lend itself to these separation of concerns.

Foisting complexity to either end of the spectrum is where truly nasty problems are bred.