# Should we reduce the number of Item Types in the Attribute Resource

**URL:** <https://discourse.kitware.com/t/should-we-reduce-the-number-of-item-types-in-the-attribute-resource/164>\
**Category:** Design\
**Created:** [October 3, 2018, 5:22pm UTC](https://discourse.kitware.com/t/should-we-reduce-the-number-of-item-types-in-the-attribute-resource/164 "2018-10-03T17:22:03Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![Bob\_Obara](https://discourse.kitware.com/user_avatar/discourse.kitware.com/bob_obara/32/37_2.png) [@Bob\_Obara](https://discourse.kitware.com/u/Bob_Obara)\
**Post date:** [October 3, 2018, 5:22pm UTC](https://discourse.kitware.com/t/should-we-reduce-the-number-of-item-types-in-the-attribute-resource/164/1 "2018-10-03T17:22:03Z")

</div>

Back when the attribute resource was being designed (when it was called an Attribute System), I needed to be able to refer to model and mesh entities and attributes as items within an attribute. Since there was no base class that the 3 classes shared, I created specific items classes that became ModelEntityItem, MeshEntityItem, and AttrRefItem respectively along with their corresponding Definition classes.

In SMTK 3.0, we have the resource::Component class that is the base class to attribute::Attribute, model::Component, and mesh::Component. There is now an attribute::ComponentItem class (along with its corresponding Definition class) that can functionally do all the things that the original 3 item classes can do. The question is do we remove the other classes or keep them around as convenience classes that target specifically these less abstract concepts and potentially provide additional API? For example, ModelEntityItem has the ability to use EntityRefs while the superclass would not.

We would like to make a decision soon but wanted to give other developers a chance to weigh in. So comments are strongly encouraged!

---

<div class="post-metadata">

**Author:** ![tj.corona](https://discourse.kitware.com/user_avatar/discourse.kitware.com/tj.corona/32/35_2.png) [@tj.corona](https://discourse.kitware.com/u/tj.corona)\
**Post date:** [October 3, 2018, 5:52pm UTC](https://discourse.kitware.com/t/should-we-reduce-the-number-of-item-types-in-the-attribute-resource/164/2 "2018-10-03T17:52:32Z")

</div>

I think the base differentiation is whether we want to put the pointer downcasts in a narrowing API within attribute or have the downcast be performed by the consuming code. One of the primary places we encourage smtk users to extend smtk’s functionality is the ability to add Operations, and most of the downcasts would have to be performed within the operation code (i.e. smtk users will have to perform a bunch of downcasts when writing an operation). A narrowing API would lift this burden from writers of operations, but would augment the API of smtk::attribute, and thus provide another cognitive load for users. I’m not sure which one is better, but I think contributors may be more comfortable with a larger API than with the need to cast everything into its expected type.

The need to cast everything also leaks our implementation of component hierarchy through attribute’s API. While we are not currently trying to hide the fact that components exist, it is definitely an implementation and not a front-facing feature of smtk.

---

<div class="post-metadata">

**Author:** ![dcthomp](https://discourse.kitware.com/user_avatar/discourse.kitware.com/dcthomp/32/10_2.png) [@dcthomp](https://discourse.kitware.com/u/dcthomp)\
**Post date:** [October 3, 2018, 7:58pm UTC](https://discourse.kitware.com/t/should-we-reduce-the-number-of-item-types-in-the-attribute-resource/164/3 "2018-10-03T19:58:19Z")

</div>

> [@Bob\_Obara](#):
>
> The question is do we remove the other classes or keep them around as convenience classes that target specifically these less abstract concepts and potentially provide additional API? For example, ModelEntityItem has the ability to use EntityRefs while the superclass would not.

Actually, the ComponentItem _does_ allow EntityRefs because EntityRef can take an Entity::Ptr for a constructor. This means that the ReferenceItem::as\<std::vector\>() will still work through the beauty of templates.

> [@tj.corona](#):
>
> I think the base differentiation is whether we want to put the pointer downcasts in a narrowing API within attribute or have the downcast be performed by the consuming code. …

The problem is that the pointer downcasts occur frequently and involve a lot of boilerplate code that is painful if you do not use SMTK every day.

---

<div class="post-metadata">

**Author:** ![tj.corona](https://discourse.kitware.com/user_avatar/discourse.kitware.com/tj.corona/32/35_2.png) [@tj.corona](https://discourse.kitware.com/u/tj.corona)\
**Post date:** [October 3, 2018, 8:13pm UTC](https://discourse.kitware.com/t/should-we-reduce-the-number-of-item-types-in-the-attribute-resource/164/4 "2018-10-03T20:13:46Z")

</div>

> The problem is that the pointer downcasts occur frequently and involve a lot of boilerplate code that is painful if you do not use SMTK every day.

So should we put them in the narrowing API then?

---

<div class="post-metadata">

**Author:** ![dcthomp](https://discourse.kitware.com/user_avatar/discourse.kitware.com/dcthomp/32/10_2.png) [@dcthomp](https://discourse.kitware.com/u/dcthomp)\
**Post date:** [October 3, 2018, 8:34pm UTC](https://discourse.kitware.com/t/should-we-reduce-the-number-of-item-types-in-the-attribute-resource/164/5 "2018-10-03T20:34:16Z")

</div>

> [@tj.corona](#):
>
> > The problem is that the pointer downcasts occur frequently and involve a lot of boilerplate code that is painful if you do not use SMTK every day.
> 
> So should we put them in the narrowing API then?

I prefer to just use the templated `as<Container>()` method in ReferenceItem than adding a whole narrowing class. But the worst of both worlds is to provide neither.

What value do narrowing classes provide beyond that one function? Is it Python access to items? I would prefer to provide a python-specific list conversion for that.

---

<div class="post-metadata">

**Author:** ![tj.corona](https://discourse.kitware.com/user_avatar/discourse.kitware.com/tj.corona/32/35_2.png) [@tj.corona](https://discourse.kitware.com/u/tj.corona)\
**Post date:** [October 3, 2018, 8:54pm UTC](https://discourse.kitware.com/t/should-we-reduce-the-number-of-item-types-in-the-attribute-resource/164/6 "2018-10-03T20:54:37Z")

</div>

I have written the following code:

`auto item = this->parameters()->findComponent("foo");`  
`auto faces = item->as<smtk::model::Faces>([`]`(smtk::resource::PersistentObjectPtr obj) {`  
`return smtk::model::Face(std::dynamic_pointer_cast<smtk::model::Entity>(obj));`  
`});`

I could definitely be doing this in a silly way, but this is a pretty awkward API. In contrast, there would be something like

`auto item = this->parameters()->findModelEntity("foo");`  
`smtk::model::Faces faces(item->begin(), item->end());`

If `smtk::model::EntityRef` were going away (which seems like a pretty huge undertaking), then I agree that a narrowing API to avoid `std::dynamic_pointer_cast<>` (or `as<>`) would probably be a long trip for a short slide.

So maybe the question is whether or not we want to force the public-facing API of each of the core namespaces (attribute, mesh, model) to only use the Resource/Component paradigm. The attribute system was virtually a no-op, and I know the model part is tricky. The mesh part is going to be even trickier (not impossible, though. It’s just code).

---

<div class="post-metadata">

**Author:** ![dcthomp](https://discourse.kitware.com/user_avatar/discourse.kitware.com/dcthomp/32/10_2.png) [@dcthomp](https://discourse.kitware.com/u/dcthomp)\
**Post date:** [October 3, 2018, 9:02pm UTC](https://discourse.kitware.com/t/should-we-reduce-the-number-of-item-types-in-the-attribute-resource/164/7 "2018-10-03T21:02:13Z")

</div>

> [@tj.corona](#):
>
> have written the following code:
> 
> ```c++
> auto item = this->parameters()->findComponent("foo");
> auto faces = item->as<smtk::model::Faces>([`] `(smtk::resource::PersistentObjectPtr obj) {
> return smtk::model::Face(std::dynamic_pointer_cast<smtk::model::Entity>(obj));
> });
> 
> ```

I was under the impression that we had a

```c++
auto faces = item->as<smtk::model::Faces>();

```

that worked (no lambda required).

---

<div class="post-metadata">

**Author:** ![tj.corona](https://discourse.kitware.com/user_avatar/discourse.kitware.com/tj.corona/32/35_2.png) [@tj.corona](https://discourse.kitware.com/u/tj.corona)\
**Post date:** [October 3, 2018, 9:05pm UTC](https://discourse.kitware.com/t/should-we-reduce-the-number-of-item-types-in-the-attribute-resource/164/8 "2018-10-03T21:05:56Z")

</div>

I don’t think we do. If we did, wouldn’t it have to expose the `smtk::model` API within `smtk::attribute::ReferenceItem`?

---

<div class="post-metadata">

**Author:** ![tj.corona](https://discourse.kitware.com/user_avatar/discourse.kitware.com/tj.corona/32/35_2.png) [@tj.corona](https://discourse.kitware.com/u/tj.corona)\
**Post date:** [October 7, 2018, 4:44pm UTC](https://discourse.kitware.com/t/should-we-reduce-the-number-of-item-types-in-the-attribute-resource/164/9 "2018-10-07T16:44:31Z")

</div>

One thing to consider: if we have specialized items, then we will also introduce a dependency from the namespace defining the API back to the attribute namespace. In the past we have discussed the possibility of allowing libraries to register items and definitions with the attribute resource; doing so would remove this dependency.

---

<div class="post-metadata">

**Author:** ![dcthomp](https://discourse.kitware.com/user_avatar/discourse.kitware.com/dcthomp/32/10_2.png) [@dcthomp](https://discourse.kitware.com/u/dcthomp)\
**Post date:** [October 8, 2018, 1:36pm UTC](https://discourse.kitware.com/t/should-we-reduce-the-number-of-item-types-in-the-attribute-resource/164/10 "2018-10-08T13:36:35Z")

</div>

> [@tj.corona](#):
>
> I don’t think we do. If we did, wouldn’t it have to expose the `smtk::model` API within `smtk::attribute::ReferenceItem` ?

No, not if everything from `smtk::model` was in the template parameter(s).
