技术开发 频道

敏捷开发的必要技巧(四)

【IT168 技术文章】    这是一个会议管理系统,它用来管理所有参会者的信息。刚开始的时候,我们只需要记录每个参会者的ID(这是会议组织者分配的)、姓名、电话和地址就行。于是,我们写了如下代码:

class Participant { String id; String name; String telNo; String address; } class ConferenceSystem { Participant participants[]; }

    接着,新的需求来了。现在每个参会者可以让组织者帮忙预订酒店,所以我们要记录他想预订的酒店名、入住日期、离开日期、房间类型(单人房或双人房)。于是,我们又扩充成如下代码:

class Participant { String id; String name; String telNo; String address; boolean bookHotelForHim; String hotelName; Date checkInDate; Date checkOutDate; boolean isSingleRoom; void setHotelBooking(String hotelName, Date checkInDate, ...) { ... } }

    接着,又来了一个新需求:参会者可以参加不同的研讨会,所以我们要记录下参会者参加的研讨会。对于他要参加的每一场研讨会,我们还要记录下他的登记时间,同时记录他需要什么翻译设备。于是代码又扩充成:

class Participant { String id; String name; String telNo; String address; boolean bookHotelForHim; String hotelName; Date checkInDate; Date checkOutDate; boolean isSingleRoom; String idOfSeminarsRegistered[]; Date seminarRegistrationDates[]; boolean needSIDeviceForEachSeminar[]; void setHotelBooking(String hotelName, Date checkInDate, ...) { ... } void registerForSeminar(String seminarId, Date regDate, boolean needSIDevice) { //将seminarId加到idOfSeminarsRegistered //将regDate加到seminarRegistrationDates //将needSIDevice加到needSIDeviceForEachSeminar. } boolean isRegisteredForSeminar(String seminarId) { ... } Date getSeminarRegistrationDate(String seminarId) { ... } boolean needSIDeviceForSeminar(String seminarId) { ... } String [] getAllSeminarsRegistered() { return idOfSeminarsRegistered; } }

代码开始肿胀

    请注意,这已经是我们第二次扩充Participant这个类了。每扩充一次,它就包含了更多的代码(实例变量和方法)及更多的功能。本来它只有4个属性。现在已经是12个了。此外,这个类要处理的业务逻辑也极大的增加。本来它只需要处理参会者的基本信息(姓名、地址等),现在它还要包含酒店、酒店预订、研讨会和翻译设备等的逻辑。如果以后还有新需求,我们又要扩充Participant类,到时候这个类要复杂庞大成什么样子?所以我们得修整这个类。
    如何修整Participant类呢?如何让它一直保持在第一天那样的简洁度?在回答这两个问题之前,我们先来考虑另一个需要优先回答的问题:给你一个类,你怎么判断它需要修整?

怎么判断一个类需要修整

    要判断一个类是否需要修整,一个比较主观的方法是,当在读一个类的代码时,看看我们会不会觉得这个类“太长”、“太复杂”,或者概念“太多”?如果这样觉得,我们就认定,这个类需要修整。
    另外一个比较简单而且客观的方法是,当发现我们已经在第二次或者第三次扩充这个类时,我们认定这个类要修整了。这是一个比较“懒惰”、“被动”的方法,却很有效。
    现在让我们看一下怎么修整Participant这个类吧。

抽取有关酒店预订的功能

    首先,考虑一下怎么抽取出酒店预订的功能。一个可行的方案是:

class Participant { String id; String name; String telNo; String address; } class HotelBooking { String participantId; String hotelName; Date checkInDate; Date checkOutDate; boolean isSingleRoom; } class HotelBookings { HotelBooking hotelBookings[]; void addBooking(HotelBooking booking) { ... } } class ConferenceSystem { Participant participants[]; HotelBookings hotelBookings; }

    现在,Participant类一点都不知道酒店预订的存在。当然,我们不一定要用数组来存放酒店预订情况。比如,我们可以用Map:

class Participant { String id; String name; String telNo; String address; } class HotelBooking { String participantId; String hotelName; Date checkInDate; Date checkOutDate; boolean isSingleRoom; } class HotelBookings { HashMap mapFromPartIdToHotelBooking; //必须提供参会者ID void addBooking(String participantId, HotelBooking booking) { ... } } class ConferenceSystem { Participant participants[]; HotelBookings hotelBookings; }

    这一方案的优点是Participant一点都不知道HotelBooking的存在,Participant不依赖于HotelBooking。还有另一个可行的方案是:

class Participant { String id; String name; String telNo; String address; HotelBooking hotelBooking; } class HotelBooking { String hotelName; Date checkInDate; Date checkOutDate; boolean isSingleRoom; } class ConferenceSystem { Participant participants[]; }

    注意到,在这一方案里,Participant类还是要知道HotelBooking的存在,也就是说Participant还是要知道有酒店预订这回事。只是具体酒店预订是怎么做的,这些真正的功能放在HotelBooking里面实现。
    因为每个Participant都直接引用了本人的酒店预订情况,所以可以直接找到他的酒店预订情况。而代价就是,Pariticipant还是要知道酒店预订的概念。从类的关系来讲,Pariticipant还要依赖HotelBooking这个类。
    当然,除了以上几种情况,还有许多其他的可行方案。

抽取研讨会的相关功能

    现在我们来考虑一下怎么抽取出研讨会的功能。一个可行的方案是:

class Participant { String id; String name; String telNo; String address; } class SeminarRegistration { String participantId; String seminarId; Date registrationDate; boolean needSIDevice; } class SeminarRegistry { SeminarRegistration registrations[]; void registerForSeminar(SeminarRegistration registration) { //将registration加到registrations } boolean isRegisteredForSeminar(String participantId, String seminarId) { ... } Date getSeminarRegistrationDate(String participantId, String seminarId) { ... } boolean needSIDeviceForSeminar(String participantId, String seminarId) { ... } SeminarRegistration[] getAllRegistrations(String participantId) { ... } } class ConferenceSystem { Participant participants[]; SeminarRegistry seminarRegistry; }

改进后的代码

    下面是改进后的代码:

class Participant { String id; String name; String telNo; String address; } class HotelBooking { String participantId; String hotelName; Date checkInDate; Date checkOutDate; boolean isSingleRoom; } class HotelBookings { HotelBooking hotelBookings[]; void addBooking(HotelBooking booking) { ... } } class SeminarRegistration { String participantId; String seminarId; Date registrationDate; boolean needSIDevice; } class SeminarRegistry { SeminarRegistration registrations[]; void registerForSeminar(SeminarRegistration registration) { //将registration加到registrations } boolean isRegistered (String participantId, String seminarId) { ... } Date getRegistrationDate(String participantId, String seminarId) { ... } boolean needSIDevice(String participantId, String seminarId) { ... } SeminarRegistration[] getAllRegistrations(String participantId) { ... } } class ConferenceSystem { Participant participants[]; HotelBookings hotelBookings; SeminarRegistry seminarRegistry; }
0
相关文章