Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Refactoring-mvp-Anti-Pattern

 Refactoring-mvp-Anti-Pattern

きりみん

May 10, 2017
Tweet

More Decks by きりみん

Other Decks in Programming

Transcript

  1. MVP΍ͬͯ·͔͢ʁ • MVP = Model View Presenter • Androidք۾ͰMVP͕࿩୊ʹͳͬͨͷ͸2೥͘Β͍લɻ •

    MVPΛ࠾༻͍ͯ͠ΔϓϩδΣΫτ΋݁ߏݟ͔͚Δҹ৅ɻ • ओͳϝϦοτͱͯ͠Α͘ςετͷॻ͖΍͕͢͞ ڍ͛ΒΕ͍ͯͨɻ
  2. public class MainActivity extends AppCompatActivity {
 
 private MainPresenter presenter;


    private Button button;
 
 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);
 presenter = new MainPresenter(this, new MainUseCase()); presenter.onCreate();
 button = (Button) findViewById(R.id.button);
 button.setVisibility(View.INVISIBLE);
 button.setOnClickListener(v -> presenter.onButtonClick());
 presenter.loadButtonText();
 }
 
 public void setButtonText(String buttonText) {
 if (TextUtils.isEmpty(buttonText)) {
 button.setVisibility(View.INVISIBLE);
 } else {
 button.setText(buttonText);
 button.setVisibility(View.VISIBLE);
 }
 }
 }
  3. @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState); …
 presenter.loadButtonText();
 }


    
 public void setButtonText(String buttonText) {
 if (TextUtils.isEmpty(buttonText)) {
 button.setVisibility(View.INVISIBLE);
 } else {
 button.setText(buttonText);
 button.setVisibility(View.VISIBLE);
 }
 }
 } 7JFX͕1SFTFOUFSʹ ࢦࣔΛग़͍ͯ͠Δ 7JFXଆͰϩδοΫΛ ͍࣋ͬͯΔ
  4. public class MainPresenter {
 
 private MainActivity view;
 private MainUseCase

    useCase;
 
 public MainPresenter(MainView view, MainUseCase useCase) {
 this.view = view;
 this.useCase = useCase;
 }
 
 public void onCreate() { }
 
 public void onButtonClick() {
 view.startActivity(new Intent(view, SubActivity.class));
 }
 
 public void loadButtonText() {
 useCase.loadButtonText()
 .subscribe(s -> {
 view.setButtonText(s);
 }, throwable -> {
 });
 }
 }
  5. public class MainPresenter {
 
 private MainActivity view;
 private MainUseCase

    useCase;
 … 
 public void onButtonClick() {
 view.startActivity( new Intent(view,ɹSubActivity.class));
 }
 
 public void loadButtonText() {
 useCase.loadButtonText()
 .subscribe(s -> {
 view.setButtonText(s);
 }, throwable -> {
 });
 }
 } 7JFXΛ"DUJWJUZͱͯ͠ ௚઀͍࣋ͬͯΔ "DUJWJUZΛ1SFTFOUFS͕ ௚઀ૢ࡞͍ͯ͠Δ
  6. interface MainView {
 
 void startSubActivity();
 void showButton();
 void hideButton();


    void setButtonText(String s);
 
 class MainActivity extends AppCompatActivity implements MainView {
 
 private MainPresenter presenter;
 private Button button;
 
 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);
 button = (Button) findViewById(R.id.button);
 button.setOnClickListener(v -> presenter.onButtonClick());
 presenter = new MainPresenter(this, new MainUseCase()); presenter.onCreate();
 }
 
 @Override
 public void startSubActivity() {
 startActivity(new Intent(this, SubActivity.class));
 }
 
 @Override
 public void showButton() {
 button.setVisibility(View.INVISIBLE);
 }
 
 @Override
 public void hideButton() {
 button.setVisibility(View.INVISIBLE);
 }
 
 @Override
 public void setButtonText(String buttonText) {
 button.setText(buttonText);
 }
 }
 }
  7. interface MainView {
 
 void startSubActivity();
 void showButton();
 void hideButton();


    void setButtonText(String s);
 
 class MainActivity extends AppCompatActivity implements MainView {
 "DUJWJUZͷૢ࡞Λ *OUFSGBDFͱͯ͠ந৅Խ "DUJWJUZ͸7JFXΛ࣮૷
  8. protected void onCreate(Bundle savedInstanceState) { …
 presenter.onCreate();
 }
 
 @Override


    public void startSubActivity() {
 startActivity(new Intent(this, SubActivity.class));
 }
 
 @Override
 public void showButton() {
 button.setVisibility(View.VISIBLE);
 }
 
 @Override
 public void hideButton() {
 button.setVisibility(View.INVISIBLE);
 }
 
 @Override
 public void setButtonText(String buttonText) {
 button.setText(buttonText);
 } 7JFX͸1SFTFOUFSʹରͯ͠ ϥΠϑαΠΫϧͳͲͷ ΠϕϯτΛ౉͚ͩ͢ ϩδοΫ͸࣋ͨͣɺ ୹͍6*ૢ࡞Λ࣮ߦ͢Δ͚ͩͷ ϝιου܈Λ࣋ͭ
  9. public class MainPresenter {
 
 private MainView view;
 private MainUseCase

    useCase;
 
 public MainPresenter(MainView view, MainUseCase useCase) {
 this.view = view;
 this.useCase = useCase;
 }
 
 public void onCreate() {
 view.showButton();
 loadButtonText();
 }
 
 public void onButtonClick() {
 view.startSubActivity();
 }
 
 private void loadButtonText() {
 useCase.loadButtonText()
 .subscribe(s -> {
 if (TextUtils.isEmpty(s)) {
 view.hideButton();
 } else {
 view.showButton();
 view.setButtonText(s);
 }
 }, throwable -> {
 });
 }
 }
  10. public class MainPresenter {
 
 private MainView view;
 private MainUseCase

    useCase;
 …
 
 public void onCreate() {
 view.showButton();
 loadButtonText();
 }
 
 public void onButtonClick() {
 view.startSubActivity();
 }
 
 private void loadButtonText() {
 useCase.loadButtonText()
 .subscribe(s -> {
 if (TextUtils.isEmpty(s)) {
 view.hideButton();
 } else {
 view.showButton();
 view.setButtonText(s);
 }
 }, throwable -> {
 });
 }
 } ந৅Խͨ͠*OUFSGBDFͱͯ͠ 7JFXΛอ࣋͢Δ ॲཧͷྲྀΕ͸ΠϕϯτΛड͚ औͬͨ1SFTFOUFS੍͕ޚ͢Δ ௚઀తͳ6*ૢ࡞͸ WJFXͷ࣮૷ʹҠৡ͢Δ ϩδοΫ͸1SFTFOUFSଆͰ࣋ͪɺ ݁Ռͷࢦ͚ࣔͩΛ7JFXʹ౉͢
  11. @RunWith(RobolectricTestRunner.class)
 @Config(constants = BuildConfig.class)
 public class MainPresenterTest {
 
 @Rule


    public MockitoRule mockito = MockitoJUnit.rule();
 
 @Mock
 MainView viewMock;
 @Mock
 MainUseCase useCaseMock;
 @Spy
 @InjectMocks
 MainPresenter presenter;
 
 @Test
 public void onCreateTest() {
 when(useCaseMock.loadButtonText()).thenReturn(Single.just("test"));
 presenter.onCreate();
 verify(useCaseMock, times(1)).loadButtonText();
 verify(viewMock, times(2)).showButton();
 verify(viewMock, times(1)).setButtonText("test");
 }
 
 @Test
 public void buttonTextEmptyTest() {
 when(useCaseMock.loadButtonText()).thenReturn(Single.just(""));
 presenter.onCreate();
 verify(useCaseMock, times(1)).loadButtonText();
 verify(viewMock, times(1)).showButton();
 verify(viewMock, times(1)).hideButton();
 verify(viewMock, never()).setButtonText(anyString());
 }
 
 @Test
 public void onButtonClickTest() {
 when(useCaseMock.loadButtonText()).thenReturn(Single.just("test"));
 presenter.onCreate();
 presenter.onButtonClick();
 verify(viewMock, times(1)).startSubActivity();
 }
 }
  12. @RunWith(RobolectricTestRunner.class)
 @Config(constants = BuildConfig.class)
 public class MainPresenterTest {
 
 @Rule


    public MockitoRule mockito = MockitoJUnit.rule();
 
 @Mock
 MainView viewMock;
 @Mock
 MainUseCase useCaseMock;
 @Spy
 @InjectMocks
 MainPresenter presenter;
 
 !.PDLΞϊςʔγϣϯͰ ϞοΫΛ࡞੒ग़དྷΔ !*OKFDU.PDLTͰ !.PDLͷ஋Λ࢖ͬͯ ΠϯελϯεΛੜ੒ग़དྷΔ .PDLJUPͷΞϊςʔγϣϯΛ ࢖༻͢ΔͨΊͷ3VMF
  13. @Test
 public void onCreateTest() {
 when(useCaseMock.loadButtonText()).thenReturn(Single.just("test"));
 presenter.onCreate();
 verify(useCaseMock, times(1)).loadButtonText();
 verify(viewMock,

    times(2)).showButton();
 verify(viewMock, times(1)).setButtonText("test");
 }
 
 @Test
 public void buttonTextEmptyTest() {
 when(useCaseMock.loadButtonText()).thenReturn(Single.just(""));
 presenter.onCreate();
 verify(useCaseMock, times(1)).loadButtonText();
 verify(viewMock, times(1)).showButton();
 verify(viewMock, times(1)).hideButton();
 verify(viewMock, never()).setButtonText(anyString());
 }
 
 @Test
 public void onButtonClickTest() {
 when(useCaseMock.loadButtonText()).thenReturn(Single.just("test"));
 presenter.onCreate();
 presenter.onButtonClick();
 verify(viewMock, times(1)).startSubActivity();
 }
 }
  14. @Test
 public void onCreateTest() {
 when(useCaseMock.loadButtonText()).thenReturn(Single.just("test"));
 presenter.onCreate();
 verify(useCaseMock, times(1)).loadButtonText();
 verify(viewMock,

    times(2)).showButton();
 verify(viewMock, times(1)).setButtonText("test");
 }
 
 @Test
 public void buttonTextEmptyTest() {
 when(useCaseMock.loadButtonText()).thenReturn(Single.just(""));
 presenter.onCreate();
 verify(useCaseMock, times(1)).loadButtonText();
 verify(viewMock, times(1)).showButton();
 verify(viewMock, times(1)).hideButton();
 verify(viewMock, never()).setButtonText(anyString());
 }
 
 @Test
 public void onButtonClickTest() {
 when(useCaseMock.loadButtonText()).thenReturn(Single.just("test"));
 presenter.onCreate();
 presenter.onButtonClick();
 verify(viewMock, times(1)).startSubActivity();
 }
 } WFSJGZͰ7JFX΍6TF$BTFͷ ϝιου͕ظ଴௨Γʹ ݺ͹Ε͍ͯΔ͔Λςετ͢Δ .PDL͕ฦ͢஋Λม͑ɺ݁Ռݺ ͹ΕΔϝιου΋มΘ͍ͬͯΔ ͔Λςετ͢Δ ΫϦοΫΠϕϯτΛखಈͰ࠶ݱ ͠ɺ݁ՌΛςετ͢Δ