301
社区成员
发帖
与我相关
我的任务
分享正向建模
在Java编程中,正向建模(Forward Modeling)通常指的是从设计阶段开始,将系统的需求和规范逐步转化为详细的实现代码。这种方法包括从概念和需求分析出发,通过逐步细化设计,最终编写出完整的代码实现。
需要进行
本单元的正向建模
private void queryBookFormal(){}
private void queryBookDrift(){}
private void borrowBookFormal(){}
private void borrowBookDrift(){}
private void orderBook(){}
private void returnBook(){}
private void pickBook(){}
private void renewBook(){}
private void donateBook(){}
public static void queryUser(LibraryQcsCmd libraryQcsCmd){}
Place接口,有利于统一管理书籍
本单元的开发
Deliver类。这个类和Service类不同。Service类用于响应图书馆的各种操作,控制图书馆,借还处,预约处响应用户的需求Deliver类专门用于移动书籍,所有从Place from移动到Place to的操作都由Deliver类完成;图书馆闭馆后的整理操作也由Deliver完成。因此Deliver中的方法都为静态方法public class Deliver {
public static void moveBook(LibraryReqCmd req, Place from, Place to){}
public static void addReturned(LibraryReqCmd req){}
public static void updateDate(LocalDate date){}
public static void organizeBook(){}
}
Mainutils(Service,Deliver,Check)places(BookShelf,AppoOffice,BoReOffice...)
两者的关系
本单元架构设计
Main中实现四大操作的基本响应if (command instanceof LibraryOpenCmd) {/* 执行开馆操作 */}
else if (command instanceof LibraryCloseCmd) {/* 执行闭馆操作 */}
else if (command instanceof LibraryQcsCmd) {/* 执行查询用户操作 */}
else {/* 执行图书服务操作 */}
Service中通过execute()调用各种图书服务操作,以实现图书服务Deliver中完成移动图书、整理图书的需求Place接口,需要实现四个抽象方法:public interface Place {
void addBook(LibraryReqCmd req, int numToAdd);
void removeBook(LibraryReqCmd req);
boolean containsBook(LibraryReqCmd req);
void check();
}
addBook,removeBook,containsBook,check的操作Deliver.moveBook()方法的简化,对于移动书籍都转换为Place类public static void moveBook(LibraryReqCmd req, Place from, Place to){}

最终的代码设计和UML模型之间的追踪关系
BookShelf,DriftCorner采用单例模式,并且构造方法为publicpublic class BookShelf implements Place {
public BookShelf() { }
}
public class DriftConer implements Place {
public DriftConer() {}
}
AppoOffice采用单例模式,并且构造方法为private。AppoOffice中维护一组保存在预约处的书籍private LinkedList<BookReservation> savedOrders = new LinkedList<>();
BoReOffice,User,均含有属性为BookShelf实例和DriftCorner实例,用于管理存储在借还处或者用户处的正式书籍,漂流书籍。其中BoReOffice采用单例模式public class BoReOffice implements Place {
public static final BoReOffice boReOffice = new BoReOffice();
private final BookShelf bookShelf = new BookShelf();
private final DriftConer driftConer = new DriftConer();
}
public class User implements Place {
private final BookShelf bookShelf = new BookShelf();
private final DriftConer driftConer = new DriftConer();
}
User集合到一个UserTable中,UserTable采用单例模式,用于对每个用户执行一些统一的操作,比如给所有用户处的书籍增加已借阅日期public class UserTable {
public static final UserTable USERS = new UserTable();
private UserTable() {}
public boolean hasUser(String username) {}
public void addUser(String username) {}
public void addOneOwnDay() {}
public void checkOverdue() {}
}
U1 递归下降
在U1中,我的架构思维还比较初步,对于问题的思考和架构主要参考往年学长的博客
对于递归下降解析一个复杂的表达式,使用一个统一的输入处理器Process,表达式解析器Parse,和Expr,Term,Factor三个类去解析这个表达式
在模仿和思考的过程中,我逐步学会了一些架构设计的思维,尤其是在U1的第二次作业中,如何合并同类项。在第二次作业的形式化表达( Unit = ax^nexp( \sum Unit ) )下,判断两个单项式相等不仅要判断a和n,还要判断exp中的(\sum Unit)是否相等,而每个(Unit)中仍有可能继续嵌套(\sum Unit)。参考学长的做法,以及和同学们思考讨论之后,得出了递归判等的方法。伪代码如下:

U2 多线程
Distributor线程完成输入的读取和分发,由多个Elevator线程完成运送乘客
U3 JML
MyNetwork来实现对社交网络中各种请求的响应MyPerson,MyMessage这些类来具体实现U4 UML
设计思维的演进
在四次作业中,通过模仿、学习学长的代码,并加以自己的思考,我架构设计的思维得到了一定的提升,从一开始的依赖他人架构,逐步走向自己思考如何设计出合理的架构,我总结出架构设计的以下三点经验:
根据需求划分
在拿到设计要求的时候,我们首先要认真阅读指导书,对于每次需要实现的需求和功能进行初步的分类。并且一个需求可能会涉及到多个步骤,每个步骤如何完成,交给哪个类完成,是否需要为某个步骤单独考虑而建立一个类都是需要思考的。
进一步细化职责,降低耦合度
思考好之后,可能我们会开始写一些初步的代码,在这个过程我们会发现更多起初没有考虑到的细节,从而可以考虑得更加全面,然后调整每个类在处理请求中的地位,应该承担的功能,把相似的请求或者有密切关联的功能实现在同一个类中,降低类与类之间的耦合度
增加工具层,统一化响应
并且,在四次作业中,我发现了建立工具类来完成对各种请求的统一响应是使得代码层次清晰,架构合理的一个常用方法
比如在U2中大多数同学都采用了Controller类来统一指挥电梯下一步的运行应该是OPNE_AND_CLOSE,SPE_MOVE,MOVE,TURN,WAIT,RESET,SUB_RESET,FINISH中的哪一种
public Instruction getInstruction() {
if () { return Instruction.RESET; }
else if () { return Instruction.SUB_RESET; }
else if () { return Instruction.OPNE_AND_CLOSE; }
else if () { return Instruction.MOVE; }
else if () { return Instruction.TURN; }
else if () { return Instruction.FINISH; }
else { return Instruction.WAIT; }
}
U4中采用Service类来统一完成对QUERIED, BORROWED, ORDERED, RETURNED, PICKED, RENEWED, DONATED操作的响应
public void execute() {
switch (req.getType()) {
case QUERIED:
if (isFormal) { queryBookFormal();
} else { queryBookDrift(); }
break;
case BORROWED:
if (isFormal) { borrowBookFormal();
} else { borrowBookDrift(); }
break;
case ORDERED:
orderBook();
break;
case RETURNED:
returnBook();
break;
case PICKED:
pickBook();
break;
case RENEWED:
renewBook();
break;
case DONATED:
donateBook();
break;
default:
break;
}
}
U1构造嵌套多项式 + 正确性判断
U1是我第一次尝试自己搭建测评机
第一次搭建的测评机主要分为两个部分:数据生成gene.py和运行程序main.py

第二次搭建的测评及沿用第一次测评机的框架

U2构造电梯请求
U3构造社交请求
U3我搭建了数据生成器,而对于输出由于是有唯一答案的输出,因此采用了对拍的方法来实现正确定判断
数据构造的思路就是根据各种操作,完成生成每种操作数据的方法,并且通过随机数来触发各种异常分支,达到可以认为控制覆盖率的目的。
mr id1 id2 value, 因此可能触发的错误有:def mr():
choose = random.randint(1,5)
if choose==1:
mr_wrong_unexisted_id()
elif choose==2:
mr_wrong_unexisted_rel()
elif choose==3:
mr_wrong_same_id()
elif choose==4:
mr_set_value("add")
elif choose==5:
mr_set_value("delete")
同时设计了config参数来修改社交网络的规模,操作指令的条数,达到对程序进行压力测试的目的
# 2. operate times
times={
"ap_times":150,
"ar_times":500,
"mr_times":100,
"at_times":500,
"dt_times":100,
"att_times":2000,
"dft_times":200,
"am_all_times":4000,
"sm_times":800,
"cn_times":50,
"sei_times":100,
"dce_times":50
}
U4进行书架检查
Check类,在BookShelf,AppoOffice,BoReOffice...等类中实现了check()方法,来查看图书馆的情况CLOSE: 2024-06-12
--------------------
书架:
A-8175 : 5
----------
B-0074 : 0
B-3378 : 1
B-5645 : 3
B-6328 : 3
B-6894 : 5
B-8903 : 1
----------
C-4217 : 0
C-6627 : 0
C-6685 : 0
--------------------
借还处:
B-0074 : 0
B-3378 : 0
B-5645 : 0
/* ... */
/* ... */
/* ... */
--------------------
用户:
60997402:
B-8903 : 1
----------
C-6685 : 1
CU-5618 : 1
{CU-5618=0}
信用积分:14
{CU-5618=14, B-8903=30, C-6685=60}
{CU-5618=64, B-8903=1, C-6685=143}
/* ... */
/* ... */
/* ... */
测试思维的演进
学会了搭建测评机
学会了架构设计