<div dir="ltr"><div><div>+1<br><br></div>This was bothering me for a long time.<br><br></div>But I guess there must be some reason it had to be this way?<br></div><div class="gmail_extra"><br><br><div class="gmail_quote">On Wed, Jan 9, 2013 at 12:15 PM, Maru Newby <span dir="ltr"><<a href="mailto:mnewby@internap.com" target="_blank">mnewby@internap.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi,<br>
<br>
I consider quantum's use of dicts instead of first-class model instances to be problematic, and the repeated compositional patterns are a symptom of that.  What do you think of updating the codebase to use objects instead of dicts, and relying on model-specific marshalling to and from wire formats like json or xml?<br>

<br>
Thanks,<br>
<br>
<br>
Maru<br>
<div class="HOEnZb"><div class="h5"><br>
<br>
On 2013-01-07, at 4:54 AM, Avishay Balderman <AvishayB@Radware.com> wrote:<br>
<br>
> Hi<br>
> A common pattern that I found when looking at the DB layer is that after a we fetch an object from DB we call helper method that convert this object into a dict.<br>
><br>
> I have seen few "sub patterns"<br>
> 1) 1:1 mapping : (Example 0) every attribute of the db object is copied "as is" into the dict<br>
> 2) 1:1 mapping with "lazy" collections (Example 1) : every attribute of the db object is copied "as is" into the dict. The objects in the "joins" are not copied. Only their id's is copied into the dict<br>

> 3) 1:1 mapping with "lazy" collections and some naming modifications (Example 2) : almost every attribute of the db object is copied "as is" into the dict. The objects in the "joins" are not copied. Only their id's is copied into the dict. Some of the attributes names are changed during the conversion.<br>

><br>
> Since it is a common pattern I think that the utility method "_make_XYZ_dict" should be a method in the super class QuantumBase.<br>
> It can come with a default implementation that can cover examples 1 and 2.<br>
> Sub classes that needs "special" implementation will be able to override it.<br>
> The method in the base class will be able to cover the _fields (see below) method as well.<br>
><br>
> Thanks<br>
><br>
> Avishay<br>
><br>
> Example 0:<br>
> -----------<br>
> def _make_member_dict(self, member, fields=None):<br>
>        res = {'id': member['id'],<br>
>               'tenant_id': member['tenant_id'],<br>
>               'pool_id': member['pool_id'],<br>
>               'address': member['address'],<br>
>               'port': member['port'],<br>
>               'weight': member['weight'],<br>
>               'admin_state_up': member['admin_state_up'],<br>
>               'status': member['status']}<br>
>        return self._fields(res, fields)<br>
><br>
> Example 1:<br>
> -----------<br>
>    def _make_network_dict(self, network, fields=None):<br>
>        res = {'id': network['id'],<br>
>               'name': network['name'],<br>
>               'tenant_id': network['tenant_id'],<br>
>               'admin_state_up': network['admin_state_up'],<br>
>               'status': network['status'],<br>
>               'shared': network['shared'],<br>
>               'subnets': [subnet['id']<br>
>                           for subnet in network['subnets']]}<br>
> Example 2:<br>
> ----------<br>
> def _make_subnet_dict(self, subnet, fields=None):<br>
>        res = {'id': subnet['id'],<br>
>               'name': subnet['name'],<br>
>               'tenant_id': subnet['tenant_id'],<br>
>               'network_id': subnet['network_id'],<br>
>               'ip_version': subnet['ip_version'],<br>
>               'cidr': subnet['cidr'],<br>
>               'allocation_pools': [{'start': pool['first_ip'],<br>
>                                     'end': pool['last_ip']}<br>
>                                    for pool in subnet['allocation_pools']],<br>
>               'gateway_ip': subnet['gateway_ip'],<br>
>               'enable_dhcp': subnet['enable_dhcp'],<br>
>               'dns_nameservers': [dns['address']<br>
>                                   for dns in subnet['dns_nameservers']],<br>
>               'host_routes': [{'destination': route['destination'],<br>
>                                'nexthop': route['nexthop']}<br>
>                               for route in subnet['routes']],<br>
>               'shared': subnet['shared']<br>
>               }<br>
>        if subnet['gateway_ip']:<br>
>            res['gateway_ip'] = subnet['gateway_ip']<br>
><br>
>        return self._fields(res, fields)<br>
><br>
> _fields:<br>
> ---------<br>
>    def _fields(self, resource, fields):<br>
>        if fields:<br>
>            return dict(((key, item) for key, item in resource.iteritems()<br>
>                         if key in fields))<br>
>        return resource<br>
><br>
> _______________________________________________<br>
> OpenStack-dev mailing list<br>
> <a href="mailto:OpenStack-dev@lists.openstack.org">OpenStack-dev@lists.openstack.org</a><br>
> <a href="http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev" target="_blank">http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev</a><br>
<br>
<br>
_______________________________________________<br>
OpenStack-dev mailing list<br>
<a href="mailto:OpenStack-dev@lists.openstack.org">OpenStack-dev@lists.openstack.org</a><br>
<a href="http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev" target="_blank">http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev</a><br>
</div></div></blockquote></div><br><br clear="all"><br>-- <br><div><b>Intel SSG/SSD/SOTC/PRC/CITT</b></div>
<div>880 Zixing Road, Zizhu Science Park, Minhang District, Shanghai, 200241, 
China<br></div>
<div>+862161166500</div>
</div>