重构 01

# 这是一份echo服务器代码, 来自于Interprocess Communication and Networking部分,
# 来自于Shaka, 总的来讲, 写得还好!
# 在征得Shaka的同意后, 做少量的重构!


# 第一步: 理解代码
from socket import *
from signal import *
import time
def sigint_handler(signum, frame):
global is_sigint_up
is_sigint_up = True
print 'interrupt signal is up, server is cleaning up...'

signal(SIGINT, sigint_handler)
is_sigint_up = False
identify = lambda addr: '%s:%d' % (addr[0], addr[1])
local_id = identify
peer_id = identify
curr_time = lambda struct_time: '(%d-%d-%d %d:%d:%d)' % \
         (struct_time[0], \
          struct_time[1], \
          struct_time[2], \
          struct_time[3], \
          struct_time[4], \
          struct_time[5])
host = '127.0.0.1'
port = 8000
serv_addr = (host, port)
backlog = 5
buff_size = 8192
listen_sock = socket(AF_INET, SOCK_STREAM)
listen_sock.bind(serv_addr)
listen_sock.listen(backlog)
print 'echo-server is running at (%s)' % local_id(serv_addr)
conn_sock = None
peer_addr = ''
while not is_sigint_up:
conn_sock, peer_addr = listen_sock.accept()
print 'request from %s   ...accepted' % peer_id(peer_addr)
print 'session with %s   ...started' % peer_id(peer_addr)
print

try:
  while True:
   recv_data = conn_sock.recv(buff_size) # except socket.error
   if not recv_data: break   # for tcp, receiving none data on blocking socket means that peer has closed.
   print peer_id(peer_addr), curr_time(time.localtime())
   print ' ', recv_data
   print
   
   conn_sock.sendall(recv_data) # except socket.error
   print local_id(serv_addr), curr_time(time.localtime())
   print ' ', recv_data
   print
   
  conn_sock.close()
  print 'session with %s ending   ...finished' % peer_id(peer_addr)

except error, (sock_error_no, sock_error_msg):
  conn_sock.close()
  print sock_error_msg + '!'
  print 'session with %s broken...' % peer_id(peer_addr)
  print
  
except KeyboardInterrupt: # KeyboardInterrupt has no-effect! KeyboardInterrupt is concerned to I/O.
  pass
  
finally:
  pass # Why conn_sock.close() has been placed here?
   
raw_input('hit to quit')


第二步: 确定单元范围并做出分析
identify = lambda addr: '%s:%d' % (addr[0], addr[1])
local_id = identify
peer_id = identify
curr_time = lambda struct_time: '(%d-%d-%d %d:%d:%d)' % \
         (struct_time[0], \
          struct_time[1], \
          struct_time[2], \
          struct_time[3], \
          struct_time[4], \
          struct_time[5])
         
lambda表达式identify意在对(ip, port)元组进行字符串格式化.
local_id、peer_id则是从命名着手, 提高代码的意图性.
curr_time同样是lambda表达式, 旨在提取出time struct的年月日时分秒,
进行格式化.


第三步: 实行重构
identify = lambda addr: '%s:%d' % addr # 无须一一提取元组的值
local_id = identify      # 不变
peer_id = identify      # 不变
curr_time = lambda struct_time=time.localtime(): '(%d-%d-%d %d:%d:%d)' % \
                                                 struct_time[:6]
                                        # 借助元组的slice操作
                                                
第四步: 回归测试
第五步: 循环1~4步