一次“任性”的编码

摘要:
最近,我用Python编写了一个小工具,结合我在C#重构方面的经验,我经历了一段不同的旅程。当我开始编写这个工具时,我决定不做任何设计,而是“任性”地编写代码,看看它最终会是什么样子。这意味着代码将重复多次。因此,我决定第一次重构它以删除重复的代码。重构之后,我进一步了解了如何实现这个工具。defget_qtn_id_by_sch_number:val=连接。单值打印defget_offer_id_by_sch_number:val=连接。我对当前的价值打印代码感到满意。所以我遵循当前的思路,继续编写以下代码:defget_qtn_id_by_sch_number:val=connection。单值输出!

最近又用Python写了一个小工具,结合自己在C#上已有的一点重构经验,让我又经历了一次不一样的旅行。

当我开始写这个工具的时候,我决定不做任何设计,来一次“任性”的编码,看最终会是什么样子。

于是,我开始用sublime创建了一个新文件py文件,然后开始在里面写main函数。

当我把main这个单词在屏幕上打出来时,我才开始思考。这个工具要实现的是验证数据库中数据的功能,因此我需要先打开数据库的连接。于是,我写出了下面这段代码

def main():
    with pypodbc.connect('....') as con:
        with con.cursor() as cur:
            pass

当我写完这段代时,我意识到会有很多的值需要从数据库里面读出来验证。这就意味着这段代码肯定会被多次重复。因此,我决定对其进行第一次重构,移除重复代码。重构之后,我对如何实现这个工具有了进一步的认识。然后我又写出了下面这段代码

import sys
import connection

def get_qtn_id_by_sch_number(schedule_number):
    def get_qtn_id(cursor):
        cursor.execute("select id from phoenix.phx_quotations where lease_number='%s' "% schedule_number)

        for row in cursor.fetchall():
            print('quotation id:%s'%row[0])
            return row[0]

        return None
    return connection.run(get_qtn_id)


def get_offer_id_by_sch_number(schedule_number):
    def get_offer_id(cursor):
        cursor.execute("select offer.id from phoenix.phx_offers offer inner join phoenix.phx_quotations qtn on qtn.id = offer.qtn_id where qtn.lease_number='%s'"%schedule_number)

        for row in cursor.fetchall():
            print('offer id:%s'%row[0])
            return row[0]

        return None

    return connection.run(get_offer_id)

在这段代码里面,连接数据库的代码没有重复,被connection类取代了。但是当我把第二个函数写完时,我又感觉到了不对劲。因为我意识到每段sql的执行只返回一个值。如果每个函数都这么写,还是会出现不少重复代码。于是我进行了第二次重构。

def get_qtn_id_by_sch_number(schedule_number):
    val = connection.single_value("select id from phoenix.phx_quotations where lease_number='%s' "% schedule_number)
    print('quotation id:%s'%val)


def get_offer_id_by_sch_number(schedule_number):
    val = connection.single_value("select offer.id from phoenix.phx_offers offer inner join phoenix.phx_quotations qtn on qtn.id = offer.qtn_id where qtn.lease_number='%s'"%schedule_number)

    print('offer id:%s'%val)

现在的代码让我感到比较满意。于是我就顺着当前的思路,继续写出了下面这段代码

def get_qtn_id_by_sch_number(schedule_number, out):
    val = connection.single_value("select id from phoenix.phx_quotations where lease_number='%s' "% schedule_number)

    if out != None:
        out.add('quotation id:%s'%val)

    return val


def get_offer_id_by_sch_number(schedule_number, out):
    val = connection.single_value("select offer.id from phoenix.phx_offers offer inner join phoenix.phx_quotations qtn on qtn.id = offer.qtn_id where qtn.lease_number='%s'"%schedule_number)

    if out != None:
        out.add('offer id:%s'%val)

    return val

def get_vat_by_sch_number(schedule_number, out):
    val = connection.single_value('''
        select vat from phoenix.phx_invoices
        where id=%s
        '''% get_inv_id_by_sch_number(schedule_number, out))

    if out != None:
        out.add('VAT is:%s'%val)
    return val

def get_inv_id_by_sch_number(schedule_number, out):
    val = connection.single_value("select inv_id from phoenix.phx_invoice_mappings where off_id=%s"%get_offer_id_by_sch_number(schedule_number, out))
    inv_number = connection.single_value('''select inv.inv_number from phoenix.phx_invoices inv
        inner join phoenix.phx_invoice_mappings imp on inv.id = imp.inv_id
        where imp.off_id=%s
        '''%get_offer_id_by_sch_number(schedule_number, out))

    if out != None:
        out.add('inv id:%s'%val)
        out.add('inv number:%s'%inv_number)

    return val

def get_imd_status_by_sch_number(schedule_number, out):
    val = connection.single_value('''
        select imd.status from phoenix.phx_imd_statuses imd
        inner join phoenix.phx_invoices inv on inv.ims_id = imd.id
        where inv.id = %s
        '''%get_inv_id_by_sch_number(schedule_number, out))

    if out != None:
        out.add('invoice status:%s'%val)

    return val

def get_purchase_option_by_sch_number(schedule_number, out):
    val = connection.single_value('''
        select bo.billing_option_desc from phoenix.phx_billing_options bo
        inner join phoenix.phx_offer_bill_details obd on bo.billing_option_id = obd.purchase_opt_id
        where obd.offer_id = %s
        '''% get_offer_id_by_sch_number(schedule_number, out))

    if out != None:
        out.add('billing option:%s'%val)

    return val

这时,我又觉得不对劲。每个方法里面都有对out的判断,这是一种重复。于是我进行了第三次重构。

def get_qtn_id_by_sch_number(schedule_number, out):
    sv = single_value.single_value("select id from phoenix.phx_quotations where lease_number='%s' "% schedule_number)
    sv.set_out(out)
    sv.set_title('quotation id')

    return sv.execute()


def get_offer_id_by_sch_number(schedule_number, out):
    sv = single_value.single_value("select offer.id from phoenix.phx_offers offer inner join phoenix.phx_quotations qtn on qtn.id = offer.qtn_id where qtn.lease_number='%s'"%schedule_number)
    sv.set_out(out)
    sv.set_title('offer id')

    return sv.execute()


def get_vat_by_sch_number(schedule_number, out):
    sv = single_value.single_value('''
        select vat from phoenix.phx_invoices
        where id=%s
        '''% get_inv_id_by_sch_number(schedule_number, out))
    sv.set_out(out)
    sv.set_title('VAT')

    return sv.execute()


def get_inv_id_by_sch_number(schedule_number, out):
    sv = single_value.single_value("select inv_id from phoenix.phx_invoice_mappings where off_id=%s"%get_offer_id_by_sch_number(schedule_number, None))
    sv.set_out(out)
    sv.set_title('inv id')

    sv_number = single_value.single_value('''select inv.inv_number from phoenix.phx_invoices inv
        inner join phoenix.phx_invoice_mappings imp on inv.id = imp.inv_id
        where imp.off_id=%s
        '''%get_offer_id_by_sch_number(schedule_number, out))
    sv_number.set_out(out)
    sv_number.set_title('inv number')

    sv_number.execute()

    return sv.execute()

def get_imd_status_by_sch_number(schedule_number, out):
    sv = single_value.single_value('''
        select imd.status from phoenix.phx_imd_statuses imd
        inner join phoenix.phx_invoices inv on inv.ims_id = imd.id
        where inv.id = %s
        '''%get_inv_id_by_sch_number(schedule_number, out))
    sv.set_out(out)
    sv.set_title('invoice status')

    return sv.execute()

def get_purchase_option_by_sch_number(schedule_number, out):
    sv = single_value.single_value('''
        select bo.billing_option_desc from phoenix.phx_billing_options bo
        inner join phoenix.phx_offer_bill_details obd on bo.billing_option_id = obd.purchase_opt_id
        where obd.offer_id = %s
        '''% get_offer_id_by_sch_number(schedule_number, out))
    sv.set_out(out)
    sv.set_title('billing option')

    return sv.execute()

当我完成第三次重构时,我对目前的代码比较满意。因为它将过程中的数据转换成了single_value类的状态。single_value类根据当前的状态来决定是否执行这个过程。这样,if out != None就被封装了起来。这也增强了single_value的灵活性。

虽然重构了三次,但整个过程,都比较愉快。因为这三次重构都是根据开发推进的具体阻力来完成的。这也让我再次体会到了软件系统架构设计就是将不变的核心部分从可变的细节中分离出来的道理。

软件架构设计并不是对设计模式和架构模式的生搬硬套,而是对特定软件项目的不变核心部分的深刻理解和发现。

免责声明:文章转载自《一次“任性”的编码》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇VisualSVN服务器的本地搭建和使用MAC 忘记Homebrew安装的mysql密码下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

GB2312编码(为什么要加2020H、8080H,外码→内码→交换码→字形码)

为什么要加上2020H和8080H? 区位码、内码、国标码怎么转换非常简单,但是令人迷惑的是为什么要那么转换?这种转换不可能平白无故地那样转换! 我搜索很多资料,找到最好的解释,总结如下: 首先,注意到一点,GB2312虽说是对中文编码,但是里面有对26个英文字母和一些特殊符号的编码,按理说这和ASCII重合的部分应该无需设置,沿用ASCII中不就行了?但...

使用原生 python 造轮子搭建博客

这篇用来 记录一个 从零开始的 博客搭建,希望坚持下去,因为python 开发效率令人发指,所以会原生从零写 ORM ,Web 框架 前提是打好 异步 io 的基础, 使用异步,有一点要谨记,一旦开始异步,层层异步,从 http 到 数据库层都要用异步框架写异步函数,所谓开弓没有回头箭 # -*- coding: utf-8 -*- import asy...

【转】宽字节注入详解

前言在mysql中,用于转义的函数有addslashes,mysql_real_escape_string,mysql_escape_string等,还有一种情况是magic_quote_gpc,不过高版本的PHP将去除这个特性。 首先,宽字节注入与HTML页面编码是无关的,笔者曾经看到 <meta charset=utf8>...

代码页

  最近写一个网络程序时,碰到字符串和字节数组之间的转换问题,开始时还比较简单,字符串都是标准的Ascll编码,处理起来比较简单:字符串转字节数组 byte [] bts=Encoding.ASCII.GetBytes(str);字节数组转字符串 string str=Encoding.ASCII.GetString(bts);但是后来发送的数据不仅仅是A...

【转】一个URL编码和解码的C++类

下面的代码实现了一个用于C++中转码的类strCoding。里面有UTF8、UNICODE、GB2312编码的互相转换。 .H文件: #pragma once #include <iostream> #include <string> #include <windows.h> using namespace std;...

oracle 字符集

影响Oracle数据库字符集最重要的参数是NLS_LANG参数。 它的格式如下: NLS_LANG = language_territory.charset 它有三个组成部分(语言、地域和字符集),每个成分控制了NLS子集的特性。 其中: Language: 指定服务器消息的语言, 影响提示信息是中文还是英文 Territory: 指定服务器的日期和数字格...