> >> Something like: > >> (db.mytable.id == 3).ignore_common_filters().select() > > > A bit ugly, and gets worse if we add more arguments in the future. > > Say in our API that we have a Cat type with some uncommon options for > users to set. Which is the better approach for setting these options? > > A) add optional argument(s) to the constructor. B) add method(s) to > modify the object state. C) add properties to assign. D) encapsulate > the options in a wrapper class Feline. > D (though the wrapper class might be something more like GroomedCat, not a strict synonym)
> A), obviously, is the normal solution, but we can't do that with Query > because we normally produce Query objects from overloaded operators of > Field. Going with solution D) over B) or C) is a very odd thing to do. > Not sure why. It leads to nicer syntax. > If D) served some other purpose, it might begin to make sense, but as > I've already argued, it doesn't. > Why does the chosen solution have to serve more than one purpose? Maybe it's better to think about it from the perspective of using the API rather than worrying about the internal implementation. We have a connection object that represents a database: db db is callable -- calling it with a query plus some optional arguments defines a set of records in the database: db(query, **optional_arguments) The query involves special DAL syntax, applying various operators to table fields (behind the scenes, the DAL converts that to a Query object, but that's just an implementation detail). The optional arguments may further refine the set of records identified by the query. Once we have defined a set of records, we can apply various methods to that set, such as select, count, delete, etc. db(query, **optional_arguments).select(...) That all seems fairly straightforward to me, and the syntax is clean. In this story, the query is just the DAL syntax for identifying particular records, whereas the set is defined both by the query syntax and the optional arguments. From the standpoint of the API, it doesn't really matter that the query becomes a Query object internally -- you just need to know the query syntax, and you pass your query syntax to the db object to define your records. Note, the Query class doesn't have any public methods to call, so the user doesn't need to explicitly think about the Query class -- all the action happens with the Set object. From the user perspective, there's query syntax and a Set object -- no need to worry about the internal details of the Query vs. Set classes. Perhaps there's a better alternative for the internal implementation, but the public API seems reasonable to me. Anthony