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)

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.