双人(或者两个团队)合作写一个软件,如何做到前台后台并行开发相互不受影响?

我以软工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...
}

模块开发完成。