The Forum for Discussion about The Third Manifesto and Related Matters

Please or Register to create posts and topics.

Almost (but not quite) an ANNOUNCE

MyTableQuery01.builder().min(6).max(12).query(database)
              .forEach(tuple -> System.out.println("x = " + tuple.x + ", y = " + tuple.y));

 

Your 'builder' notation is a violation of a fundamental D language rule : that update operators return no values.  Your .min() and .max() things are clearly update operators, yet they still return some value (a pointer to the updated object).

This is Command-Query separation, first defined by Bertrand Meyer and expanded by Martin Fowler. Every pure function (no side effects) is a query, every command must have a side-effect. This builder notation is a so-called fluent interface (per MF again), which typically chains together a series of pure functions (queries) and ends with a command.

As long as the starting point is a new value, this construct complies with CQS (and D). There is no side-effect, no externally visible update. Updates to temporary values don't count.

 

Andl - A New Database Language - andl.org
Quote from Erwin on September 14, 2021, 7:15 pm
Quote from Dave Voorhis on September 14, 2021, 6:14 pm
Quote from Erwin on September 14, 2021, 5:56 pm
Quote from tobega on September 12, 2021, 8:01 am
Quote from Dave Voorhis on September 11, 2021, 8:23 pm
Quote from tobega on September 11, 2021, 6:46 pm
Dave, this looks pretty great!
Thanks!
...

One thing that would make it even better is named parameters in the QueryDefinition ...

Antc mentioned that too, and I agree that it would be good. At the moment, it's a very minimal skin around existing JDBC facilities. But as I mentioned in my reply to Antc, I could, I suppose, lightly wrap it with some text-replacement machinery, though I'm trying to use existing JDBC/Streams facilities wherever possible without altering or adding layers to them. But I can see the value. Must (continue to) think on this.

Great!

I also forgot the second part of the ask, to have a query builder instead of positional arguments when running the query.

MyTableQuery01.builder().min(6).max(12).query(database)
.forEach(tuple -> System.out.println("x = " + tuple.x + ", y = " + tuple.y));
MyTableQuery01.builder().min(6).max(12).query(database) .forEach(tuple -> System.out.println("x = " + tuple.x + ", y = " + tuple.y));
MyTableQuery01.builder().min(6).max(12).query(database)
              .forEach(tuple -> System.out.println("x = " + tuple.x + ", y = " + tuple.y));

 

Your 'builder' notation is a violation of a fundamental D language rule : that update operators return no values.  Your .min() and .max() things are clearly update operators, yet they still return some value (a pointer to the updated object).

No, unless I've misunderstood the construct, in D terms min(...) selects the 'min' argument, max(...) selects the 'max' argument, and query(database) runs the query -- which is parametric, with 'max' and 'min' parameters, against the database specified by 'database'. There are no updates in the D sense.

But what I'm working on here isn't a D anyway. It's an alternative to heavyweight ORMs and awkward JDBC, which makes SQL easier to integrate into Java. It's a, uh, NoD product.

It's clearly intended to make the 'builded' thing remember the value for the 'min' parameter (think 'setMin') and remember the value for the 'max' parameter (think 'setMax') so that the .query() method can actually run.  I'm probably looking at the provided example more from the traditional Java way and wondering "What can Java do with this" while you are looking more from, eurhm, well, some other angle but if you're real about "trying to make it work in Java" you might ponder the possibility that my angle is the better one ...

Since it crossed my mind, you might have been thinking of the 'min()' method as returning a "query with the min parameter set" (and hence not "changing state" in anything at all in the sense that I was thinking of) and ditto for the 'max()' method which then begs the question of "what type is a query with both parameters set", which then begs the question of whether the lattice model of TTM IM does not apply here in some way (for any meaning of 'some' - but at the very least that 'some meaning' should make it possible for the system to detect and ascertain that the .query() method can only be invoked for queries that have set both - and then 'both' translates to 'all parameters needed' for the more general case of parametric queries).

This is at least very close to the way I think of it, as typestates, where the "query" method only exists once all parameters are set. But it is also just a way to simulate named parameters. Dave's suggestion of wrapping each value in its own object type is another way to simulate named parameters. These things become somewhat clunky to emulate in languages that don't have them, but it may sometimes be worth it (and sometimes not).