4

私はこのサイトの初心者で、これが最初の質問です。

Web サイトを作成する必要があり、Java と Struts2 を使用していますが、Struts2 は初めてです。

私のサイトでは、Facebook へのリクエストを行い、OAuth で認証を受ける必要があります。

アクション ページの execute メソッドですべてのプロセス (認証と保護されたリソースの要求) を実行しています。このプロセスは非常に複雑で、Facebook と Web の間で多くのリダイレクトが発生します。

先日、「複数のメソッドでアクションを作成しないでください。「実行」と実行したい操作(「createUser」など)で十分です」(http://freeopenidea.blogspot.com.es/より)を読みました。 2010/04/struts2-best-practices.html )。

ほとんどのコードは、最初に接続するときにこのプロセスを実行するため、別の瞬間にサイトの別の部分から呼び出すことができますが、連絡先リストを更新するためにこれ (または同様のこと) を実行できます。

1 - 必要なメソッド用に別のクラス (アクションではない) を作成し、それらを「実行」メソッドから呼び出す必要がありますか?

2 - コードはアクション ページに保持する必要がありますが、「実行」とは別のメソッドに保持する必要がありますか? そして、いくつかのタスクを実行する必要があるたびに、このページを呼び出します。

コードをどこに置くべきかわかりません (そして、accessToken を保存する必要があることはわかっています。複雑さを示すためにコードを貼り付けるだけですが、修正は見ていません)。

public String execute() throws Exception{
   if (code!=null){
      Verifier verifier = new Verifier(code);
      //get the accessToken to do requests
      Token accessToken = service.getAccessToken(EMPTY_TOKEN, verifier);
      OAuthRequest requestList = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL);
      service.signRequest(accessToken, requestList);
      Response responseList = requestList.send();
      if (responseList.getCode() == 200){
        //I get the Friends List
        JsonParse parser = new JsonParse();
        JSONObject json = (JSONObject) JSONSerializer.toJSON(responseList.getBody());
        JSONArray datos = json.getJSONArray("data");
        for (Object o : datos) 
        {//for every friend of the list I do this
            JSONObject elem = (JSONObject) o;
            String id = elem.getString("id");                
            OAuthRequest requestFriend = new OAuthRequest(Verb.GET,"https://graph.facebook.com/"+id);
            service.signRequest(accessToken, requestFriend);
            Response responseFriend = requestFriend.send();
            if (responseFriend.getCode() == 200){
                JsonParse parserAux = new JsonParse();
                PerfilContacto pcBean = parserAux.parseFacebookElement(responseFriend.getBody());
                pcDAO.insertarContacto(pcBean); 
            }
        }
      }
      return SUCCESS; 
   }      
   else return ERROR;    
 }
4

1 に答える 1

3

アクションメソッドのコードが多すぎるIMO。アクションは、Web レイヤーとビジネス レイヤーの間のレイヤーを処理する必要があります。このレベルの結合、特にハードコーディングされたクラスのインスタンス化では、アクションのロジックを分離してテストすることが非常に困難になります。

基本的にすべてのコードをサービスに移動します。このアクションは、サービスの相互作用のみに関連しています。フレームワークは、の存在を検証しcodeます。サービスは Struts 2 の外部でテストされます。アクションはモック サービスでテストされます。

完全にテストされていませんが、私のコードは以下のものにはるかに近いと思われます. あるタイプの複雑さを別のタイプと交換しますが、複数の利点をもたらします。各メソッドは、焦点が絞られており、読みやすいです。サービス呼び出しは分離されているため、さまざまなモードのサービス障害をテストできます。これは、システムの動作と機能を詳細に表現したものです。

アクション

public String execute() throws Exception {
    fbService.updateFriends(code);
    return SUCCESS;
}

FBサービス

public void updateFriends(String code) {
    Token accessToken = getAccessToken(code);
    Response response = getFriends(accessToken);
    if (response.getCode() == 200) {
        processFriends(accessToken, response);
    }
}

private void processFriends(Token accessToken, Response response) {
    JSONObject json = (JSONObject) JSONSerializer.toJSON(response.getBody());
    JSONArray datos = json.getJSONArray("data");
    for (Object o : datos)  {
        JSONObject friend = (JSONObject) o;
        processFriend(friend);
    }
}

private void processFriend(Token accessToken, JSONObject friend) {
    Response response = getFriendGraph(accessToken, friend.getString("id"));
    if (response.getCode() == 200){
        PerfilContacto pcBean = new JsonParse().parseFacebookElement(response.getBody());
        pcDAO.insertarContacto(pcBean); 
    }
}

//~ Service interaction

private Response getFriends(Token accessToken) {
    return sendSignedGetRequest(PROTECTED_RESOURCE_URL, accessToken);
}

private Response getFriendGraph(Token accessToken, String id) {
    return sendSignedGetRequest("https://graph.facebook.com/" + id, accessToken);
}

private Token getAccessToken(String code) {
    return service.getAccessToken(EMPTY_TOKEN, new Verifier(code));
}

private Response sendSignedGetRequest(String url, Token accessToken) {
    OAuthRequest request = new OAuthRequest(Verb.GET, url);
    service.signRequest(accessToken, request);
    return request.send();
}

メトリックを考慮すると、次のようになります。

オリジナル:

Average Function NCSS:      24.00
Average Function CCN:        6.00
Program NCSS:               25.00

再加工:

Average Function NCSS:       3.63
Average Function CCN:        1.38
Program NCSS:               31.00

最終的には、次のことを意味します。

  • 有意な LOC の数はあまり増加しませんでした。
  • 各関数の長さは 4 行未満です (読みやすい)。
  • 各関数の循環的複雑度は 2 未満です (テストと推論が容易です)。
  • プログラムは、それが行っていることのように読み取り、より迅速に理解できるようになります。

トレードオフは、複雑さの一種であるより多くのメソッドがあることです (合理的な IDE またはテキスト エディターを考えると、これは大きな問題はなりません)。でも:

  • 選択した深さで読むのをやめることができます。
  • はるかに細かい粒度でテストできます。
  • 見逃した可能性のある成功/失敗モードを特定できます。
  • 機能をより簡単に交換および/または拡張できます。
于 2012-09-19T21:20:59.907 に答える