A clean way to program an interface

rh0dium steven.klass at gmail.com
Mon Jul 9 16:19:19 EDT 2007


On Jul 9, 9:59 am, Paul McGuire <p... at austin.rr.com> wrote:
> I believe the OP is talking about "interface" as in "hardware
> interface", using some form of serial communication.  His example does
> not use pyserial, but it does refer to a "UnidenConnection" class,
> with parameters such as bitrate, port, etc. for what looks like serial
> communication.

Yes - You are correct UnidenConnection is nothing more than a pyserial
connection which handles all of the setup and returns (converting
strings to list objects etc).


> Some general comments:
>
> 1. Much of the OP's use of sys._getframe().f_code.co_name coincides
> with his naming of certain methods with the same name as the command
> to be sent down the serial line.  "STS", "EPG", "PRG", "SIN", etc. are
> all 3-character command codes that get sent down the wire, along with
> the appropriate values for the particular command.  While many of
> these routines have *some* code in common, only a few have their
> entire method body duplicated with one or more other methods.
> Refactoring a couple of these into code closures, you can get:
>
>     @staticmethod
>     def makeStatusCheckCommandFunction(cmd):
>         def fn(self):
>             return ( self.uniden.write(cmd)[0]=="OK" )
>         return fn
>     PRG = makeStatusCheckCommandFunction("PRG")
>     EPG = makeStatusCheckCommandFunction("EPG")
>
>     @staticmethod
>     def makeCmdFunction(cmd,attrname):
>         def fn(self):
>             setattr(self, attrname, int(self.PRGWrite(cmd)[0]))
>             return getattr(self,attrname)
>         return fn
>     SCT = makeCmdFunction("SCT","systems")
>     SIH = makeCmdFunction("SIH","sih")
>     SIT = makeCmdFunction("SIT","sit")

Hmm very interesting - I've never played with code closures.  Very
cool - I need to learn me about these thingy's :)

> Now there is no sys._getframe().f_code.co_name legerdemain going on,
> the command strings are just passed along as the argument cmd, and the
> functions themselves are named the same for some level of self-
> documentation and/or convenience.
>
> For the remaining methods, I declare a local variable named cmd and
> assign to it the write mnemonic.  Yes, I know it violates DRY ("Don't
> Repeat Yourself"), but it avoids the getframe() stuff and again, is at
> least a snippet of self-documentation.
>
> 2. This code for reading and unpacking all the non-blank values feels
> ugly:
>
>     cmd = "SIF"
>     if args is None:
>         p=self.PRGWrite("%s,%s" % (cmd,idx))
>         t={}
>         t["site_type"],t["name"],t["quick_key"],t["hld"],t["lout"],\
>             t["mod"],t["att"],t["cch"],t["apco"],t["threshold"],\
>             t["rev_index"],t["fwd_index"],t["sys_index"],t["chn_head"],
> \
>             t["chn_tail"],t["seq_no"],t["start_key"],t["latitude"],\
>             t["longitude"],t["range"],t["gps_enable"],t["rsv"]=p
>
>         delitems=[]
>         for item in t:
>             if t[item]=="": delitems.append(item)
>         for x in delitems: del t[x]
>
> How about this instead?:
>
>     cmd = "SIF"
>     if args is None:
>         p=self.PRGWrite("%s,%s" % (cmd,idx))
>         names = "site_type name quick_key hld lout mod att cch "\
>                 "apco threshold rev_index fwd_index sys_index "\
>                 "chn_head chn_tail seq_no start_key latitude " \
>                 "longitude range gps_enable rsv".split()
>
>         t = dict( k,v for k,v in zip(names,p) if v != "" )

This is absolutely the right way to do this - I totally like this -
Super!!


> HTH,
> -- Paul

Hey thanks a lot!!






More information about the Python-list mailing list