tags:

views:

58

answers:

2

Hi everyone -

I'm coding a poker hand evaluator as my first programming project. I've made it through three classes, each of which accomplishes its narrowly-defined task very well:

HandRange = a string-like object (e.g. "AA"). getHands() returns a list of tuples for each specific hand within the string:

[(Ad,Ac),(Ad,Ah),(Ad,As),(Ac,Ah),(Ac,As),(Ah,As)]

Translation = a dictionary that maps the return list from getHands to values that are useful for a given evaluator (yes, this can probably be refactored into another class).

{'As':52, 'Ad':51, ...}

Evaluator = takes a list from HandRange (as translated by Translator), enumerates all possible hand matchups and provides win % for each.

My question: what should my "domain" class for using all these classes look like, given that I may want to connect to it via either a shell UI or a GUI? Right now, it looks like an assembly line process:

user_input = HandRange()
x = Translation.translateList(user_input)
y = Evaluator.getEquities(x)

This smells funny in that it feels like it's procedural when I ought to be using OO.

In a more general way: if I've spent so much time ensuring that my classes are well defined, narrowly focused, orthogonal, whatever ... how do I actually manage work flow in my program when I need to use all of them in a row?

Thanks,

Mike

+1  A: 

You could create a Poker class that ties these all together and intialize all of that stuff in the __init__() method:

class Poker(object):
    def __init__(self, user_input=HandRange()):
        self.user_input = user_input
        self.translation = Translation.translateList(user_input)
        self.evaluator = Evaluator.getEquities(x)

    # and so on...

p = Poker()
# etc, etc...
jathanism
+3  A: 

Don't make a fetish of object orientation -- Python supports multiple paradigms, after all! Think of your user-defined types, AKA classes, as building blocks that gradually give you a "language" that's closer to your domain rather than to general purpose language / library primitives.

At some point you'll want to code "verbs" (actions) that use your building blocks to perform something (under command from whatever interface you'll supply -- command line, RPC, web, GUI, ...) -- and those may be module-level functions as well as methods within some encompassing class. You'll surely want a class if you need multiple instances, and most likely also if the actions involve updating "state" (instance variables of a class being much nicer than globals) or if inheritance and/or polomorphism come into play; but, there is no a priori reason to prefer classes to functions otherwise.

If you find yourself writing static methods, yearning for a singleton (or Borg) design pattern, writing a class with no state (just methods) -- these are all "code smells" that should prompt you to check whether you really need a class for that subset of your code, or rather whether you may be overcomplicating things and should use a module with functions for that part of your code. (Sometimes after due consideration you'll unearth some different reason for preferring a class, and that's allright too, but the point is, don't just pick a class over a module w/functions "by reflex", without critically thinking about it!).

Alex Martelli