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

Sin refactor no hay paraíso

Sin refactor no hay paraíso

Todos hemos tenido que lidiar alguna vez con código legado, en Idealista, la app de Android tiene ya varios años y necesitaba un poco de cariño y mimos.

En esta charla contaremos las venturas y desventuras de cómo tratar con código legado, estrategias para no sufrir (tanto), y cómo darle abrazos y besos a tu proyecto para adaptar tu código a las nuevas necesidades.

Trabajaremos sobre Android, aunque muchas de las técnicas, estrategias y consejos son aplicables también para Java (incluso para otros lenguajes)

Avatar for Nicolás Patarino

Nicolás Patarino

February 09, 2017
Tweet

More Decks by Nicolás Patarino

Other Decks in Technology

Transcript

  1. #T3chFest2017 @npatarino • The harder to understand the code, the

    faster it decay • Duplicated code means duplicated changes • Code could run faster, but it takes days to understand • Your code is part of a bigger story Spaguetti code
  2. #T3chFest2017 @npatarino 7 What refactor is? Refactoring (noun): a change

    made to the internal structure of software to make it easier to understand and cheaper to modify without changing its observable behavior. Refactoring (verb): to restructure software by applying a series of refactorings without changing its observable behavior.
  3. #T3chFest2017 @npatarino 8 What refactor is? Refactoring (noun): a change

    made to the internal structure of software to make it easier to understand and cheaper to modify without changing its observable behavior. Refactoring (verb): to restructure software by applying a series of refactorings without changing its observable behavior.
  4. #T3chFest2017 @npatarino • Help the future developer, the future developer

    is going to be yourself • Refactor helps to understand unfamiliar code • You could find bugs. It clarifies assumptions that you’ve made • You get your patterns sense Why refactor?
  5. #T3chFest2017 @npatarino • They have done their best with their

    resources • Schedule Driven Development • At the time was other or no well formed architecture Respect the previous dev
  6. #T3chFest2017 @npatarino • They have done their best with their

    resources • Schedule Driven Development • At the time was other or no well formed architecture • Business grows faster than the app • Your current code will be legacy in a while • If there is no legacy, whom will you blame? Respect the previous dev
  7. #T3chFest2017 @npatarino • It’s OK if MVPs or beginning of

    the project Problems ◦ You’ll lose some know-how ◦ No time to response to a new cool competitor’s feature ◦ Migration old to new data ◦ It could fall down in spaghetti code again Rewrite
  8. #T3chFest2017 @npatarino Add Clean Architecture Presentation Layer Model View Presenter

    Domain Layer Java Objects Providers Data Layer Repository Pattern Java Objects Asynchronous Layer
  9. #T3chFest2017 @npatarino • Extract methods, classes • Replace types with

    polymorphism • Smell codes • Remove unnecessary external libraries • Immutability • ... Little refactors
  10. #T3chFest2017 @npatarino • Mutable objects are not thread-safe • Hard

    to parallelize • Inconsistent if you have exceptions • Not possible to cache objects • Side effects Mutability
  11. #T3chFest2017 @npatarino CommonFilter commonFilter = new CommonFilter(); commonFilter = new

    CommonFilter.Builder() .withTypology(commonFilter.getPropertyType()) .withWhere(commonFilter.getWhere()) .withOperation(Operation.rent()); filterManager.doSomething(commonFilter); Log.d(commonFilter.getOperation()); CommonFilter commonFilter = new CommonFilter(); commonFilter = commonFilter.with(Operation.rent()); filterManager.doSomething(commonFilter); Log.d(commonFilter.getOperation()); Mutability
  12. #T3chFest2017 @npatarino Problems • Difficulties to change libraries or implementations

    • Little changes were reflected into all project • Connascence Coupling
  13. #T3chFest2017 @npatarino private void addImageToView(ApiAd rowElement) { Log.d(TAG, "Maradona es

    más grande que Pelé"); textView.setText("Time: " + System.currentTimeMillis()) Picasso.with(context) .load(rowElement.getImageUrl()) .into(thumbnail); } Wrapping up
  14. #T3chFest2017 @npatarino public interface ImageLoader<T> { void load(T imageView, String

    url) ; } public interface Logger<T> { void d(String tag, String message) ; } public interface TimeProvider { long getCurrentTimeMillis() ; } Wrapping up
  15. #T3chFest2017 @npatarino public class PicassoImageLoader implements ImageLoader<ImageView> { private final

    Context context; public PicassoImageLoader(Context context) { this.context = context; } @Override public void load(ImageView imageView, String url) { Picasso.with(context).load(url).into(imageView); } } Wrapping up
  16. #T3chFest2017 @npatarino private void addImageToView(ApiAd rowElement) { Log.d(TAG, "Maradona es

    más grande que Pelé"); textView.setText("Time: " + System.currentTimeMillis()); Picasso.with(context) .load(rowElement.getImageUrl()) .into(thumbnail); } private void addImageToView(ApiAd rowElement) { logger.d(TAG, "Maradona es más grande que Pelé"); long currentTimeMillis = timeProvider.getCurrentTimeMillis(); textView.setText("Time: " + currentTimeMillis) imageLoader.load(thumbnail, rowElement.getImageUrl()); } Wrapping up
  17. #T3chFest2017 @npatarino public class GetTitleCommand extends Command<MoviesView> { private final

    GetTitlesUseCase useCase; public GetTitleCommand( MoviesView view, UseCaseProvider useCaseProvider, Presenter presenter ) { super(view); useCase = useCaseProvider.getGetTitle(); presenter.addCommand(this); } @Override public void ui(MoviesModel movies) { view.clearMovies(); view.addMovies(movies); } } Dependency injection
  18. #T3chFest2017 @npatarino • If we increase the complexity, we should

    reduce somewhere else • Extract method / variable / class • Remove “Roberto Carlos Code” Metrics To-Do(s)
  19. #T3chFest2017 @npatarino public int getCheckId(NewAdSecondStepField field) { for (int i

    = 0; i < field.getPossibleValues().size(); i++) { String value = (String) field.getPossibleValues().values().toArray()[i]; if (value =! null) { if (value.equals(field.getDefaultValue())) { return 100 + i; } } } return 100; } Roberto Carlos Code
  20. #T3chFest2017 @npatarino • If we increase the complexity, we should

    reduce somewhere else • Extract method / variable / class • Remove “Roberto Carlos Code” • SOLID, DRY (DIE), KISS, Patterns Metrics - To-Do(s)
  21. #T3chFest2017 @npatarino • Share Knowledge • Mentoring • Make consensus

    • Find bugs Important • Respect • Critique - Solution Code Review
  22. #T3chFest2017 @npatarino Draw Search, MV(S)P Drawing Live Search Polygon Ad

    Selected Actions • cancel() • buttonClicked() • selectAd()
  23. #T3chFest2017 @npatarino Draw Search, MV(S)P Drawing Live Search Polygon Ad

    Selected cancel() cancel() selectAd() selectAd() cancel() cancel() cancel() buttonClicked() buttonClicked()
  24. #T3chFest2017 @npatarino • Remove PropertyFilter • Remove PropertyFilter (Mikado method)

    • Reduce number of lines • Test less than we should It’s OK to fail
  25. #T3chFest2017 @npatarino • Little refactor • Strict with ourselves •

    Increase Automation • Think about big story • Test, test, test! (as less as possible to sleep well) • Innovate Because we’ve learned for everyday work
  26. #T3chFest2017 @npatarino {api} Fran Pulido @FranPulidoM Victor de Francisco @vicdefran

    Jose del Pozo @Josedlpozo Kike Fau @KikeFau Miguel Olmedo @molmedoc Javier Aznar @JavierAznar1 Dani Jiménez @danibto Salvador Labajos @SalvatoreLabs
  27. #T3chFest2017 @npatarino You don’t need to be an excellent programmer.

    You need to be a good programmer with excellent habits.