Diese Präsentation wurde erfolgreich gemeldet.
Wir verwenden Ihre LinkedIn Profilangaben und Informationen zu Ihren Aktivitäten, um Anzeigen zu personalisieren und Ihnen relevantere Inhalte anzuzeigen. Sie können Ihre Anzeigeneinstellungen jederzeit ändern.

Y U NO CRAFTSMAN

Releasing a great app is more than having a unique idea. It takes teamwork, collaboration and the will to be the best. At Novoda we make awesomeness happen. This talk is about our process from coding dojos to group design and iterative sprint planning with our customers. We'll describe some of our best practices as well as some of the components that can make a good app great.

This includes:
- Day-to-day processes: pairing tennis, gif code reviews and toggling hidden features.
- Work Environment: hack & tells, continuous communication & kicking ass at Tekken.
- Releasing the app: polishing & quantifying can get you top of the class and not listening to Google can get you expelled.

Finishing with some bonus Android coding tips and tricks and crazy AOSP anti-patterns.

  • Loggen Sie sich ein, um Kommentare anzuzeigen.

Y U NO CRAFTSMAN

  1. 1. Y U NO CRAFTSMAN Xavi Rigau & Paul Blundell
  2. 2. Who? @blundell_apps @xrigau
  3. 3. Competition Tweet something about the talk with the hashtags #droidconAE #YUNOCRAFTSMAN
  4. 4. What is craftsmanship? craftsmanship ˈkrɑːf(t)smənʃɪp/ the quality of design and work shown in something
  5. 5. Coder vs Craftsman “Make a chair”
  6. 6. We’re gonna talk about... - Improving day to day craftsmanship - Creating a positive working environment - The final few steps to awesomeness - Opinionated bonus material
  7. 7. Improving day to day craftsmanship
  8. 8. Whiteboard ideation
  9. 9. Brainstorming session
  10. 10. Help non dev team members
  11. 11. Pair programming
  12. 12. Pairing tennis
  13. 13. Driver & Navigator pairing Mistakes Driver Would make Mistakes Navigator Would make Actual Mistakes
  14. 14. Best coding practices
  15. 15. Code reviews
  16. 16. Selfies & Gifs https://github.com/thieman/github-selfies
  17. 17. Caring about the CI
  18. 18. Static analysis reports
  19. 19. CI Game #rekt
  20. 20. Pull Request Builder
  21. 21. Be “agile” build features the way that makes sense
  22. 22. YAGNI Overengineering You Ain’t Gonna Need It GSD
  23. 23. Pragmatism
  24. 24. Creating a positive working environment
  25. 25. Continuous communication
  26. 26. Morning standups
  27. 27. Daily news
  28. 28. Hack & Tells
  29. 29. Dojos
  30. 30. Zero walls office
  31. 31. 2 keyboards 2 mice per desk
  32. 32. Standing desks
  33. 33. Remote working
  34. 34. Remote working
  35. 35. CI Alarm
  36. 36. Xbox downtime
  37. 37. Social / Pub!
  38. 38. Hire the best (for you)
  39. 39. The final steps to awesomeness
  40. 40. That extra 5%
  41. 41. Optimise & leave the main thread alone
  42. 42. Strict Mode private void initializeStrictMode() { if (BuildConfig.DEBUG) { ThreadPolicy threadPolicy = new ThreadPolicy.Builder() .detectAll() .penaltyLog() .penaltyDeath() .build(); StrictMode.setThreadPolicy(threadPolicy); VmPolicy vmPolicy = new VmPolicy.Builder() .detectAll() .penaltyLog() .penaltyDeath() .build(); StrictMode.setVmPolicy(vmPolicy); } }
  43. 43. GPU Profiling
  44. 44. Show Overdraw
  45. 45. Polish the app
  46. 46. Animate all the things
  47. 47. User features - Second screen / Chromecast / TV - Widget - Wear - Daydream - LiveWallpaper
  48. 48. Behind the scenes - Content provider - Sync Adapter - Deep linking / Web search deep linking - Voice commands
  49. 49. Listen for feedback
  50. 50. Measure the data
  51. 51. Follow the guidelines
  52. 52. What happens when you don’t follow the guidelines
  53. 53. Opinionated Bonus
  54. 54. The dark side of AOSP try { mWallpaper = getCurrentWallpaperLocked(context); } catch (OutOfMemoryError e) { Log.w(TAG, "No memory load current wallpaper", e); } try { BitmapFactory.Options options =new BitmapFactory.Options(); return BitmapFactory.decodeStream(is, null, options); } catch (OutOfMemoryError e) { Log.w(TAG, "Can't decode stream", e); } https://android.googlesource.com in WallpaperManager.java - line 263
  55. 55. Follow the examples - but not too closely
  56. 56. minSdkVersion 16 For more info: https://developer.android.com/about/dashboards/index.html
  57. 57. Activity lifecycle callbacks public interface ActivityLifecycleCallbacks { void onActivityCreated(Activity activity, Bundle savedInstanceState); void onActivityStarted(Activity activity); void onActivityResumed(Activity activity); void onActivityPaused(Activity activity); void onActivityStopped(Activity activity); void onActivityDestroyed(Activity activity); void onActivitySaveInstanceState(Activity activity, Bundle outState); } public class MyActivityLifecycleCallbacks implements Application.ActivityLifecycleCallbacks { … } public class MyApplication extends Application { @Override public void onCreate() { super.onCreate(); registerActivityLifecycleCallbacks(new MyActivityLifecycleCallbacks()); } }
  58. 58. Fail Gracefully! Do not crash out there public class ReportingUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler { @Override public void uncaughtException(Thread thread, Throwable ex) { // Do necessary crash handling crashlytics.reportCrash("user crash captured", ex); } } private void swallowExceptionsInRelease() { if (!BuildConfig.DEBUG) { Thread.UncaughtExceptionHandler handler = new ReportingUncaughtExceptionHandler(); Thread.currentThread().setUncaughtExceptionHandler(handler); } } Not recommended to use on your main thread
  59. 59. newInstance all the things! public class WidgetImageLoader { private final Retriever memoryRetriever; private final Retriever fileRetriever; public static WidgetImageLoader newInstance(Context context) { Retriever memoryRetriever = MemoryRetriever.getInstance(); Retriever fileRetriever = FileRetriever.newInstance(context); return new WidgetImageLoader(memoryRetriever, fileRetriever); } WidgetImageLoader(Retriever memoryRetriever, Retriever fileRetriever) { this.memoryRetriever = memoryRetriever; this.fileRetriever = fileRetriever; } }
  60. 60. Robolectric is dead Long live the JVM
  61. 61. In summary
  62. 62. Questions? ‫األسئلة‬‫؟‬ #droidconAE #YUNOCRAFTSMAN @blundell_apps
  63. 63. Competition Winner
  64. 64. We are hiring Liverpool, London, Barcelona, Berlin & New York info@novoda.com
  65. 65. References & Attributions novoda.com karenknowsbest.com experttek.co.uk memegenerator giphy.com cloudfront.net wandisco.com electronicproducts.com alistair.cockburn.us deadzebra.com dribble.com Jovie Brett smosh.com Dilbert developer.android.com gradle.org failauthority.com hilariousgifs.com spin.atomicobject.com

×