Michael Haufe (\"TNO\")
6/1/2016 9:29:00 PM
On Wednesday, June 1, 2016 at 12:50:01 PM UTC-5, Stefan Weiss wrote:
> I sort of agree with this, to a point, but only if I created the data
> structure myself (or my application did). In many situations we simply don't
> have that level of control over data. Examples for this would be external
> APIs, JSON config files, or any other external tree-like structure mapped to
> nested objects.
> Are you saying that all data exchange formats with optional components are
> badly designed,
No. Nothing like that at all.
> or that at least all known container nodes should be
> present? I don't think that's a realistic requirement.
Nor this either.
Let me try to approach this another way to try and clarify my meaning:
<script>
var someObject = JSON.parse(foo);
</script>
If I could rely on the structure of someObject, I could use a definite access pattern:
<script>
var target = someObject.left.right.right.left.value
</script>
We know that's unrealistic in reality and we'd want to do some checking.
We could apply one of the patterns in my last message:
<script>
target = Object.walk(someObject,"someObject.left.right.right.left.value")
</script>
or let's assume the elvis operator was available in the language:
<script>
target = someObject?.left?.right?.right?.left?.value
</script>
Another example with the DOM:
<script>
var target2 = document.body.firstChild.nextSibling.lastChild
</script>
and again with the suggested operator as a more robust alternative:
<script>
target2 = document?.body?.firstChild?.nextSibling?.lastChild
</script>
I assume these two examples strike you as ridiculous, or at least suspect in what it is doing In your own applications, and many you've no doubt run across, you see such a thing not all on one line, but instead spread across methods and function calls as a parameter:
<script>
foo(someObject)
function foo(obj) {
if(obj && obj.left) {
// ...
bar(obj.left)
}
}
function bar(obj) {
if(obj && obj.right) {
//...
baz(obj.right)
}
}
function baz(obj) {
if(el && obj.right) {
//etc...
}
}
</script>
It's the same issue, but less obvious as it's spread across the program.
Now let's backup and look at the DOM example.
Instead of the above, you'd no doubt avoid such probing to find the element you want and would instead use a search of the data structure:
<script>
target2 = document.getElementById("targetNode")
</script>
But you generally don't see this being exercised against arbitary objects (with the exception of JSONPath users and such)
Partly this is due to the lack of such a general facility in JS, but also due to a different mindset when it comes to the DOM vs. JS objects.
If you are able to recognize the objects you deal with as being an instance of one of the well known data structures you can leverage such functionality as searching.
Even if you aren't provided such a structure you could use the Decorator Pattern to wrap that 3rd party structure and provide something more useful for your own portion of the application:
<script>
var data = new MyTreeConstructor(
someThirdPartyObject
);
var results = data.find("something")
result.forEach(...)
</script>
For simpler objects you can use the Decorator Pattern to provide sensible defaults just once.