双人(或者两个团队)合作写一个软件,如何做到前台后台并行开发相互不受影响?
我以软工CW的用户登录功能举例,用MVC模式的角度作简要阐述。
首先,在对需求的了解的基础上,双方共同约定Controller的所有接口,一般是前台人员提出需求,后台人员针对数据结构对值类型做优化。比如前台现在需要做一个用户登录,那么需要一个隶属于UserController的login方法加此外,为了进一步使前后台相分离,Controller建议使用单例模式并采用以下instance
写法。
package controller;
public interface UserController {
/**
* The unique controller instance.
*/
public final static UserController instance = null;
/**
* Login method
* @param username The username.
* @param password The password.
* @throws Exception "No such user" or "invalid password".
*/
public void login(String username, char[] password) throws Exception;
// Other methods...
}
接口约定后,前后台可以分别进行开发。
前台在假设Controller已开发完备的基础上,进行界面设计等一系列操作。
前台需要调用Controller的方法时,使用Controller.instance.方法名的方式进行调用,见actionPerformed:3
处。
前台代码:
package view;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPasswordField;
import javax.swing.JTextField;
import controller.UserController;
@SuppressWarnings("serial")
public class LoginWindow extends JFrame implements ActionListener {
private JTextField txtUsername;
private JPasswordField txtPassword;
public LoginWindow()
{
super("Login");
txtUsername = new JTextField();
txtPassword = new JPasswordField();
JButton btnLogin = new JButton("Login");
setLayout(new GridLayout(3,2));
add(new JLabel("username"));
add(txtUsername);
add(new JLabel("password"));
add(txtPassword);
add(new JLabel(""));
add(btnLogin);
btnLogin.addActionListener(this);
pack();
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
}
@Override
public void actionPerformed(ActionEvent e) {
try
{
UserController.instance.login(txtUsername.getText(), txtPassword.getPassword());
JOptionPane.showMessageDialog(this, "Login Successful!");
}
catch(Exception ex)
{
JOptionPane.showMessageDialog(this, ex.getMessage());
}
}
public static void main(String[] args)
{
new LoginWindow().setVisible(true);
}
}
后台代码:开发的过程主要是对约定接口的实现过程,在本例中是实现login方法。
package controller;
import java.util.Arrays;
import valueobject.User;
import model.UserList;
class UserControllerImpl implements UserController {
@Override
public void login(String username, char[] password) throws Exception {
UserList userList = UserList.getInstance();
for(User user : userList)
{
if(username.equals(user.getUsername()))
{
if(Arrays.equals(password, user.getPassword()))
{
return;
}else{
throw new Exception("Invalid Password");
}
}
}
throw new Exception("No Such User.");
}
}
Model端主要是文件操作,与讨论主题无关。
package model;
import java.util.ArrayList;
import valueobject.User;
@SuppressWarnings("serial")
public class UserList extends ArrayList<User> {
private static UserList instance;
public static UserList getInstance()
{
if(instance == null)
instance = new UserList();
return instance;
}
private UserList()
{
super();
loadData();
}
private void loadData()
{
//Load from file.
add(new User("admin", new char[]{'p','w','d'}));
}
public void saveData()
{
//Save to file.
}
}
因为CW不许使用数据库,所以用定义valueobjct的方式定义字段。
package valueobject;
public class User {
private String username;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
private char[] password;
public char[] getPassword() {
return password;
}
public void setPassword(char[] password) {
this.password = password;
}
public User(String username, char[] password)
{
setUsername(username);
setPassword(password);
}
}
此时前后台已分别开发完成。
最后一步,更改接口中的instance静态属性,使其引用实现后的实体对象。
package controller;
public interface UserController {
/**
* The unique controller instance.
*/
public final static UserController instance = new UserControllerImpl();
/**
* Login method
* @param username The username.
* @param password The password.
* @throws Exception "No such user" or "invalid password".
*/
public void login(String username, char[] password) throws Exception;
// Other methods...
}
模块开发完成。