博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Day 5 - 编写Web框架 代码优化
阅读量:6158 次
发布时间:2019-06-21

本文共 3217 字,大约阅读时间需要 10 分钟。

1.匿名sina网友V 

廖大的版本

def add_routes(app, module_name):

    n = module_name.rfind('.')

    if n == (-1):

        mod = __import__(module_name, globals(), locals())

    else:

        name = module_name[n+1:]

        mod = getattr(__import__(module_name[:n], globals(), locals(), [name]), name)

    for attr in dir(mod):

        if attr.startswith('_'):

            continue

        fn = getattr(mod, attr)

        if callable(fn):

        #这里用callable区分函数和普通成员变量是不合适地。

        #总是有一些奇怪的东西混进来,例如handler里边引入的User 用callable判断它总是True,然而扫描User纯粹是浪费电。

            method = getattr(fn, '__method__', None)

            path = getattr(fn, '__route__', None)

            if method and path:

            #这里method和path 判断完就丢了,有点可惜,add_route()里边还要再费二遍事,最好能修改add_route的签名,add_route(app,fn,method,path)一套传过去。

                add_route(app, fn)

我改过的

import types

def add_routes(app,module_name):

    n = module_name.rfind('.')

    if n == (-1):

        mod = __import__(module_name,globals(),locals())

    else:

        name = module_name[n+1:]

        mod = getattr(__import__(module_name[:n],globals(),locals(),[name]),name)

    for attr in dir(mod):

        if attr.startswith('_'):

            continue

        fn = getattr(mod , attr)

        if isinstance(fn,types.FunctionType):

            has_method = hasattr(fn,"__method__")

            has_path = hasattr(fn,"__route__")

            if has_method and has_path:

                add_route(app,fn)

2.middleware和RequestHandler是一定要实现的,不然耦合度太高很容易混乱。

相反,add_route可以省略,如果只加一个的话app.router.add_route就足以应付了。

这是我重构过的版本, __import__有一个黑魔法,不用写得这么复杂的:

mod = __import__(module_name, fromlist=[''])

叫做mblog-master

github地址 https://github.com/moling3650/mblog

3.你的add_routes()很机智,廖大版的method 和 path 查到了不用实在是浪费。

RequestHandler看起来写得和廖大的结构上不一样,粗略的搂了两眼,两份我都没仔细看具体实现。

在这里我得黑一下廖大,廖大版的RequestHandler 貌似把handler函数的参数名写死了,handler的参数必须得叫request。我感觉这样对用户不太友好,这是对用户赤裸裸地强J。

最好能用判断类型的方法来代替判断参数名的方法,来保证传入了一个request类型的参数。这样用户写handler的时候就r,req,request 什么的随意写了。用户用得爽了,框架才有市场。

4.https://github.com/moling3650/mblog

效果图

http://www.qiangtaoli.com/bootstrap/manage/blogs

我的已经是做完了,而且重构了不少地方,比如RequestHandler,重构的理由在这里。

你黑的并不是地方,不是handler函数的参数写死了,而是app.router.add_route方法的第三个参数写死了,这里必需是一个只有一个参数request的函数,所以才用__call__统一封装成RequestHandler(handler)(request)的形式,这样使得handler的参数可以多样化。

然而RequestHandler是整个项目中最值得黑的地方,你可以看看我和别人在楼下的评论就会知道真正值得黑的地方在哪里了XD

5.add_routes最后直接用一个if更简洁

if isinstance(fn, types.FunctionType) and hasattr(fn, '__method__') and hasattr(fn, '__route__'):

    add_route(app, fn)

6.你没读过asyncio的源码才会这样说,func = asyncio.coroutine(func)这方法会内部处理func是协程或生成器,根本无需在外先判断func的类型,最终出来的就是标准的协程函数。

在add_routes都用了method = getattr(func, '__method__', None)了,还要在add_route进行hasattr(fn, '__method__')判断是没有意义的,在add_routes中没有__method__和__route__属性时根本不会调用add_route

add_route这些判断是为单独调用时存在的,然而并没有单独调用的场景。有单独调用的场景我倒不如直接用pp.router.add_route了。

7.看明白了,你只需要简单判断一下callable就可以丢给add_route处理就行了,hasattr(fn, '__method__') and hasattr(fn, '__route__')放在add_route处理就好。

8.async def logger_factory(app, handler): #这就是个装饰器呀

    async def logger(request):

        logging.info('Request: %s %s Begin>>>' % (request.method, request.path))

        # await asyncio.sleep(0.3)

        rst = (await handler(request))

        return rst

    return logger

async def response_factory(app, handler): #这个middleware比较不错,大家在handler里边可以返回各种类型的结果,在这里统一由廖大的response_factory给大家擦屁股。

    。。。

middleware的代码示意:

m1( m2( m3( doFoo())))

middleware调用流程:

req -> m1 -> m2 -> m3 -> doFoo()- 一路return 原路返回

<- m1 <- m2 <- m2 <- resq - <-

本文转自 liqius 51CTO博客,原文链接:http://blog.51cto.com/szgb17/1943522,如需转载请自行联系原作者

你可能感兴趣的文章
羊都哪里去了?
查看>>
大数据打造你的变美频道——数加平台上小红唇的大数据实践
查看>>
Manual手册的正确姿势
查看>>
Python之IPython开发实践
查看>>
Linux 应用程序开发入门
查看>>
MFC ListCtrl和IP控件的使用杂记
查看>>
ActiveMQ_基础学习
查看>>
有关OCS监控软件安装在windows上, 服务端显示乱码的问题
查看>>
Spring对JNDI的支持方法
查看>>
[C#]Attribute特性(2)——方法的特性及特性参数
查看>>
nagios监控单网卡双IP
查看>>
ExtJs之Ext.view.View
查看>>
YII中session和cookie
查看>>
python搭建服务器
查看>>
TCP三次握手及其背后的缺陷
查看>>
zookeeker如何解决HBase单节点故障
查看>>
E-MapReduce结合DataV进行数据展现
查看>>
Cocos2D v2.0至v3.x简洁转换指南(一)
查看>>
HTTP状态码集
查看>>
安装Ubuntu时分区选择
查看>>