[Tutor] Proper SQLite cursor handling?

dn PyTutor at DancesWithMice.info
Sat Jul 3 20:47:27 EDT 2021


On 03/07/2021 22.13, Alan Gauld via Tutor wrote:
> On 03/07/2021 10:02, dn via Tutor wrote:
> 
>> now, to run a game, the three steps are self-documenting:
>>
>> game_parameters = get_game_data_from_DB( db_defns )
>> game = SolitaireGame( game_name, other_game_data )
>> store_game_results_in_DB( game.results_for_DB() )
> 
> From an OOP perspective I'd change that to:
> 
> parameters = GameParameters( db_defns )
> game = SolitaireGame( parameters )
> game.store()


Does this mean that within game.store() the code will call a method
within parameters (GameParameters) to perform the necessary o/p to
backing-store? It will work (see below). Is it 'good design'/'best
practice'?


An alternative (re-stating the original outline) might be something like:

parameters = GameParameters( db_defns )
game = SolitaireGame( parameters )
parameters.store_results( game.store() )

In this case, game.store() extracts/exports relevant parameter-values
from the game. These are then handed across an
interface/'API'/"contract" to parameters.store_results() which performs
the transfer of values being carried-forward into the next game/play,
onto the 'DB'/backing-store.


There is room for some debate about which of these two approaches is
'best' - or a better approach to the decision: which is preferable for
this application?
(it's nothing personal)


The reasons for (my) preferring the (second outline) above is that each
object (GameParameters and SolitaireGame) has its own (separate) set of
methods, and the two only 'meet' across the two 'mirror' interfaces, ie
a 'Clean Architecture'. SolitaireGame plays Solitaire. GameParameters
handles persistence.

Whereas, the former case requires that SolitaireGame not only take in
the data (parameters) but either:
- understand that the parameters object to include a
store_results/store_parameters method, or
- will directly store the parameters itself
(which would mean that both objects need to know about I/O for
persistence - whither 'separation of concerns'?).


The disadvantage of distinct "separation" is that whilst the I/O method
can change without affecting the game-object, adding additional
parameters will require evident changes to both. Changes to 'the
database' (or the API) are seldom insignificant within projects, and are
often reasons why an application will 'step up' a "major" version-number
(https://en.wikipedia.org/wiki/Software_versioning) - because all 'old'
stores require conversion/migration before re-use.

Perhaps without such separation it might be possible to 'bury' changes
and make them seem less significant ("major")?


On the other hand, in a commercial situation, "separation" enables the
work to be split between different people/teams. In this example, we
could ask our DB-specialist to create GameParameters, whilst our
games-expert gets-busy with SolitaireGame. The two will have to 'put
their heads together' to design and agree the interface both up-front
and in an Agile cyclic-update manner thereafter. Which brings me to...


If achieving working-code is where the objective/satisfaction lies.
Either of the above, or indeed the paired-functions (used as a more
simple illustration, earlier in the thread), will 'do the job'. If the
author is likely to be the only user, then should changes (even
'catastrophic changes') need to be made, 'no puppies will die'.


Alternately, (and rightly or wrongly) I take @boB's penchant for
learning-by-experimenting as a key component of any response - and in
this case (per previous discussion-threads 'here') his "learning
objectives" in this project seem to encompass Python, coding techniques,
storage options, and application-design. Accordingly, the earlier
suggestion that separating I/O from game-play would enable various (and
independent) iterations of both game-complexity and storage-medium - all
the while (post iteration nr1), having a working-application.

In this project's learning-path we might see some merit in starting-out
with a dict to hold key:value pairs of parameters. Zero persistence, but
with a trade-off of easy addition/alteration. Accordingly, one may
concentrate on the workings of SolitaireGame, and find that over-time
the requirements for I/O (interface) seem to naturally 'fall out' and
make themselves obvious.

In the early days, the dict can be easily expanded and altered. When
SolitaireGame starts to feel 'stable', there will be time and 'spare
effort' to apply to the I/O object/methods. A dict will lead naturally
to JSON, and thereafter JSON could lead to MongoDB. Thus, a convenient
expansion plan/learning-path. Not that it would be difficult to re-form
the dict into a relational schema either...

-- 
Regards,
=dn


More information about the Tutor mailing list