Python演绎的精彩故事(二)

书接上回。在展示了App最顶层的代码后,我们去看看各模块如何编程。

为了能看懂各模块的代码,首先需要铺垫一下Softchip架构的基本概念和设计规范。

1、任意模块不持有其他模块的实例,自然不再显式使用句柄调用任何方法。

这意味着模块之间不存在编码期和编译期的耦合。

2、每个模块在形式上只与Machine之间存在接口,该接口以APIEvent两种形态存在。

API将直接映射到函数入口地址,使用者可直接调用,运行期性能高。主要用于Utility性质的方法和需要高性能的场合。

Event也是同步调用,但运行期性低于API。它的关键作用是在逻辑上切割冗长的调用链。在传统套路中,一个模块在完成自己的处理后,往往还要辛苦地触发其他模块的相关后续动作,这在逻辑上相当于惦记着“别人的事儿”。Event的引入相当于将原来长长的调用链在时间上切分为一个一个的阶段状态。每个模块只需要告诉Machine“X的事情Y完了”,Machine会自动查找谁需要在“X的事情Y完了”之后继续。Machine寻找后续操作的依据就是目标模块在自己的接口中所做的事件监听声明。

3、模块接口由自行声明,包括:

3-1) outAPI  : 自己需要调用的API名称列表。

3-2) inAPI   : 自己可以提供其他模块调用的API名称列表(附带对应的函数入口地址)。

3-3) inEvent : 自己要监听的事件名称列表(附带对应的事件处理函数入口地址)。

3-4) outEvent: 自己是否要发送事件。

基于各模块声明,Machine自动将各模块“插入”,完成运行期API的绑定和event的分发。

4、概括来说,各模块基本只需要关心“自己的事情”:

4-1) 我提供什么API?

4-2) 我需要调用什么API?

4-3) 我监听并处理什么事件?

4-4) 我产生什么事件?

反过来讲,模块不需要关心“别人的事情”:

4-5) 谁使用我的API?

4-6) 谁提供API给我用?

4-7) 我监听的事件是谁产生的?(我干活之前是谁在干?)

4-8) 我产生的事件谁处理?(我干完了谁来继续?)

举个简单的例子,在TextChat的设计中,LoginWindow登录成功后,不需要显式通知ChatWindow,因为那是ChatWindow的事情。LoginWindow只需要告诉Machine“LoginWindow登录成功了”。Machine会自动找到ChatWindow出来干活,因为ChatWindow之前已经告诉过Machine,如果“LiginWindow登录成功了”,请通知我。

OK,有了上面的铺垫,下面的代码就比较容易看懂了,基本套路是:

1、每个模块都继承Chip类。

2、实现_DefineInterface()方法以完成接口声明。

3、实现_PowerOn()方法以接收Machine发出的"上电"通知。

除此以外,每个模块就完全自由了,爱怎么玩就怎么玩吧。

新版的模块关系参照下图。

from Softchip import Chip
class Controller(Chip):
    def __init__(self, chipID):
        Chip.__init__(self, chipID)

    def _DefineInterface(self):
        outAPIList = [
            u'connect_server',
            u'disconnect_server',
        ]

        inAPIList = [
            (u'api_start_work', self.__apiStartWork),
        ]

        inEventList = [
            (u'evt_logout_done', self.__evtOnLogoutDone),
        ]

        self.__interface = {
            Chip.TYPE_INT_API  : inAPIList,
            Chip.TYPE_OUT_API  : outAPIList,
            Chip.TYPE_OUT_EVENT: None,
        }

        return self.__interface

    def _PowerOn(self):
        self._eHandler = self.__interface[CHIP.TYPE_OUT_EVENT]

        apiMap = self._DefineInterface[CHIP.TYPE_OUT_API]
        self.__apiConnect    = apiMap[u'connect_server']
        self.__apiDisconnect = apiMap[u'disconnect_server']

    def __apiStartWork(self, serverHost, serverPort):
        succeeded = self.__apiConnect(serverHost, serverPort)

        if not succeeded:
            self._eHandler(u'evt_connect_failed')
        return

        self._eHandler(u'evt_connect_succeeded')

    def __evtOnLogoutDone(self):
        self.__apiDisconnect()

class CommunicationManager(Chip):
    def __init__(self, chipID):
        Chip.__init__(self, chipID)

    def _DefineInterface(self):
        inAPIList = [
            (u'connect_server',    self.__Connect     ),
            (u'disconnect_server', self.__DisConnect  ),
            (u'log_in',            self.__Login       ),
            (u'log_out',           self.__Logout      ),
            (u'invite_friend',     self.__InviteFriend),
            (u'send_message',      self.__SendMessage ),
        ]

        self.__interface = {
            Chip.TYPE_IN_API   : inAPIList,
            Chip.TYPE_OUT_EVENT: None,
        }

        return self.__interface

    def _PowerOn(self):
        self._eHandler = self.__interface[Chip.TYPE_OUT_EVENT]

    def __Connect(serverHost, serverPort):
        pass

    def __DisConnect(serverHost, serverPort):
        pass

    def __Login(username, password):
        pass

    def __Logout():
        pass

    def __InviteFriend(friendName):
        ...
        self.__MessageReceiveThread()
        ...

    def __SendMessage(message):
        pass

    def __MessageReceiveThread():
        while(True):
        ...
        message = xxx
        self._eHandler(u'evt_message_arrived', message)
        ...

class LoginWindow(Chip):
    def __init__(self, chipID):
        Chip.__init__(self, chipID)

    def _DefineInterface(self):
        outAPIList = [
            u'log_in',
            u'log_out',
        ]

        inEventList = [
            (u'evt_connect_succeeded', self.__evtOnConnectSucceeded),
            (u'evt_chat_closed',       self.__evtOnChatClosed      ),
        ]

        self.__interface = {
            Chip.TYPE_OUT_API  : outAPIList,
            Chip.TYPE_INT_EVENT: inEventList,
            Chip.TYPE_OUT_EVENT: None,
        }

        return self.__interface

    def _PowerOn(self):
        self._eHandler = self.__interface[CHIP.TYPE_OUT_EVENT]

        apiMap = self._DefineInterface[CHIP.TYPE_OUT_API]
        self.__apiLogin  = apiMap[u'log_in']
        self.__apiLogout = apiMap[u'log_out']

    def __evtOnConnectSucceeded(self):
        self.Show()

    def __evtOnChatClosed(self):
        self.__apiLogout()

        self._eHandler(u'evt_logout_done')

    def __OnLoginButtonPressed(self):
        username = xxx.GetValue()
        password = xxx.GetValue()
        succeeded = self.__apiLogin(username, password)

        if not succeeded:
            self._eHandler(u'evt_login_failed')
            return

        self._eHandler(u'evt_login_succeeded')
        self.Hide()

class ChatWindow(Chip):
    def __init__(self, chipID):
        Chip.__init__(self, chipID)

    def _DefineInterface(self):
        outAPIList = [
            u'invite_friend',
            u'send_message',
            u'log_out',
            u'disconnect_server',
        ]

        inEventList = [
            (u'evt_login_succeeded', self.__evtOnLoginSucceeded ),
            (u'evt_message_arrived', self.__evtOnMessageReceived),
        ]

        self.__interface = {
            Chip.TYPE_OUT_API  : outAPIList,
            Chip.TYPE_IN_API   : inEventList,
            Chip.TYPE_OUT_EVENT: None,
        }

        return self.__interface

    def _PowerOn(self):
        self._eHandler = self.__interface[CHIP.TYPE_OUT_EVENT]

        apiMap = self._DefineInterface[CHIP.TYPE_OUT_API]
        self.__apiInvite     = apiMap[u'invite_friend']
        self.__apiSendMsg    = apiMap[u'send_message']
        self.__apiLogout     = apiMap[u'log_out']
        self.__apiDisconnect = apiMap[u'disconnect_server']

    def __evtOnLoginSucceeded(self):
        self.Show()

    def __evtOnMessageReceived(self, message):
        xxx.ShowText(message)

    def __OnInviteButtonPressed(self):
        friendName = xxx.GetValue()

        succeeded = self.__apiInvite(friendName, self.__OnMessageReceived)
        if not succeeded:
            self._eHandler(u'evt_invite_failed')
            return

        self._eHandler(u'evt_invite_succeeded')

    def __OnSendButtonPressed(self):
        message = xxx.GetValue()

        self.__apiSendMsg(message)

    def __OnWindowClosing(self):
        self._eHandle(u'evt_chat_closed')

在本系列的下一篇,我们将简要分析一下Softchip框架的意义。

时间: 2024-10-27 08:45:24

Python演绎的精彩故事(二)的相关文章

Python演绎的精彩故事(一)

Python是一门广受赞誉的编程语言.她既有强大.简洁而优雅的表现力,又能够支撑工业级的开发实践. 但本文不是Python的入门介绍和教程. 今天我们来讲一个与众不同的故事,看看Python还有哪些不为人知的精彩值得发掘. 我们想借助Python的智慧和威力来尝试一种新思维.新设计.新框架.我们希望构造一种可以媲美硬件工业成熟典范的力量,让软件开发也能够高效.成熟而艺术.这是本文作者的一个梦想. 故事情节概要:假设我们要编写一个应用程序,功能是基于网络的纯文本聊天客户端程序,命名为TextCha

Python演绎的精彩故事(三)

Softchip架构到底为开发者带来了什么?和传统的开发套路相比到底有什么本质的不同? 相信有部分开发者在阅读完前两篇之后已经有了基本清晰的认识. 在这里阐述一下笔者个人的见解,仅供参考. 形式上看,Softchip为模块制订了一个限制性设计规范,把模块深深地包藏起来,各模块不能再自由地调用其他模块的方法了. 而实际上,这个看似限制的动作却把模块彻底解放了.严格来说,是把模块设计者彻底解放了.为什么呢? 1.你不再与数不清的模块发生关系,你只与一个叫做Machine的角色打交道. 2.你不知道也

《舌尖上的中国》精彩故事

<舌尖上的中国>精彩故事 <舌尖上的中国>是纪录频道推出的第一部高端美食类系列纪录片,从2011年3月开始大规模拍摄,是国内第一次使用高清设备拍摄的大型美食类纪录片.共在国内拍摄60个地点方,涵盖了包括港澳台在内的中国各个地域,它全方位展示博大精深的中华美食文化.向观众,尤其是海外观众展示中国的日常饮食流变,千差万别的饮食习惯和独特的味觉审美,以及上升到生存智慧层面的东方生活价值观,让观众从饮食文化的侧面认识和理解传统和变化着的中国. 第一集<自然的馈赠> 中国拥有世界

Python开发【第二十二篇】:Web框架之Django【进阶】

Python开发[第二十二篇]:Web框架之Django[进阶] 猛击这里:http://www.cnblogs.com/wupeiqi/articles/5246483.html 博客园 首页 新随笔 联系 订阅 管理 随笔-124  文章-127  评论-205 Python之路[第十七篇]:Django[进阶篇 ] Model 到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞: 创建数据库,设计表结构和字段 使用 MySQLdb 来连接数据库,并编写数据访问层代码 业务逻

问道python之基础篇【二】python入门

问道python之基础篇[二] Python入门 1.python的工作过程 python解释器把源代码转换为字节码的中间形式,然后再把它翻译成机器使用的机器语言并运行. 2.pyc文件 2.1.什么是pyc文件 执行python代码时,如果导入了其他的.py文件,那么在执行过程中会自动生成一个与其同名的.pyc文件,该文件就是python解释器编译之后产生的字节码. ps:代码经过编译可以产生字节码:字节码通过反编译也可以得到代码. Pyc文件一般由3个部分组成: 最开始4个字节是一个Maig

进击的Python【第五章】:Python的高级应用(二)常用模块

Python的高级应用(二)常用模块学习 本章学习要点: Python模块的定义 time &datetime模块 random模块 os模块 sys模块 shutil模块 ConfigParser模块 shelve模块 xml处理 re正则表达式 一.Python模块的定义 有过C语言编程经验的朋友都知道在C语言中如果要引用sqrt这个函数,必须用语句"#include<math.h>"引入math.h这个头文件,否则是无法正常进行调用的.那么在Python中,如

python网络爬虫入门(二)——用python简单实现调用谷歌翻译

最近在看国外的文档,有些生词不认识.就用谷歌翻译来理解,用着用着闲来无事就按F12查看了下页面的源代码.发现可以用python简单的实现下谷歌翻译的页面功能.于是先上网搜下有没有类似的文章博客,发现几篇不错的,于是参考其他代码与自己的思路,简单的实现了下翻译的功能,代码如下: import re import urllib,urllib2 #----------模拟浏览器的行为,向谷歌翻译发送数据,然后抓取翻译结果,这就是大概的思路------- def Gtranslate(text): #t

Python学习入门笔记(二):Python运算符

1.算术运算符 "+"加法:3+2=5 "-"减法:3-2=1 "*"乘法:3*2=6 "/"实数除法:3/2=1,3.0/2=1.5 "//"整数除法:5.6//2=2.0 "%"求余数:17%6=5 "**"求幂运算:2**3=8 2.赋值运算符 "="等于:x=3 "+="加等于:x+=2 "-="减等

[XPath/Python] XPath 与 lxml (二)XPath 语法

XPath 选取节点时使用的表达式是一种路径表达式.节点是通过路径(path)或者步(steps)来选取的. 本章使用以下 XML 文档作为示例. <?xml version="1.0" encoding="utf8"?> <bookstore> <book> <title lang="eng">Harry Potter</title> <price>29.99</pr