Mailinglist Archive: yast-devel (79 mails)

< Previous Next >
Re: [yast-devel] A convenient wrapper layer to query devicegraphs
On Fri, 18 Mar 2016 09:57:11 +0100
Ancor Gonzalez Sosa <ancor@xxxxxxx> wrote:

I have a design decision to take and I need advise. Please, stay on
topic (i.e. "design a ruby layer to query the not-under-discussion
structure of devicegraphs coming from libstorage").

While writing the code for the new proposal we needed to query a
devicegraph (hopefully you all know what a devicegraph is in the
libstorage-ng world) for things like:

- all free spaces in a given subset of disks (candidates for install)
- all filesystems in the same subset, not caring if they are directly
on the disk or on a partition table

While writing tests, we found we had similar requirements but without
constraining those queries to a set of disks (i.e. we wanted to list
the free spaces, partitions, filesystems, etc. at some point of the
whole devicegraph).

We came up with the idea of a Devicegraph query object that is already
partially implemented and seems to solve our problems. But if we are
going to start using it in many places (there will be calls in almost
every single test) I want to make sure the API does not suck much. I
have two alternatives and would like to hear/read opinions.

As usual, we don't want to over-engineer it, but we don't want to
throw it away with the next requirement change either.

Explanation by example, hopefully enough (ping me if it's not). Please
read both options before commenting (I actually like more the second
one).

Option 1 - Only a DevicegraphQuery class

https://gist.github.com/ancorgs/9c628ef0f4fa717a2817

But, what about something like this?
more_fine_query.disks

With the implementation I have in mind, it would return the same that
fine_query.disks, but some people could expect it to return only disks
from fine_query.disks which, as additional requirement, contain any
primary partition.

This, of course, can be solved documenting which restrictions are
honored by each query method (for example, #disks would only honor
#with_disk while #partitions would honor both #with_disk and
#with_partition).

That is, the expected direction of the hierarchy (like "a filesystem
can be expected at some point below a disk, but not the other way
around") would be in the source code and documentation of the methods
at DevicegraphQuery.

Option 2 - A WhateverQuery class per type of object

https://gist.github.com/ancorgs/a98597fa9a5e348eaaac

This is my preferred option for several reasons, even if it means
implementing more classes (something that is not bad, per se).

First of all, the direction of the hierarchy is reflected in the API
(DiskQuery has a method #filesystems which returns a FilesystemQuery
but not the other way around).

It also makes possible (and easy) to write specific filters for a
given type of query, like
# Get an array of free spaces big enough to be used for something
FreeDiskSpaceQuery.new(devicegraph).useful.to_a

I also find it more readable for the tests and very Ruby-like (even
Rails-like), but that can be a matter of taste.

Opinions?

Hi,
I check both examples and few notes:

1) we should reinvent wheel. ActiveModel already have queries, so why
not use it?

2) Why we need to create query object? It is not intuitive for me. I
expect query is action on container, not object itself.
It is same for me like having
`Question.new(human).age?`
versus
`human.age?`
Also in ActiveModel mentioned above you do not use something like
`Query.new(Human.all).with_age(25)` but `Human.all.with_age(25)`

3) it is probably related to 2), second approach looks better to me,
just please no query object. Object should be containers like Disks or
Partitions holding object of given type which you can query, filter,
whatever. See for example this code using this approach in yast(!) -
https://github.com/yast/yast-cio/blob/master/src/lib/iochannel/channels.rb#L37

So to sum it, for me the main design issue is that query is not object,
but action. Object is for me container holding objects of given type
with actions on it.
Then you can have your code like:
https://gist.github.com/jreidinger/3883aa68662e9a7fdc7b

just my 2c
Josef
--
To unsubscribe, e-mail: yast-devel+unsubscribe@xxxxxxxxxxxx
To contact the owner, e-mail: yast-devel+owner@xxxxxxxxxxxx

< Previous Next >
References