如果我们只能返回一个值并在视图中设置(MVP结构)

时间:2016-07-29 06:18:35

标签: android unit-testing mvp

已经两个月了,我一直在与MVP Structure合作创建Android应用程序。

正如我在MVP中发现的每个链接所解释的那样,Presenter类负责所有业务登录和数据(来自Model类),我理解并开始工作。

教程中显示的优势之一,我想在此强调MVP使单元测试更容易,因为没有视图的依赖性(我也明白了)。

我不明白为什么要创建界面来更新来自演示者的视图,而我可以调用一个将返回值的演示者方法,我可以在那里设置它?

让我发挥上面谈到的优势(单元测试)。使用那些接口单元测试会更成问题,因为方法需要一个接口实现来完成我们在单元测试中没有的操作(我知道Instrumental测试也来自单元测试,但我只谈论非ui测试)。 / p>

我更喜欢调用presenter方法并获取值并在视图中设置片段或活动本身,因为创建接口会创建另一级别的复杂性和不必要的接口声明,所有视图操作都将被实现。它有点令人沮丧。

我正在与之合作的一位朋友在我的代码中指出了这个问题并告诉我查看所有在线参考资料以澄清我的错误。但我想知道这些接口如何在编程实践中提供全面的帮助。因为我不能只是消化它。它变成了我的屁股的痛苦。我查看了所有在线参考文献没有解决方案。

实施例

带界面的演示者

class Presenter
{

    private ViewInterface viewInterface;

    public void setViewInterface(ViewInterface viewInterface)
    {
        this.viewInterface = viewInterface;
    }

    // Here value is being passed to interface method that is implemented in fragment.
    // No problem with this implementation but why to do it. 
    // It will make unit test problematic as this method needs ViewInterface.
    public void calculate()
    {
        // Some calculation
        viewInterface.updateView(/*pass some paramerer*/);
    }
}

没有界面的演示者

class Presenter
{


    // Here just take the value and set the view in fragment
    // Unit test easier just check the returned value.
    public int calculate()
    {
        int result = -1;
        // Some calculation
        return result;
    }
}

使用演示者的片段

class MyFragment extends Fragment{

    ....

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.layout1, container, false);
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState)
    {
        super.onViewCreated(view, savedInstanceState);
        // just call method and get value to set in a view.
        int result = new Presenter().calculate();
        // set result in a view
    }

}

请检查上述代码中的评论。

任何帮助将不胜感激。 提前谢谢。

1 个答案:

答案 0 :(得分:4)

仅仅几个月,因为我从我自己的新手代码转换到MVP,我不得不说学习这个架构让我成为一个更好的程序员,让我对Interfaces有了新的认识。

我没有教育或经验,谈论SOLID或计算机科学中的任何其他原则,但我可以根据我所学到的经验向您提供我的意见。

为每个组件提供接口使您可以轻松查看应用程序的功能。

查看以下合同,找到here

我确切地知道在这个应用程序的整个模块中发生了什么。 如果我关心如何完成任务,我可以看一下实现。 在编写单元测试时,我并不关心事情是如何工作的,只是他们能够工作。 我可以更改每个组件,M,V或P,而不会破坏我的应用程序中的任何内容。

当我们对同一个模型有多个视图时,可能会有一个用例。 我们可以有一个ProductListCustomView,一个ProductListFragment和一个ProductListActivity。我们可以根据运行应用程序的设备选择其中一个。所有这些都实现了相同的接口,因此即使在运行时也很容易进行更改。

public class ProductListContract {

public interface View {
    void showProducts(List<Product> products);

    void showAddProductForm();

    void showEditProductForm(Product product);

    void showDeleteProductPrompt(Product product);

    void showGoogleSearch(Product product);

    void showEmptyText();

    void hideEmptyText();

    void showMessage(String message);

}

public interface Actions {
    void loadProducts();

    void onAddProductButtonClicked();

    void onAddToCartButtonClicked(Product product);

    Product getProduct(long id);

    void addProduct(Product product);

    void onDeleteProductButtonClicked(Product product);

    void deleteProduct(Product product);

    void onEditProductButtonClicked(Product product);

    void updateProduct(Product product);

}

public interface Repository {
    List<Product> getAllProducts();

    Product getProductById(long id);

    void deleteProduct(Product product);

    void addProduct(Product product);

    void updateProduct(Product product);

}

}

查看上面的示例,除非您有多个演示者实现,否则我认为不需要Presenter的界面。 我想不出View可以与多个Presenter类型相关联的场景(例如LongProductListPresenter,ShortProductListPresenter等)

使用MVP完成应用程序几个月后,您可以决定更改部分视图,将其转换为自定义视图,或将Layouts转换为Android发布的最新功能。

您可能还决定使用其他库来存储您的数据或网络。

您可能希望对演示者中的逻辑进行更改,但是您不可能在一天早上醒来并决定是否需要为您的应用程序使用全新的演示者。

Google的MVP todo示例使用演示者的界面。因此,绝大多数开发人员都会这样做。如果他们有一天更改此示例应用程序,那么其他所有人都会很快效仿。

在一天结束时,您是架构师,您构建应用程序的方式是您(或您老板的)决定。

我希望无论你做出何种选择,你都会更自信地做出自己的决定。

这是另一篇关于这个主题的文章。

http://blog.karumi.com/interfaces-for-presenters-in-mvp-are-a-waste-of-time/