首页 > 代码库 > Python演绎的精彩故事(一)

Python演绎的精彩故事(一)

Python是一门广受赞誉的编程语言。她既有强大、简洁而优雅的表现力,又能够支撑工业级的开发实践。

但本文不是Python的入门介绍和教程。

今天我们来讲一个与众不同的故事,看看Python还有哪些不为人知的精彩值得发掘。


我们想借助Python的智慧和威力来尝试一种新思维、新设计、新框架。我们希望构造一种可以媲美硬件工业成熟典范的力量,让软件开发也能够高效、成熟而艺术。这是本文作者的一个梦想。


故事情节概要:假设我们要编写一个应用程序,功能是基于网络的纯文本聊天客户端程序,命名为TextChat
按照常见的典型设计,开发者这样切分了系统模块:
1.Controller       :控制服务器的连接。
2.LoginWindow:供用户输入用户名和密码,登录服务器。
2.ChatWindow  :显示聊天信息及好友在线状态,输入并发送聊天消息,登出服务器。
3.CommunicationManager:负责进行通讯的底层网络模块。

用于App主体及各主要class的代码(
近似Python语法的伪代码,简略起见仅作示意用)大概长这个样子:
<span style="font-size:12px;">import CommunicationManager
import LoginWindow
import ChatWindow
import Controller

def main():
    serverHost = u'192.168.1.100'
    serverPort = 8000
    
    ctrl = Controller()
    ctrl.StartWork(serverHost, serverPort)</span>


# 连接服务器,创建LoginWindow和ChatWindow,启动LoginWindow。
class Controller():
    def __init__(self):
        pass
        
    def StartWork(self, serverHost, serverPort):
        commMgr = CommunicationManager(serverHost, serverPort)
        succeeded = commMgr.Connect()
        if not succeeded:
            return

        winChat  = ChatWindow(commMgr)
        
        winLogin = LoginWindow(commMgr, winChat)
        winLogin.Show()	#Modal window.
        
        commMgr.Disconnect()

    
# 登录服务器,启动ChatWindow。
class LoginWindow():
    def __init__(commMgr, winChat):
        self.__commMgr = commMgr
        self.__winChat = winChat

    def Show():
        username = xxx.GetValue()
        password = xxx.GetValue()
		
        succeeded = self.__commMgr.Login(username, password)
	if not succeeded:
            return
		
        self.__winChat.Show()

#处理用户Chat操作:邀请好友、收发message,登出服务器。
class ChatWindow():
    def __init__(commMgr):
        self.__commMgr = commMgr
	
    def __OnInviteButtonPressed():
        ...
        friendName = xxx.GetValue()
        succeeded = self.__commMgr.InviteFriend(friendName, self.HandleReceivedMsg)
        ...
        
    def __OnSendButtonPressed():
        ...
        message = xxx.GetValue()
        succeeded = self.__commMgr.SendMessage(message)
		...
        
    def HandleReceivedMsg(receivedMsg):
        ...

    def __OnWindowClosing(self):
        self.__commMgr.Logout()

# 提供所有底层通讯功能:连接、断开;登入、登出;收发消息;邀请好友等。
class CommunicationManager():
    def __init__(serverHost, serverPort):
        self.__serverHost = serverHost
        self.__serverPort = serverPort

    def Connect(serverHost, serverPort):
        pass

    def Disonnect(serverHost, serverPort):
        pass

    def Login(username, password):
        pass

    def Logout():
        pass

    def InviteFriend(friendName, callbackListener):
        ...
        self.__MessageReceiveThread(callbackListener)
        ...

    def SendMessage(message):
        pass

    def __MessageReceiveThread(callbackListener):
        pass
        

各模块之间的协作与交互关系参看模块关系图。        


从模块关系图可以清晰看到模块间的耦合关系:

1.Controller==>LoginWindow和CommunicationManager。
2.LoginWindow==>ChatWindow和CommunicationManager。
3.ChatWindow==>CommunicationManager。

在这里,A==>B(A依赖于B)的意思就是:A需要持有B的实例并通过实例调用B的方法。


基于C++或Java这类静态编程语言,A必将在编码和编译期间就开始产生对B的依赖,例如:
1.include对方的头文件。
2.严格按照对方的method声明编写调用语句,参数的类型和顺序,返回值的类型都必须一丝不苟。


如果B模块还没有开发,A模块的很多代码可能就没法写。如果B模块发生了变更,A模块往往也不得不重新编译。

A模块的开发者被B模块牵制得很苦,很苦。这就是模块耦合和编程语言自身的特点所带来的痛楚。

当然,水平极高的少数开发者也许有办法避开一部分上述问题,但那些技巧是具有相当难度的,不是谁都能掌控得了。

而上文所展示的代码则是大多数开发者最常使用的典型套路,是现实中最普遍存在的情况。


实际项目的规模远远大于这个TextChat,其模块间的耦合之多、之复杂可以想见。

但凡有过经验的开发者都能理解其中的痛楚。

到此为止,是故事的序幕阶段。

当一筹莫展的开发者遇到Python的时候,真正令人幸福的故事才开始。


假定,我们利用Python开发TextChat之前,已经实现了一套应用程序框架,称之为Softchip

这个框架包含三个组件:Machine和Chip等组件。这些组件分别模拟计算机硬件系统的机器和芯片。

那么首先,快速预览一下,基于Softchip架构的应用程序,其App启动部分代码是怎么写的。

from Softchip import Machine
import CommunicationManager
import LoginWindow
import ChatWindow
import Controller

def main():
    CHIP_ID_COMM_MGR   = u'chip_id_comm_mgr'
    CHIP_ID_CONTROLLER = u'chip_id_controller'
    CHIP_ID_LOGIN_WIN  = u'chip_id_login_win'
    CHIP_ID_CHAT_WIN   = u'chip_id_chat_win'

    chipList = [
        {
            Machine.CI_CREATOR: CommunicationManager,
            Machine.CI_ARGS   : CHIP_ID_COMM_MGR,
        },
        {
            Machine.CI_CREATOR: Controller,
            Machine.CI_ARGS   : CHIP_ID_CONTROLLER,
        },
        {
            Machine.CI_CREATOR: LoginWindow,
            Machine.CI_ARGS   : CHIP_ID_LOGIN_WIN,
        },
        {
            Machine.CI_CREATOR: ChatWindow,
            Machine.CI_ARGS   : CHIP_ID_CHAT_WIN,
        },
    ]

    machine = Machine()
    machine.CreateChips(chipList)
    machine.Boot()
    machine.Trigger(u'api_start_work', u'192.168.1.100', 8000)

怎么样?是不是觉得像军队的列阵一般整齐、刚劲、简洁!

这正是我们所期待的代码。当然,代码虽然优美,但要能够真正work才行,不能只是花拳绣腿。

Softchip架构在底层默默地支撑着,而各模块也需要按照明确的规范来设计。

在本系列的下一篇,我们将浏览各模块的代码,看看在Softchip架构上是如何编程的。

Python演绎的精彩故事(一)