mercredi 25 décembre 2019

How to capture the essence of an object-oriented API "ideally"?

I'm confused as to how best to organize the fields/properties of an object. Specifically, the graphic sprite. These are some of the ways you can create the object:

{
  width: 10,
  height: 10,
  marginTop: 2,
  marginRight: 3,
  marginBottom: 4,
  marginLeft: 5,
  alpha: 0.5,
  red: 200,
  blue: 200,
  green: 200
  // ...
}

Or a million ways in between. Or this for example:

{
  size: {
    width: 10,
    height: 10
  },
  margin: {
    top: 2,
    right: 3,
    bottom: 4,
    left: 5
  },
  color: {
    red: 200,
    blue: 200,
    green: 200,
    alpha: 0.5
  }
}

One reason you might want to have these nested objects vs. the flat structure, is for type-checking. You would have clear objects with specific types which could be used elsewhere. But the reason for the flat structure is potentially performance in accessing the properties. But, you loose some of the conceptual relations which the nested object provides. So I am confused.

I am confused because in HTML you are essentially at this strucure:

{
  type: 'div',
  width: 10,
  height: 10,
  style: {
    margin: {
      top: 2,
      right: 3,
      bottom: 4,
      left: 5
    },
    color: 'rgba(200, 200, 200, 0.5)'
  }
}

Or perhaps the width and height are moved into the style object. But we just showed you can have a flat list of properties in the first example. And why the need for the nested style object. Why is "margin" (a pixel value for sizing) separated into style while width/height are delegated to the element? I'm not actually wondering why HTML did it this way, or if there are other ways of viewing it. I am just using this as an example to demonstrate that there are potentially many various ways of doing the same thing. Having nested or flat objects in various configurations and combinations.

I could imagine having a div be like this too:

{
  vector: [10, 10],
  marginVector: [2, 3, 4, 5],
  colorVector: [200, 200, 200, 0.5]
}

Needless to say, there's unlimited ways of organizing the code, with tradeoffs in every direction.

But what I want to know is if there is some notion of an "ideal representation" of an object. Is one way better than the other in the end? Specifically in terms of being generic.

A related example is how list iteration works. If you worry about implementation details of lists, like if it is using pointers vs. a dynamic language, or if you have complex data structure implementations of lists, etc., then you have to write a custom implementation of each list iteration algorithm.

iterateThisListType
iterateThatListType
...

This creates the problem of that you now don't have a "generic list iteration algorithm", like those you learn in school. Each list iteration algorithm can be totally different depending on architecture-specific/etc. implementation details.

This problem can be solved by using the concept of "iterators". Passing an iterator to the list algorithm allows you to have a very simple, single list iteration algorithm.

for (item in iterator) {
  ...
}

Not something that doesn't resemble list iteration at all (just making this up):

let something = *another;
while (true) {
  if (something->else > 10) {
    complicated....
  } else {
    complicated...
  }
}

That doesn't capture the "essence" of list iteration like the iterator does.

In the same light, I am wondering how do we capture the "essence" of a DOM node? It makes total sense on some level to group everything under style, or to make color all one object, etc. But at the same time, it also makes sense to have a top-level red and blue, etc. rather than nesting it in an object. So how can we do similar to the list-iteration example and capture the essence of the DOM node? (Or any other relatively complex structure)

It only gets more complicated when you start to think more in terms of graphics and effects. In graphics, like in sound production, you have all kinds of "effects" that are applied to the main object, our sprite in the graphics example. Some effects are "drop shadow", "blur", "reflection", "old film", and many others. Often times (in the graphics case) the effects are simply modifying existing lower-level properties on the object. So like blur might just modify the pixels attribute (where each pixel has a color of some sort). (Just making this up). Effects (or you could call them "filters"), could also be like regular properties it seems. Grayscale, for example, could be a top-level boolean:

{
  grayscale: true
}

Or it could be an effect:

{
  effects: [
    { type: 'grayscale' }
  ]
}

Well if you are doing this, then why not just make "width" and "height" into effects too! I mean, they are effects of the object as well, "giving them a size".

{
  effects: [
    { type: 'grayscale' },
    { type: 'width', value: 10 },
    { type: 'height', value: 10 }
  ]
}

Well now we are seeing that effects could then just be thought of as attributes in this simple case, and we can go back to the flat top-level attribute example. But some other effects seem to be layers on top of lower-level "effects/attributes", sort of forming a graph of processing on some "fundamental" attributes. So I don't know! I am wondering, is there an "ideal" approach to this? Is there a way to "capture the essence" of the graphics sprite? To make it so that every algorithm that used it could be written in one way (like the iterator)? So in one case we don't have top-level flat attributes, and another nested, and another effects, etc. Which one is right? How do we arrive at the ideal?

That was just for demonstration.

My question is about the DOM node. Not specifically the DOM node API and how it works or why it is like that, but about the philosophy behind it. How can we capture the essence of the DOM node attributes in this way?

Another quick example... It seems you could nest things pretty deeply if you wanted to.

{
  type: 'animal',
  body: {
    organs: {
      skin: {
        mesh3d: {
          texture: {
            color: '#ff0000'
          }
        }
      }
    }
  }
}

Rather than just doing:

{
  type: 'animal',
  color: '#ff0000'
}

You might have a really complicated mesh which is has a color on the texture. But then you want to just think about it as "the animal has a color". So I am confused on what to do.

Aucun commentaire:

Enregistrer un commentaire